最近在学习SpringBoot响应式编程,所以在自己捣鼓的项目中使用了web reactive,r2dbc等响应式技术
因为是微服务项目,所以首先就想到了使用注册中心和配置中心,这里我选择了Nacos
Nacos下载与使用
Nacos下载地址
下载完成之后,解压文件,先别着急启动,先进入conf文件夹修改application.properties
首先是环境变量中配置好JAVA_HOME,这是最基础的一步
然后正式开始Nacos的配置,这里参考Nacos官方文档
这里主要讲一下Nacos的鉴权
在nacos\conf\application.properties中,默认是关闭鉴权的
nacos.core.auth.enabled=false
如果需要开启鉴权,需要修改成
nacos.core.auth.system.type=nacos
nacos.core.auth.enabled=true
其次就是自定义密钥,2.2.1版本之后,Nacos官方移除了该配置的默认值,在使用时需自己填充,否则无法启动节点,Nacos官方推荐使用Base64编码的字符串,我这里使用的密钥是官方示例的,切勿用于实际部署!!!
nacos.core.auth.default.token.secret.key=VGhpc0lzTXlDdXN0b21TZWNyZXRLZXkwMTIzNDU2Nzg=
若开启鉴权,项目中需要在application.yml中配置如下信息,若没有开启则无需额外配置即可使用
spring:
cloud:
nacos:
discovery:
username: nacos
password: nacos
最后就是Nacos集群之间的鉴权
### 开启鉴权
nacos.core.auth.enabled=true
### 关闭使用user-agent判断服务端请求并放行鉴权的功能
nacos.core.auth.enable.userAgentAuthWhite=false
### 配置自定义身份识别的key(不可为空)和value(不可为空)
nacos.core.auth.server.identity.key=example
nacos.core.auth.server.identity.value=example
需要说明的是,如果开启集权鉴权,需要所有Nacos服务节点的server.identity相同,否则可能导致服务端之间数据不一致或无法删除实例等问题
SpringCloud项目集成Nacos做注册中心和配置中心
我这里采用了比较新的SpringBoot3.0.0和SpringCloud2022.0.0:依赖版本对应关系
所以整个版本的对应关系为:SpringBoot3.0.0,SpringCloud2022.0.0,SpringCloudAlibaba2022.0.0.0-RC1
所以在父pom中,配置parent信息
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.0.0</version>
</parent>
配置dependencyManagement
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2022.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2022.0.0.0-RC1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
到这里,父pom就算配置完成了
创建微服务module,测试是否能注册到Nacos
在子pom中引入需要依赖的包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-rsocket</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
编写application.yml
spring:
cloud:
nacos:
config:
prefix: webflux
file-extension: yaml
server-addr: 127.0.0.1:8848
discovery:
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
loadbalancer:
ribbon:
enabled: false
config:
import: nacos:webflux.yaml
application:
name: webfluxone
server:
port: 8887
启动Ncos
startup.cmd -m standalone
Nacos配置管理中的配置

因为这里还没有讲r2dbc,所以不做过多的说明
需要注意的是SpringCloud2022.0.0,需要添加一个叫spring.config.import=nacos:xxx.yaml的配置,原因是因为该版本的SpringCloud默认不支持bootstrap.yml
其他配置说明:
spring.cloud.nacos.config.prefix和spring.cloud.nacos.config.file-extension:需要对应Nacos中配置管理的dataId,具体规则为:prefix-spring.profiles.active.file-extension(这点官方有很好的说明),如不配置spring.profiles.active,则为:prefix.file-extension,我这里的配置对应的配置管理的配置就是webflux.yaml

做好上述配置之后,我们就可以启动该服务了

可以看到,服务已经成功监听到了webflux.yaml,成功!

并且服务也成功注册到Nacos
使用WebClient实现服务调用
既然是服务调用,那至少需要两个微服务,另一个微服务和上述一致,只需改个端口,这里就不演示了
先定义测试需要的接口
@GetMapping("/hello/{name}")
public Mono<String> hello(@PathVariable String name){
return Mono.just("Hello, " + name);
}
这是服务的被调用方,Nacos中的服务名称是webfluxtwo,Mono和Flux是spring reactive编程中两个重要的对象,一系列流操作都需要基于这两个对象,并且在webflux中,返回值需要是Mono或者Flux类型的,其中Mono是返回0或者1个对象,Flux是返回多个对象
然后在调用方做如下配置
@Configuration
public class WebClientConfiguration {
@Bean
public WebClient webClient(ReactorLoadBalancerExchangeFilterFunction function){
return WebClient.builder().filter(function).build();
}
}
配置完成之后,在需要的地方注入
@Autowired
WebClient webClient;
然后编写调用者接口
@GetMapping("/hello/{name}")
public Mono<String> hello(@PathVariable String name){
return webClient.get().uri("http://webfluxtwo/hello/{name}", name)
.retrieve().bodyToMono(String.class);
}
到这里就全部完成了,可以进行测试了,我们启动两个微服务
然后访问调用者对外提供的接口

可以看到,完全是没问题的
最后,如果本文对你有帮助的话麻烦点个赞,因为是新学的技术,我也不是完全能搞懂,如果有人指出问题我会进行修改的
