二、SpringCloud Alibaba之nacos
2.1、环境搭建
https://github.com/alibaba/spring-cloud-alibaba 中的wiki
在spring的官网中也有spring cloud alibaba:https://spring.io/projects/spring-cloud-alibaba
2.1.1、分支版本
分支版本地址:https://sca.aliyun.com/zh-cn/docs/next/overview/version-explain
Spring Cloud Alibaba Version | Spring Cloud Version | Spring Boot Version |
---|---|---|
2.2.8.RELEASE* | Spring Cloud Hoxton.SR12 | 2.3.12.RELEASE |
2.2.7.RELEASE | Spring Cloud Hoxton.SR12 | 2.3.12.RELEASE |
2.2.6.RELEASE | Spring Cloud Hoxton.SR9 | 2.3.2.RELEASE |
2.1.4.RELEASE | Spring Cloud Greenwich.SR6 | 2.1.13.RELEASE |
2.2.1.RELEASE | Spring Cloud Hoxton.SR3 | 2.2.5.RELEASE |
2.2.0.RELEASE | Spring Cloud Hoxton.RELEASE | 2.2.X.RELEASE |
2.1.2.RELEASE | Spring Cloud Greenwich | 2.1.X.RELEASE |
2.0.4.RELEASE(停止维护,建议升级) | Spring Cloud Finchley | 2.0.X.RELEASE |
1.5.1.RELEASE(停止维护,建议升级) | Spring Cloud Edgware | 1.5.X.RELEASE |
2.1.2、组件版本关系
其实spring cloud Alibaba依赖也是版本管理器,点击进去会发现这个依赖管理里面管理者nacos、rocketMQ、gateway、seata等组件的版本。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
每个 Spring Cloud Alibaba 版本及其自身所适配的各组件对应版本如下表所示:
Spring Cloud Alibaba Version | Sentinel Version | Nacos Version | RocketMQ Version | Dubbo Version | Seata Version |
---|---|---|---|---|---|
2.2.8.RELEASE | 1.8.4 | 2.1.0 | 4.9.3 | ~ | 1.5.1 |
2021.0.1.0 | 1.8.3 | 1.4.2 | 4.9.2 | ~ | 1.4.2 |
2.2.7.RELEASE | 1.8.1 | 2.0.3 | 4.6.1 | 2.7.13 | 1.3.0 |
2.2.6.RELEASE | 1.8.1 | 1.4.2 | 4.4.0 | 2.7.8 | 1.3.0 |
2021.1 or 2.2.5.RELEASE or 2.1.4.RELEASE or 2.0.4.RELEASE | 1.8.0 | 1.4.1 | 4.4.0 | 2.7.8 | 1.3.0 |
2.2.3.RELEASE or 2.1.3.RELEASE or 2.0.3.RELEASE | 1.8.0 | 1.3.3 | 4.4.0 | 2.7.8 | 1.3.0 |
2.2.1.RELEASE or 2.1.2.RELEASE or 2.0.2.RELEASE | 1.7.1 | 1.2.1 | 4.4.0 | 2.7.6 | 1.2.0 |
2.2.0.RELEASE | 1.7.1 | 1.1.4 | 4.4.0 | 2.7.4.1 | 1.0.0 |
2.1.1.RELEASE or 2.0.1.RELEASE or 1.5.1.RELEASE | 1.7.0 | 1.1.4 | 4.4.0 | 2.7.3 | 0.9.0 |
2.1.0.RELEASE or 2.0.0.RELEASE or 1.5.0.RELEASE | 1.6.3 | 1.1.1 | 4.4.0 | 2.7.3 | 0.7.1 |
2.1.3、springcloud父类pom文件
在maven中的pom.xml文件中,只允许出现一个<parent>
标签,在项目中<parent>
是用来引用springboot版本管理中心的。如果需要添加别的父依赖,可以在<dependencyManagement>
标签中使用<dependency>
标签来实现。
<dependencyManagement>
<dependencies>
<!--springcloud alibaba的版本管理中心,通过dependency完成继承。
springboot的版本管理中心也可以通过这种方式继承-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.1.4、完整的父pom文件
搭建环境最重要的一步就是确定好springboot、springcloud、springcloud alibaba三个框架的版本。
这些版本对照可以在springcloud alibaba的官网找到:https://sca.aliyun.com/zh-cn/docs/next/overview/version-explain
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.java.coder</groupId>
<artifactId>spring-cloud</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>spring-cloud-order</module>
<module>spring-cloud-stock</module>
</modules>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring.boot.version>2.3.2.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR9</spring.cloud.version>
<spring.cloud.alibaba.version>2.2.6.RELEASE</spring.cloud.alibaba.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!--springboot的版本管理-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--springcloud alibaba的版本管理中心,通过dependency完成继承,
springboot的版本管理中心也可以通过这种方式继承-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version> ${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--springcloud的版本管理-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.6.3</version>
</plugin>
</plugins>
</build>
</project>
2.1.5、spring cloud alibaba搭建快速向导
2.2.1、nacos简介
nacos定义:一个更易于构建云原生应用的动态服务发现、服务配置和服务管理平台。(+配置中心+服务管理)
服务注册:Nacos Client会通过发送REST请求的方式向Nacos Server注册自己的服务,提供自身的元数据,比如ip地址、端口等信息。Nacos Server接收到注册请求后,就会把这些元数据信息存储在一个双层的内存Map中。
服务心跳:在服务注册后,Nacos Client会维护一个定时心跳来持续通知Nacos Server,说明服务一直处于可用状态,防止被剔除。默认5s发送一次心跳。
服务同步:Nacos Server集群之间会互相同步服务实例,用来保证服务信息的一致性。 leader raft
服务发现:服务消费者(Nacos Client)在调用服务提供者的服务时,会发送一个REST请求给Nacos Server,获取上面注册的服务清单,并且缓存在Nacos Client本地,同时会在Nacos Client本地开启一个定时任务定时拉取服务端最新的注册表信息更新到本地缓存
服务健康检查:Nacos Server会开启一个定时任务用来检查注册服务实例的健康情况,对于超过15s没有收到客户端心跳的实例会将它的healthy属性置为false(客户端服务发现时不会发现),如果某个实例超过30秒没有收到心跳,直接剔除该实例(被剔除的实例如果恢复发送心跳则会重新注册)
刚开始时服务之间通过ip:port
的方式直接调用
2.2.3、nacos的下载
下载地址:
windows环境下nacos server
2.2.4、启动模式修改成单例
2.2.5、nacos与springcloud alibaba的版本关系
根据spring cloud alibaba的版本,选择响应的nacos版本
Spring Cloud Alibaba Version | Sentinel Version | Nacos Version | RocketMQ Version | Dubbo Version | Seata Version |
---|---|---|---|---|---|
2.2.8.RELEASE | 1.8.4 | 2.1.0 | 4.9.3 | ~ | 1.5.1 |
2021.0.1.0 | 1.8.3 | 1.4.2 | 4.9.2 | ~ | 1.4.2 |
2.2.7.RELEASE | 1.8.1 | 2.0.3 | 4.6.1 | 2.7.13 | 1.3.0 |
2.2.6.RELEASE | 1.8.1 | 1.4.2 | 4.4.0 | 2.7.8 | 1.3.0 |
2021.1 or 2.2.5.RELEASE or 2.1.4.RELEASE or 2.0.4.RELEASE | 1.8.0 | 1.4.1 | 4.4.0 | 2.7.8 | 1.3.0 |
2.2.3.RELEASE or 2.1.3.RELEASE or 2.0.3.RELEASE | 1.8.0 | 1.3.3 | 4.4.0 | 2.7.8 | 1.3.0 |
2.2.1.RELEASE or 2.1.2.RELEASE or 2.0.2.RELEASE | 1.7.1 | 1.2.1 | 4.4.0 | 2.7.6 | 1.2.0 |
2.2.0.RELEASE | 1.7.1 | 1.1.4 | 4.4.0 | 2.7.4.1 | 1.0.0 |
2.1.1.RELEASE or 2.0.1.RELEASE or 1.5.1.RELEASE | 1.7.0 | 1.1.4 | 4.4.0 | 2.7.3 | 0.9.0 |
2.1.0.RELEASE or 2.0.0.RELEASE or 1.5.0.RELEASE | 1.6.3 | 1.1.1 | 4.4.0 | 2.7.3 |
2.2.6、nacos server 依赖
在父类的pom文件中引入spring cloud alibaba
的依赖以及spring cloud
的依赖
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring.boot.version>2.3.2.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR9</spring.cloud.version>
<spring.cloud.alibaba.version>2.2.6.RELEASE</spring.cloud.alibaba.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!--springboot的版本管理-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--springcloud alibaba的版本管理中心,通过dependency完成继承,
springboot的版本管理中心也可以通过这种方式继承-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version> ${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--springcloud的版本管理-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.6.3</version>
</plugin>
</plugins>
</build>
注册中心
<!--必须加入web应用才能注册到nacos中-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--nacos的注册与发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
配置中心
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2.2.7、注册服务到nacos服务器
在子模块的.properties文件中配置nacos的配置信息
order-service
server.port=8081
# 应用名称(nacos会把应用名称作为服务名称)
spring.application.name=order-service
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=123456
#命名空间id
spring.cloud.nacos.discovery.namespace=495e2ede-c37a-4258-8e11-72f21b0cf1cd
#分组信息
spring.cloud.nacos.discovery.group=java-coder
server.port=8083
# 应用名称(nacos会把应用名称作为服务名称)
spring.application.name=stock-service
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=123456
#命名空间id
spring.cloud.nacos.discovery.namespace=495e2ede-c37a-4258-8e11-72f21b0cf1cd
#分组信息
spring.cloud.nacos.discovery.group=java-coder
如果springcloud版本比较低,在启动程序那里需要添加一个@EnableDiscoveryClient
注解
stock-service的启动类
package com.java.coder.stock;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
public class StockApplication {
public static void main(String[] args) {
SpringApplication springApplication=new SpringApplication();
springApplication.run(StockApplication.class,args);
}
/**
* 注入 RestTemplate
* @param builder
* @return
*/
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder){
RestTemplate restTemplate=builder.build();
return restTemplate;
}
}
order-service的启动类
package com.java.coder.order;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication springApplication=new SpringApplication();
springApplication.run(OrderApplication.class,args);
}
/**
* 注入 RestTemplate
* @param builder
* @return
*/
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder){
RestTemplate restTemplate=builder.build();
return restTemplate;
}
}
服务之间调用
ip:port
方式调用的
注册中心
之后,服务的调用可以通过服务名
客户端通过负载均衡器进行调用的,因此需要把RestTemplate的Bean示例托管给负载均衡器管理。需要在注册RestTemplate时,在注册方法上加上@LoadBalanced
/**
* 注入 RestTemplate
* @param builder
* @return
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder builder){
RestTemplate restTemplate=builder.build();
return restTemplate;
}
默认的负载均衡器
消费者服务通过生产者服务的名称可以访问到生产者。那么默认的负载均衡策略时什么呢?
首先修改生产者代码,同一个服务不同示例端口不一样。
@RestController
@RequestMapping("/stock")
public class StockServiceController {
@Value("${server.port}")
private String port;
@RequestMapping("/getStock")
public String addOrder(){
return "getStock:"+port;
}
}
生产者
把生产者的第二个实例再idea中的名称改成StockApplication_8083, 占用的端口改成8083
启动服务后,nacos注册中心情况如下:
日志分析
2023-06-03 09:51:03.481 INFO 9676 --- [nio-8081-exec-1] c.n.l.DynamicServerListLoadBalancer:
#客户端stock-service的DynamicServerListLoadBalancer已初始化
DynamicServerListLoadBalancer for client stock-service initialized:
DynamicServerListLoadBalancer:
{
#NFLoadBalancer的配置情况
NFLoadBalancer:name=stock-service,current list of Servers=[169.254.206.80:8082,169.254.206.80:8083],Load balancer stats=Zone
# 状态情况
stats: {unknown=[Zone:unknown; Instance count:2; Active connections count: 0; Circuit breaker tripped count: 0; Active connections per server: 0.0;]
},
#服务情况
Server stats:
#第一个实例的情况
[[Server:169.254.206.80:8082; Zone:UNKNOWN; Total Requests:0; Successive connection failure:0; Total blackout seconds:0; Last connection made:Thu Jan 01 08:00:00 CST 1970; First connection made: Thu Jan 01 08:00:00 CST 1970; Active Connections:0; total failure count in last (1000) msecs:0; average resp time:0.0; 90 percentile resp time:0.0; 95 percentile resp time:0.0; min resp time:0.0; max resp time:0.0; stddev resp time:0.0],
#第二个实例的情况
[Server:169.254.206.80:8083; Zone:UNKNOWN; Total Requests:0; Successive connection failure:0; Total blackout seconds:0; Last connection made:Thu Jan 01 08:00:00 CST 1970; First connection made: Thu Jan 01 08:00:00 CST 1970; Active Connections:0; total failure count in last (1000) msecs:0; average resp time:0.0; 90 percentile resp time:0.0; 95 percentile resp time:0.0; min resp time:0.0; max resp time:0.0; stddev resp time:0.0]
]
}ServerList:com.alibaba.cloud.nacos.ribbon.NacosServerList@16cc3180
更多关于 spring-cloud-starter-alibaba-nacos-discovery 的 starter 配置项如下所示:
key | 默认值 | 说明 | |
---|---|---|---|
服务端地址 | spring.cloud.nacos.discovery.server-addr | 无 | Nacos Server 启动监听的ip地址和端口 |
服务名 | spring.cloud.nacos.discovery.service | ${spring.application.name} | 给当前的服务命名 |
服务分组 | spring.cloud.nacos.discovery.group | DEFAULT_GROUP | 设置服务所处的分组 |
权重 | spring.cloud.nacos.discovery.weight | 1 | 取值范围 1 到 100,数值越大,权重越大 |
网卡名 | spring.cloud.nacos.discovery.network-interface | 无 | 当IP未配置时,注册的IP为此网卡所对应的IP地址,如果此项也未配置,则默认取第一块网卡的地址 |
注册的IP地址 | spring.cloud.nacos.discovery.ip | 无 | 优先级最高 |
注册的端口 | spring.cloud.nacos.discovery.port | -1 | 默认情况下不用配置,会自动探测 |
命名空间 | spring.cloud.nacos.discovery.namespace | 无 | 常用场景之一是不同环境的注册的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。 |
AccessKey | spring.cloud.nacos.discovery.access-key | 无 | 当要上阿里云时,阿里云上面的一个云账号名 |
SecretKey | spring.cloud.nacos.discovery.secret-key | 无 | 当要上阿里云时,阿里云上面的一个云账号密码 |
Metadata | spring.cloud.nacos.discovery.metadata | 无 | 使用Map格式配置,用户可以根据自己的需要自定义一些和服务相关的元数据信息 |
日志文件名 | spring.cloud.nacos.discovery.log-name | 无 | |
集群 | spring.cloud.nacos.discovery.cluster-name | DEFAULT | 配置成Nacos集群名称 |
接入点 | spring.cloud.nacos.discovery.enpoint | UTF-8 | 地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址 |
是否集成Ribbon | ribbon.nacos.enabled | true | 一般都设置成true即可 |
是否开启Nacos Watch | spring.cloud.nacos.discovery.watch.enabled | true |
2.2.9、nacos管理页面
通过浏览器访问: http://169.254.206.80:8848/nacos/index.html
默认的密码用户名和密码都是nacos
服务列表
在服务列表中可以查询注册到nacos服务器的服务。
一般建议 用命名空间来区分工作生产、测试、开发等环境。 用分组来区分项目
命名空间
nacos默认注册到public命名空间,public命名空间是保留命名空间,有时候命名空间需要进行区分,可以新建命名空间,如果服务中要注册到相应的命名空间。
首先在命名空间这里创建一个新的命名空间prod
。
然后在application.properties
配置文件中配置spring.cloud.nacos.discovery.namespace
,把这个值配置成命名空间的id