近期在补充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 后还是发生了很多变更的,且官方文档还没更新,需要多注意呀!