近期在补充Spring Cloud知识,Nacos 可以做服务发现与注册,还可以做配置中心。那就启航,扬帆!
组件版本说明
因去年 Log4j 2 的漏洞问题在SpringBoot 2.6.2之后的版本中已经更新成最新的版本修复了问题,所以本次实验索性就用最新的版本做实验。
1. Spring Boot:2.6.4
2. Spring Cloud: 2021.0.1
3. Spring Cloud Alibaba: 2021.0.1.0
注:Spring Cloud在2020版本以后都以年号作为大版本号, Alibaba也同时修改版本号规则,和Spring Cloud保持一致,以Spring Cloud版本加以为小版本号作为自己的版本号。
Nacos 服务端程序部署
这一步还是挺简单的,参照官方样例即可:
1. 预备环境准备
Nacos 依赖 Java 环境来运行。如果您是从代码开始构建并运行Nacos,还需要为此配置 Maven环境,请确保是在以下版本环境中安装使用:
64 bit OS,支持 Linux/Unix/Mac/Windows,推荐选用 Linux/Unix/Mac。
64 bit JDK 1.8+;下载 & 配置。
Maven 3.2.x+;下载 & 配置。
2. 下载源码或者安装包
你可以通过源码和发行包两种方式来获取 Nacos。
从 Github 上下载源码方式
git clone https://github.com/alibaba/nacos.git
cd nacos/
mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U
ls -al distribution/target/
// change the $version to your actual path
cd distribution/target/nacos-server-$version/nacos/bin
下载编译后压缩包方式
您可以从 最新稳定版本 下载 nacos-server-$version.zip 包。
unzip nacos-server-$version.zip 或者 tar -xvf nacos-server-$version.tar.gz
cd nacos/bin
3. 启动服务器
Linux/Unix/Mac
启动命令(standalone代表着单机模式运行,非集群模式):
sh startup.sh -m standalone
如果您使用的是ubuntu系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行:
bash startup.sh -m standalone
Windows
启动命令(standalone代表着单机模式运行,非集群模式):
startup.cmd -m standalone
启动之后在浏览器中输入地址 http://127.0.0.1:8848/nacos 出现登录界面就是启动成功了,用户名与密码都是 nacos
Nacos 之服务发现与注册
1. 添加依赖,不过由于为了保证整个SpringCloud引用不发生冲突,建议先在POM里面配置好相关的 dependencyManagement
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2. 写配置
application.yaml:
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
application:
name: user-service
3. 加注解
在 XXXApplication.java 入口类上加上 @EnableDiscoveryClient
@SpringBootApplicatio
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
4. 写业务逻辑
按官网描述,Nacos中自带了Robbin做负载均衡,那挺好不用再做额外的引用,走起!
添加配置类,将RestTemplate注入到Spring IOC中:
@Configuration
public class LoadBalancorConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
注意:要添加@LoadBalanced注解
调用处直接使用RestTemplate发送请求调用服务
@Autowired
public RestTemplate restTemplate;
public String index() {
return restTemplate.getForObject("http://order-service/query", String.class);
}
注:此处order-service并非是一个真实的域名,它是我们实际想要访问的服务名,即对应服务中yaml定义的 spring.application.name 的值,LoadBalancer会自行解析,根据服务名在Nacos中查询所以此服务的注册实例,并将其返回,再根据轮询或者随机算法读取实际需要访问的服务器路径。(默认为轮询算法)
重点来了!!! 此前都还是按照官方示例进行演练,我们将它运行起来,调用接口!最终结果是无法访问此接口,后台报错了!!!
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://order-service/query": order-service; nested exception is java.net.UnknownHostException: order-service] with root cause
java.net.UnknownHostException: order-service
意思是说路径中的order-service无法解析,怎么可能,不是包含有Robbin组件吗?
再看看maven中的关联依赖:
咦?怎么没有了?
经过各种baidu google,终于发现原来Robbin进入了维护版本,且 Robbin 2 与 1 之间有很大的版本区别,SpringCloudAlibaba在2020版本中将Robbin的引用去掉了。 且SpringCloud 在2020版本中推出了自己官方的负载均衡器。
ok,那我们重新添加引用吧:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
spring cloud loadbalancer 使用方法与Robbin基本一致。
OK问题解决
Nacos 之配置中心
1. 添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2. 写配置
由于 nacos-config在注入到Spring中时,会在application.yaml配置文件加载之前,如果将配置信息写到application.ymal中则无法找到配置信息,无法将配置中心服务正确加载到项目中。所以SpringCloud添加了一个bootstrap.yaml配置文件,此配置文件优先于application.yaml加载。
好吧,我们新建一个配置文件,添加配置内容:
bootstrap.yaml:
spring:
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
application:
name: user-service
然后在Nacos控制台中添加配置文件:
Data Id 填写bootstrap.yaml中的 application name
3. 写注解
在读取配置文件的类上,添加@RefreshScope注解,使配置中心中配置发生变动的时候自动更新配置文件。
4. 写业务代码
我们在此处使用Spring的@Value进行测试是否将配置文件加载到变量中,看是否能够读取到配置信息。
@Value("${person.name}")
public String name;
public String readConfig() {
return name;
}
啊哦! 又报错了,说 person.name 这个配置找不到无法注入...
难道配置写的不对? 经过多次比对发现所有配置都正常,到底是为什么呢?
此时突发奇想,我们来读取一下bootstrap.ymal中的配置看是否能够正常读取。
@Value("${spring.cloud.nacos.config.server-addr}")
public String conf;
测试结果:好吧,这个本地配置也读不出来。
经过一番baidu google,发现SpringCloud 2020版以后bootstrap配置文件需要额外添加一个引用才可以使用,ok,那我们添加引用吧。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
添加后,正常运行!
注:远端的配置信息会覆盖本地的配置文件哦!
结论
Spring Cloud 2020 后还是发生了很多变更的,且官方文档还没更新,需要多注意呀!