1. SpringCloud Alibaba基础框架搭建
1.1 创建maven项目
打开Idea,File->New->Maven
1.2 修改pom.xml内容
创建完成后,修改一下pom.xml文件内容,效果如下 :
pom.xml内容 :
<?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>tm.learn</groupId>
<artifactId>TM-Learn-SpringCloud-Alibaba</artifactId>
<version>1.0-SNAPSHOT</version>
<name>TM-Learn-SpringCloud-Alibaba</name>
<packaging>pom</packaging>
<description>TM-Learn-SpringCloud-Alibaba</description>
<properties>
<spring.boot.version>2.6.3</spring.boot.version>
<spring.cloud.dependencies.version>2021.0.1</spring.cloud.dependencies.version>
<spring.cloud.alibaba.version>2021.0.1.0</spring.cloud.alibaba.version>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<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>
</dependencies>
</dependencyManagement>
</project>
1.3 添加.gitignore文件
# Compiled class file
*.class
target
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar
*.iml
.idea
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
2. 创建 tm-springcloud-alibaba-common 模块
在根项目名称上右键 New->Module 创建 tm-springcloud-alibaba-common 模块
创建完成后,先创建一些基础文件目录,用于将来开发,并且修改pom.xml内容,添加一些公共依赖,效果如下 :
pom.xml 内容
<?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">
<parent>
<artifactId>TM-Learn-SpringCloud-Alibaba</artifactId>
<groupId>tm.learn</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>tm-springcloud-alibaba-common</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<mybatisplus.version>3.4.2</mybatisplus.version>
<mysql.version>8.0.25</mysql.version>
<commons.lang.version>3.7</commons.lang.version>
<commons.io.version>2.5</commons.io.version>
<fastjson.version>1.2.76</fastjson.version>
<hutool.version>5.1.2</hutool.version>
<gson.version>2.8.6</gson.version>
<knife4j.version>2.0.8</knife4j.version>
<lombok.version>1.18.18</lombok.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.io.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
3. 创建 tm-springcloud-alibaba-nacos-provider 模块
3.1 nacos配置命名空间
创建nacos模块之前,首先登录nacos服务,配置三个命名空间,分别为dev、prod、test,代表三个环境
3.2 springcloud添加nacos模块
在根项目名称上右键 New->Module->Spring Initializr 创建 tm-springcloud-alibaba-nacos-provider 模块
3.2.1 修改pom.xml内容
主要包括以下依赖 : mysql、druid、common、nacos-discovery、nacos-config、bootstrap
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>TM-Learn-SpringCloud-Alibaba</artifactId>
<groupId>tm.learn</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath/>
</parent>
<groupId>com.learn</groupId>
<artifactId>nacos</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>nacos</name>
<description>Learn For Nacos Provider</description>
<properties>
<java.version>1.8</java.version>
<mysql.version>8.0.21</mysql.version>
<druid.version>1.1.10</druid.version>
<common.version>1.0-SNAPSHOT</common.version>
<bootstrap.version>3.1.0</bootstrap.version>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>tm.learn</groupId>
<artifactId>tm-springcloud-alibaba-common</artifactId>
<version>${common.version}</version>
</dependency>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>${bootstrap.version}</version>
</dependency>
</dependencies>
</project>
3.2.2 修改bootstrap.yml内容
注意这里名字是bootstrap.yml不是application.yml
server:
port: 8090
spring:
application:
name: nacos-provider
profiles:
active: test
datasource:
url: jdbc:mysql://192.168.198.100:3306/learn?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false&allowMultiQueries=true
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
# dev
---
spring:
profiles: dev
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
# 注册服务的默认分组
group: DEFAULT_GROUP
# prod
---
spring:
profiles: prod
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: 91785852-93d6-4696-b20a-ba97c57989b7
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: 91785852-93d6-4696-b20a-ba97c57989b7
# 注册服务的默认分组
group: DEFAULT_GROUP
---
# test
spring:
profiles: test
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: d441c00a-a930-4324-a71f-2751ec071f24
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: d441c00a-a930-4324-a71f-2751ec071f24
# 注册服务的默认分组
group: DEFAULT_GROUP
3.2.3 启动类添加注解
//开启nacos服务的发现
@EnableDiscoveryClient
@SpringBootApplication
public class NacosApplication {
public static void main(String[] args) {
SpringApplication.run(NacosApplication.class, args);
}
}
3.2.4 测试类
注意这里需要加上@RefreshScope实现nacos配置自动更新,否则不会自动刷新
@Slf4j
@RestController
@RefreshScope//实现nacos配置自动更新
@RequestMapping("/tm")
@Api(tags = "生产者测试类")
public class ProviderController {
@Value("${testName}")
private String testName;
@GetMapping("/msg")
@ApiOperation(value = "provider测试")
public R getMsg(){
return R.ok(testName);
}
}
3.3 nacos创建各个环境配置文件
三个配置文件,名称格式为
(1) nacos-provider = spring.application.name 的值
(2) -dev 或 -test 或 -prod = spring.profiles.active 的值
(3) yml = spring.cloud.nacos.config.file-extension 的值
dev :nacos-provider-dev.yml
prod :
nacos-provider-prod.yml
test :
nacos-provider-test.yml
3.4 测试
启动nacos-provider服务和nacos服务,此时启动环境为test,可以在nacos的服务列表的test栏里看到nacos-provider服务已经被注册上去了。
使用浏览器访问:http://localhost:8090/tm/msg 调用接口,可以看到结果为
{"code":0,"data":"nacos-provider-test","msg":"执行成功"}
即确实读到了nacos里配置文件的值。此时我们修改配置文件里的值,也可以看到配置自动更新了,如果没有自动更新,需要检查以下对应的controller类上是否添加了自动刷新注解@RefreshScope
4. 创建 tm-springcloud-alibaba-gateway 模块
4.1 修改bootstrap.yml内容
注意 : 如果想要使用 uri: lb://nacos-provider 而不是 uri: http://192.168.198.100:8090 则需要配置 discovery.locator.enabled: true
server:
port: 8091
spring:
profiles:
active: dev
application:
name: api-gateway
cloud:
gateway:
routes:
# 当前路由的唯一标识
- id: tm-nacos
# 请求要转发到的地址
# uri: http://192.168.198.100:8090
uri: lb://nacos-provider
# 路由的优先级,数字越小,优先级越高
order: 1
# 断言(路由转发要满足的条件)
predicates:
- Path=/nacos-provider/**
# 过滤器,即转发之前去掉1层路径
filters:
- StripPrefix=1
discovery:
locator:
enabled: true
# dev
---
spring:
profiles: dev
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
# 注册服务的默认分组
group: DEFAULT_GROUP
# prod
---
spring:
profiles: prod
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: 91785852-93d6-4696-b20a-ba97c57989b7
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: 91785852-93d6-4696-b20a-ba97c57989b7
# 注册服务的默认分组
group: DEFAULT_GROUP
---
# test
spring:
profiles: test
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: d441c00a-a930-4324-a71f-2751ec071f24
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: d441c00a-a930-4324-a71f-2751ec071f24
# 注册服务的默认分组
group: DEFAULT_GROUP
4.2 修改pom.xml内容
这里要注意:
(1) 一定要加loadbalancer依赖,如果不加可能会报503错误。
503错误的原因是Spring Cloud 2020.0.0版本之前会自动引入Ribbon依赖, 功能类似于loadbalancer,因为Netflix公司停止维护Ribbon后,Spring Cloud 2020.0.0以后的版本使用了loadbalancer替代了Ribbon,但是loadbalancer依赖需要手动引入,所以如果你使用的版本是Spring Cloud 2020.0.0以上,则需要添加loadbalancer依赖。
(2) 不要添加common依赖 tm-springcloud-alibaba-common 这是因为common依赖中存在mysql、druid相关的驱动,需要我们在配置文件中添加mysql相关的配置才不会报错,而gateway中我们又不需要操作数据库,所以就不用添加了。或者将这些依赖移出common包也是可以的。
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (the profiles dev are currently active).
(3) 在springboot整合gateway时, gateway组件中的 【spring-boot-starter-webflux】 和 springboot作为web项目启动必不可少的 [spring-boot-starter-web] 会出现冲突,所以处理办法有两个,或者你不引入,或者使用exclusions标签来排除。
<dependency>
<groupId>xxx</groupId>
<artifactId>xxx</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</exclusion>
</exclusions>
</dependency>
依赖如下 :
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>TM-Learn-SpringCloud-Alibaba</artifactId>
<groupId>tm.learn</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath/>
</parent>
<groupId>com.learn</groupId>
<artifactId>gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway</name>
<description>Learn For Gateway</description>
<properties>
<java.version>1.8</java.version>
<bootstrap.version>3.1.0</bootstrap.version>
<loadbalancer.version>3.0.2</loadbalancer.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>${bootstrap.version}</version>
</dependency>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
</dependencies>
</project>
4.3 启动类上添加注解
@EnableDiscoveryClient
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
4.4 nacos里创建各个环境配置文件
三个配置文件 :
api-gateway-dev.yml,api-gateway-prod.yml,api-gateway-test.yml
内容分别为 :
testGatewayName: gateway-dev、testGatewayName: gateway-prod、testGatewayName: gateway-test
4.5 测试
(1) 首先直接调用nacos-provider服务 : http://localhost:8090/tm/msg 可以访问成功
(2) 然后测试通过调用gateway来路由到nacos-provider : http://localhost:8091/nacos-provider/tm/msg 可以访问成功
(3) 最后直接调用api-gateway服务 : http://localhost:8091/tm/msg 也可以调用成功,说明nacos中的配置文件生效。
服务列表里也可以看到gateway成功注册
5. 创建 tm-springcloud-alibaba-openfeign 模块
5.1 创建服务生产者代码
这里以nacos-provider服务作为服务提供者
在对应的controller中添加如下代码 :
@RefreshScope//实现nacos配置自动更新
@RestController
@RequestMapping("/tm")
public class ProviderController {
@GetMapping("/getMsgById/{id}")
public R getMsgById(@PathVariable("id") Long id) {
return R.ok("查询成功,id为"+id);
}
@PostMapping("insertMsg")
public R insertMsg(@RequestBody User user) {
return R.ok(user);
}
}
网关添加配置
- id: tm-openfeign
# 请求要转发到的地址
# uri: http://192.168.198.100:8090
uri: lb://api-openfeign
# 路由的优先级,数字越小,优先级越高
order: 1
# 断言(路由转发要满足的条件)
predicates:
- Path=/api-openfeign/**
# 过滤器,即转发之前去掉1层路径
filters:
- StripPrefix=1
这里user类自己随便写一个就可以了,可以放到common模块里
5.2 创建服务消费者代码
5.2.1 修改pom.xml文件
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>TM-Learn-SpringCloud-Alibaba</artifactId>
<groupId>tm.learn</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath/>
</parent>
<groupId>com.learn</groupId>
<artifactId>openfeign</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>openfeign</name>
<description>Learn For OpenFeign</description>
<properties>
<java.version>1.8</java.version>
<common.version>1.0-SNAPSHOT</common.version>
<test.version>2.2.13.RELEASE</test.version>
</properties>
<dependencies>
<dependency>
<groupId>tm.learn</groupId>
<artifactId>tm-springcloud-alibaba-common</artifactId>
<version>${common.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${test.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
</dependencies>
</project>
5.2.2 修改bootstrap.yml文件
server:
port: 8092
spring:
profiles:
active: dev
application:
name: api-openfeign
datasource:
url: jdbc:mysql://192.168.198.100:3306/learn?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false&allowMultiQueries=true
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
# dev
---
spring:
profiles: dev
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
# 注册服务的默认分组
group: DEFAULT_GROUP
# prod
---
spring:
profiles: prod
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: 91785852-93d6-4696-b20a-ba97c57989b7
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: 91785852-93d6-4696-b20a-ba97c57989b7
# 注册服务的默认分组
group: DEFAULT_GROUP
---
# test
spring:
profiles: test
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: d441c00a-a930-4324-a71f-2751ec071f24
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: d441c00a-a930-4324-a71f-2751ec071f24
# 注册服务的默认分组
group: DEFAULT_GROUP
5.2.3 启动类上添加启动注解
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class OpenfeignApplication {
public static void main(String[] args) {
SpringApplication.run(OpenfeignApplication.class, args);
}
}
5.2.4 测试类
@Slf4j
@RefreshScope//实现nacos配置自动更新
@RestController
@RequestMapping("/tm")
public class OpenFeignController {
@Autowired
OpenFeignService openFeignService;
@Value("${testOpenFeignName}")
private String testOpenFeignName;
@GetMapping("/msg")
@ApiOperation(value = "openFeign测试")
public R getMsg() {
return R.ok(testOpenFeignName);
}
@GetMapping("/getMsgById/{id}")
public R getMsgById(@PathVariable("id") Long id) {
return openFeignService.getMsgById(id);
}
@PostMapping("/insertMsg")
public R insertMsg(@RequestBody User user) {
return openFeignService.insertMsg(user);
}
}
=====================================================================
@Service
@FeignClient(name = "nacos-provider")//这里填写的就是你要远程调用的服务名
public interface OpenFeignService {
@GetMapping("/tm/getMsgById/{id}")
public R getMsgById(@PathVariable("id") Long id);
@PostMapping("/tm/insertMsg")
public R insertMsg(@RequestBody User user);
}
调用效果 :
(1) 访问 localhost:8092/tm/msg 验证nacos的配置文件是生效的
(2) 访问localhost:8091/api-openfeign/tm/msg验证通过网关的配置也是正确的
(3) 使用postman调用 localhost:8092/tm/getMsgById/1 或 localhost:8091/api-openfeign/tm/getMsgById/1 ,调用成功,结果为 :
{
"code": 0,
"data": "查询成功,id为1",
"msg": "执行成功"
}
(4) 使用postman调用 localhost:8092/tm/insertMsg 或 localhost:8091/api-openfeign/tm/insertMsg,参数为{"id":1,"name":"张三"} ,调用成功,结果为 :
{
"code": 0,
"data": {
"id": 1,
"name": "张三",
"age": null,
"tel": null,
"sex": null,
"address": null,
"email": null,
"birthday": null
},
"msg": "执行成功"
}
5.3 超时情况处理
5.3.1 bootstrap.yml添加配置
首先我们在消费者模块配置文件中添加配置 :
feign:
client:
# 添加此配置后修改超时时间就不需要重启服务
refresh-enabled: true
config:
default:
connectTimeout: 1000
readTimeout: 1000
5.3.2 添加休眠代码
然后在生产者模块的方法中添加代码 Thread.sleep(1000)
@GetMapping("/getMsgById/{id}")
public R getMsgById(@PathVariable("id") Long id) throws InterruptedException {
Thread.sleep(1000);
return R.ok("查询成功,id为"+id);
}
由于我设置的超时时间就是1000,那么此接口的调用时间肯定是超过了1s,所以控制台报错,去掉此行代码后,发现接口调用成功,由此判定生效。
java.net.SocketTimeoutException: Read timed out
5.3.3 contextId属性配置
那么此种方式是针对所有的接口的配置,那么如果想要单独的针对某一个模块的配置添加的话,做法如下 :
在 FeignClient 注解上配置 contextId 属性,如 :
@Service
@FeignClient(name = "nacos-provider",contextId = "nacos-provider-core")
public interface OpenFeignService {
@GetMapping("/tm/getMsgById/{id}")
public R getMsgById(@PathVariable("id") Long id);
@PostMapping("/tm/insertMsg")
public R insertMsg(@RequestBody User user);
}
然后bootstrap.yml配置修改如下 :
即默认超时时间都为1s,但是 contextId = "nacos-provider-core" 对应的接口超时时间是2s。
feign:
client:
# 添加此配置后修改超时时间就不需要重启服务
refresh-enabled: true
config:
default:
connectTimeout: 1000
readTimeout: 1000
nacos-provider-core:
connectTimeout: 2000
readTimeout: 2000
此时虽然我在生产者代码里添加了休眠1s的代码 Thread.sleep(1000);,但是接口仍可以调用成功。
5.4 重试情况处理
5.4.1 添加配置文件
代码 new Default(100, TimeUnit.SECONDS.toMillis(1), 5) 的三个参数含义如下 :
- period:周期,重试间隔时间
- maxPeriod:最大周期,重试间隔时间按照一定的规则逐渐增大,但不能超过最大周期
- maxAttempts:最大尝试次数,重试次数
import feign.RetryableException;
import feign.Retryer;
import java.util.concurrent.TimeUnit;
public class MyRetryer implements Retryer {
@Override
public void continueOrPropagate(RetryableException e) {
throw e;
}
@Override
public Retryer clone() {
return new Default(100, TimeUnit.SECONDS.toMillis(1), 5);
}
}
5.4.2 修改bootstrap.yml配置文件
添加 retryer 配置, 值 com.learn.openfeign.config.MyRetryer 为上面创建的MyRetryer类的路径
feign:
client:
# 添加此配置后修改超时时间就不需要重启服务
refresh-enabled: true
config:
default:
connectTimeout: 1000
readTimeout: 1000
retryer: com.learn.openfeign.config.MyRetryer
5.4.3 测试
将服务提供者的睡眠时间修改为超过配置的超时时间,以便可以多次触发重试,有利于看出效果。效果如下 :
调用1次,当前时间为2023-01-12 15:45:43:227
调用1次,当前时间为2023-01-12 15:45:44:290
调用1次,当前时间为2023-01-12 15:45:45:523
调用1次,当前时间为2023-01-12 15:45:46:877
调用1次,当前时间为2023-01-12 15:45:48:399
6. 创建 tm-springcloud-alibaba-sleuth 模块
链路追踪
6.1 整合sleuth
6.1.1 添加pom.xml依赖
这里我将sleuth相关的依赖都添加到了common里
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
pom.xml内容
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>TM-Learn-SpringCloud-Alibaba</artifactId>
<groupId>tm.learn</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath/>
</parent>
<groupId>com.learn</groupId>
<artifactId>sleuth</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>tm-springcloud-alibaba-sleuth</name>
<description>Learn For Sleuth</description>
<properties>
<java.version>1.8</java.version>
<common.version>1.0-SNAPSHOT</common.version>
<test.version>2.2.13.RELEASE</test.version>
</properties>
<dependencies>
<dependency>
<groupId>tm.learn</groupId>
<artifactId>tm-springcloud-alibaba-common</artifactId>
<version>${common.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${test.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
</dependencies>
</project>
6.1.2 添加bootstrap.yml配置
server:
port: 8093
spring:
profiles:
active: dev
application:
name: api-sleuth
datasource:
url: jdbc:mysql://192.168.198.100:3306/learn?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false&allowMultiQueries=true
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
feign:
client:
# 添加此配置后修改超时时间就不需要重启服务
refresh-enabled: true
config:
default:
connectTimeout: 1000
readTimeout: 1000
# dev
---
spring:
profiles: dev
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
# 注册服务的默认分组
group: DEFAULT_GROUP
# prod
---
spring:
profiles: prod
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: 91785852-93d6-4696-b20a-ba97c57989b7
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: 91785852-93d6-4696-b20a-ba97c57989b7
# 注册服务的默认分组
group: DEFAULT_GROUP
---
# test
spring:
profiles: test
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: d441c00a-a930-4324-a71f-2751ec071f24
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: d441c00a-a930-4324-a71f-2751ec071f24
# 注册服务的默认分组
group: DEFAULT_GROUP
6.1.3 启动类添加注解
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class SleuthApplication {
public static void main(String[] args) {
SpringApplication.run(SleuthApplication.class, args);
}
}
6.1.4 gateway网关添加配置
- id: tm-sleuth
# 请求要转发到的地址
uri: lb://api-sleuth
# 路由的优先级,数字越小,优先级越高
order: 1
# 断言(路由转发要满足的条件)
predicates:
- Path=/api-sleuth/**
# 过滤器,即转发之前去掉1层路径
filters:
- StripPrefix=1
6.1.5 测试类
@Slf4j
@RefreshScope//实现nacos配置自动更新
@RestController
@RequestMapping("/tm")
public class SleuthController {
@Autowired
SleuthService sleuthService;
@Value("${testSleuthName}")
private String testSleuthName;
@GetMapping("/msg")
@ApiOperation(value = "sleuth测试")
public R getMsg() {
log.info("sleuth测试");
return R.ok(testSleuthName);
}
@GetMapping("/getMsgById/{id}")
public R getMsgById(@PathVariable("id") Long id) {
log.info("getMsgById测试");
return sleuthService.getMsgById(id);
}
@PostMapping("/insertMsg")
public R insertMsg(@RequestBody User user) {
log.info("insertMsg测试");
return sleuthService.insertMsg(user);
}
}
@Service
@FeignClient(name = "nacos-provider")//这里填写的就是你要远程调用的服务名
public interface SleuthService {
@GetMapping("/tm/getMsgById/{id}")
public R getMsgById(@PathVariable("id") Long id);
@PostMapping("/tm/insertMsg")
public R insertMsg(@RequestBody User user);
}
http://localhost:8093/tm/msg 直接访问接口,控制台日志打印效果为 :
2023-01-13 10:01:51.156 INFO [api-sleuth,6789636f0df505eb,6789636f0df505eb] 4824 --- [nio-8093-exec-1] c.l.sleuth.controller.SleuthController : sleuth测试
http://localhost:8091/api-sleuth/tm/getMsgById/1 通过网关并远程调用nacos-provider服务访问,控制台日志打印效果为 :
2023-01-13 10:02:13.223 INFO [api-sleuth,380c08c2c366eec6,380c08c2c366eec6] 4824 --- [nio-8093-exec-2] c.l.sleuth.controller.SleuthController : getMsgById测试
6.2 整合Zipkin
Zipkin 是用来图形化展示 Sleuth 收集来的信息的,这里使用docker启动一个zipkin服务,这里不做过多介绍。
启动之后,发现报错日志,信息为
Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.mariadb.jdbc.internal.com.send.authentication.SendGssApiAuthPacket
at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) ~[?:?]
at jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) ~[?:?]
at java.lang.reflect.Constructor.newInstanceWithCaller(Unknown Source) ~[?:?]
at java.lang.reflect.Constructor.newInstance(Unknown Source) ~[?:?]
经过网上查询,解决办法为使用mysql5.7或修改配置信息,这里为了简单起见,我又用docker开了一个mysql5.7的服务
6.2.1 修改bootstrap.yml配置文件
主要修改内容为 :
(1) mysql连接driver-class-name改成了5.7版本的
(2) 服务调用者即sleuth模块,添加了zipkin相关配置
server:
port: 8093
spring:
profiles:
active: dev
application:
name: api-sleuth
datasource:
url: jdbc:mysql://192.168.198.100:3307/learn?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
sleuth:
enabled: true
sampler:
rate: 10000 #每秒数据采集量,多余将丢弃
probability: 1.0 #采样百分比:收集请求书数量的百分比。(默认为0.1,如果100次访问只将10次上传给zipkin )
zipkin:
sender:
type: web
# zipkin server的请求地址
base-url: http://192.168.198.100:9411/
#让nacos把它当成一个URL,而不要当做服务名
discovery-client-enabled: false
service:
name: api-zipkin
feign:
client:
# 添加此配置后修改超时时间就不需要重启服务
refresh-enabled: true
config:
default:
connectTimeout: 1000
readTimeout: 1000
# dev
---
spring:
profiles: dev
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
# 注册服务的默认分组
group: DEFAULT_GROUP
# prod
---
spring:
profiles: prod
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: 91785852-93d6-4696-b20a-ba97c57989b7
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: 91785852-93d6-4696-b20a-ba97c57989b7
# 注册服务的默认分组
group: DEFAULT_GROUP
---
# test
spring:
profiles: test
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: d441c00a-a930-4324-a71f-2751ec071f24
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: d441c00a-a930-4324-a71f-2751ec071f24
# 注册服务的默认分组
group: DEFAULT_GROUP
6.2.2 添加依赖
sleuth模块添加mysql5的依赖
<mysql5version>5.1.47</mysql5version>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql5version}</version>
<scope>runtime</scope>
</dependency>
common模块添加了zipkin相关的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
6.2.3 被调用模块添加zipkin配置
nacos-provider模块添加如下配置 :
spring:
zipkin:
sender:
type: web
# zipkin server的请求地址
base-url: http://192.168.198.100:9411/
#让nacos把它当成一个URL,而不要当做服务名
discovery-client-enabled: false
service:
name: api-zipkin-nacos-provider
注意 : 如果没有配置,nacos-provider模块会打印出如下报错 : 访问的是localhost的ip
org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost:9411/api/v2/spans": connect timed out; nested exception is java.net.SocketTimeoutException: connect timed out
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:785) ~[spring-web-5.3.15.jar:5.3.15]
at org.springframework.cloud.sleuth.zipkin2.ZipkinRestTemplateWrapper.doExecute(ZipkinRestTemplateWrapper.java:69) ~[spring-cloud-sleuth-zipkin-3.1.1.jar:3.1.1]
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:660) ~[spring-web-5.3.15.jar:5.3.15]
at org.springframework.cloud.sleuth.zipkin2.RestTemplateSender.post(RestTemplateSender.java:51) ~[spring-cloud-sleuth-zipkin-3.1.1.jar:3.1.1]
at org.springframework.cloud.sleuth.zipkin2.RestTemplateSender.lambda$new$0(RestTemplateSender.java:44) ~[spring-cloud-sleuth-zipkin-3.1.1.jar:3.1.1]
at org.springframework.cloud.sleuth.zipkin2.HttpSender.post(HttpSender.java:137) ~[spring-cloud-sleuth-zipkin-3.1.1.jar:3.1.1]
at org.springframework.cloud.sleuth.zipkin2.HttpSender$HttpPostCall.doExecute(HttpSender.java:150) ~[spring-cloud-sleuth-zipkin-3.1.1.jar:3.1.1]
at org.springframework.cloud.sleuth.zipkin2.HttpSender$HttpPostCall.doExecute(HttpSender.java:140) ~[spring-cloud-sleuth-zipkin-3.1.1.jar:3.1.1]
at zipkin2.Call$Base.execute(Call.java:391) ~[zipkin-2.23.2.jar:na]
at zipkin2.reporter.AsyncReporter$BoundedAsyncReporter.flush(AsyncReporter.java:299) ~[zipkin-reporter-2.16.3.jar:na]
at zipkin2.reporter.AsyncReporter$Flusher.run(AsyncReporter.java:378) [zipkin-reporter-2.16.3.jar:na]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
6.2.4 测试
浏览器访问 : http://localhost:8091/api-sleuth/tm/getMsgById/1 ,调用成功
日志打印 :
# 这里的23f04450350b68fa就是trace ID
2023-01-13 15:00:58.190 INFO [api-zipkin,23f04450350b68fa,23f04450350b68fa] 24400 --- [nio-8093-exec-4] c.l.sleuth.controller.SleuthController : getMsgById测试
浏览器访问 : http://192.168.198.100:9411/zipkin/ 右上角搜索 23f04450350b68fa ,点击run query可以看到结果如下 :
点击show按钮,调用者(sleuth)和被调用者(nacos-provider)链路的详细信息展示如下 :
重启zipkin服务,发现数据还在,即持久化生效。
7. 创建 tm-springcloud-alibaba-seata 模块
需要的seata依赖,可以创建在公用的common模块中。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
为了测试seata,这里需要准备 :
(1) 两个数据库,端口分别为3308 3309 并均创建数据库名为learn ,创建表undo_log,业务表 user
(2) 两个服务,分别连接上面的两个数据库
(3) seata-server这里是使用docker的方式安装的。
-- 业务表
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '姓名',
`age` int DEFAULT NULL COMMENT '年龄',
`tel` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '电话',
`sex` int DEFAULT NULL COMMENT '性别 0:女 1:男',
`address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '地址',
`email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '邮箱',
`birthday` date DEFAULT NULL COMMENT '出生日期',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
-- 回滚表
CREATE TABLE `undo_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`branch_id` bigint(20) NOT NULL,
`xid` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`context` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int(11) NOT NULL,
`log_created` datetime(0) NOT NULL,
`log_modified` datetime(0) NOT NULL,
`ext` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
7.1 seata-server在nacos里的配置信息
这里要注意 : 如果调用接口报错io.seata.core.exception.RmTransactionException: Response[ TransactionException[Could not found global transaction xid = xxx.xxx.xxx.xxx:8091:36378942915387401, may be has finished.] ] 就说明是接口时间太长,默认是1000,可以改大一点。
io.seata.core.exception.RmTransactionException: Response[ TransactionException[Could not found global transaction xid = 192.168.198.100:8091:36378942915387401, may be has finished.] ]
at io.seata.rm.AbstractResourceManager.branchRegister(AbstractResourceManager.java:69) ~[seata-all-1.4.2.jar:1.4.2]
at io.seata.rm.DefaultResourceManager.branchRegister(DefaultResourceManager.java:96) ~[seata-all-1.4.2.jar:1.4.2]
at io.seata.rm.datasource.ConnectionProxy.register(ConnectionProxy.java:272) ~[seata-all-1.4.2.jar:1.4.2]
at io.seata.rm.datasource.ConnectionProxy.processGlobalTransactionCommit(ConnectionProxy.java:250) ~[seata-all-1.4.2.jar:1.4.2]
at io.seata.rm.datasource.ConnectionProxy.doCommit(ConnectionProxy.java:230) ~[seata-all-1.4.2.jar:1.4.2]
at io.seata.rm.datasource.ConnectionProxy.lambda$commit$0(ConnectionProxy.java:188) ~[seata-all-1.4.2.jar:1.4.2]
# 二阶段提交未完成状态全局事务重试提交线程间隔时间 默认1000,单位毫秒
server.recovery.committingRetryPeriod=6000
# 二阶段异步提交状态重试提交线程间隔时间 默认1000,单位毫秒
server.recovery.asynCommittingRetryPeriod=6000
# 二阶段回滚状态重试回滚线程间隔时间
server.recovery.rollbackingRetryPeriod=6000
# 超时状态检测重试线程间隔时间 默认1000 单位毫秒 检测出超时将全局事务置入回滚会话管理器
server.recovery.timeoutRetryPeriod=6000
seata-dev.properties
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
client.tm.interceptorOrder=-2147482648
store.mode=db
store.lock.mode=db
store.session.mode=file
store.publicKey=
store.file.dir=file_store/data
store.file.maxBranchSessionSize=16384
store.file.maxGlobalSessionSize=512
store.file.fileWriteBufferCacheSize=16384
store.file.flushDiskMode=async
store.file.sessionReloadReadSize=100
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://192.168.198.100:3306/seata_config?useSSL=true&serverTimezone=GMT
store.db.user=root
store.db.password=123456
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.distributedLockTable=distributed_lock
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000
store.redis.mode=single
store.redis.single.host=127.0.0.1
store.redis.single.port=6379
store.redis.sentinel.masterName=
store.redis.sentinel.sentinelHosts=
store.redis.maxConn=10
store.redis.minConn=1
store.redis.maxTotal=100
store.redis.database=0
store.redis.password=
store.redis.queryLimit=100
server.recovery.committingRetryPeriod=6000
server.recovery.asynCommittingRetryPeriod=6000
server.recovery.rollbackingRetryPeriod=6000
server.recovery.timeoutRetryPeriod=6000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
server.distributedLockExpireTime=10000
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
client.undo.logTable=undo_log
client.undo.compress.enable=true
client.undo.compress.type=zip
client.undo.compress.threshold=64k
log.exceptionRate=100
transport.serialization=seata
transport.compressor=none
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898
tcc.fence.logTableName=tcc_fence_log
tcc.fence.cleanPeriod=1h
server.session.branchAsyncQueueSize=5000
server.session.enableBranchAsyncRemove=true
service.vgroupMapping.default_tx_group=default
service.vgroupMapping.uat_tx_group=default
service.vgroupMapping.test_tx_group=default
service.vgroupMapping.prod_tx_group=default
7.2 创建第一个服务
7.2.1 业务代码
业务代码里主要注意 最开始的调用方需要添加@GlobalTransactional注解,其他的模块的被调用方不需要添加
@Slf4j
@RefreshScope
@RestController
@RequestMapping("/tm")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/insertMsg")
public R insertMsg(@RequestBody User user){
return userService.saveUser(user);
}
}
//----------------------------------------------
@Data
@TableName("user")
@ApiModel
public class User implements Serializable {
@ApiModelProperty(position = 0,value = "用户ID")
@TableId(value = "id",type = IdType.AUTO)
private Long id;
@ApiModelProperty(position = 1,value = "用户姓名")
@TableField("name")
private String name;
@ApiModelProperty(position = 2,value = "用户年龄")
private Long age;
@ApiModelProperty(position = 3,value = "用户电话号")
private String tel;
@ApiModelProperty(position = 4,value = "用户性别")
private Long sex;
@ApiModelProperty(position = 5,value = "用户地址")
private String address;
@ApiModelProperty(position = 6,value = "用户邮箱")
private String email;
@ApiModelProperty(position = 7,value = "用户生日")
private Date birthday;
}
//----------------------------------------------
@Service
@FeignClient(name = "api-seatatwo")
public interface FeignService {
@PostMapping("/tm/insertMsg")
public R insertMsg(@RequestBody User user);
}
//----------------------------------------------
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
//----------------------------------------------
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private FeignService feignService;
@Override
@GlobalTransactional
public R saveUser(User user) {
userMapper.insert(user);
feignService.insertMsg(user);
return R.ok("保存成功");
}
}
//----------------------------------------------
public interface UserService extends IService<User> {
public R saveUser(User user);
}
//----------------------------------------------
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
@MapperScan(basePackages = "com.learn.seata.consumeone.mapper")
public class ConsumeoneApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumeoneApplication.class, args);
}
}
//----------------------------------------------
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.learn.seata.consumeone.mapper.UserMapper">
</mapper>
7.2.2 配置文件bootstrap.yml
这里主要是添加了如下关于seata的配置
#分布式事务 seata 配置
seata:
service:
vgroupMapping:
default_tx_group: default #default_tx_group分组名称必须要跟tx-service-group的值一样
#指定事务分组 分组必须在 nacos seata-dev.properties配置中有
tx-service-group: default_tx_group
config:
type: nacos
nacos:
#nacos地址
serverAddr: 192.168.198.100:8848
group: DEFAULT_GROUP
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
userName: nacos
password: nacos
#读取配置文件的 dataId
dataId: "seata-dev.properties"
registry:
type: nacos
nacos:
application: seata-server
server-addr: 192.168.198.100:8848
group: DEFAULT_GROUP
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
userName: nacos
password: nacos
server:
port: 8094
spring:
profiles:
active: dev
application:
name: api-seataone
datasource:
url: jdbc:mysql://192.168.198.100:3308/learn?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false&allowMultiQueries=true
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
type-aliases-package: com.learn.seata.consumeone.entity
feign:
client:
# 添加此配置后修改超时时间就不需要重启服务
refresh-enabled: true
config:
default:
connectTimeout: 1000
readTimeout: 1000
#分布式事务 seata 配置
seata:
service:
vgroupMapping:
default_tx_group: default #default_tx_group分组名称必须要跟tx-service-group的值一样
#指定事务分组 分组必须在 nacos seata-dev.properties配置中有
tx-service-group: default_tx_group
config:
type: nacos
nacos:
#nacos地址
serverAddr: 192.168.198.100:8848
group: DEFAULT_GROUP
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
userName: nacos
password: nacos
#读取配置文件的 dataId
dataId: "seata-dev.properties"
registry:
type: nacos
nacos:
application: seata-server
server-addr: 192.168.198.100:8848
group: DEFAULT_GROUP
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
userName: nacos
password: nacos
# dev
---
spring:
profiles: dev
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
# 注册服务的默认分组
group: DEFAULT_GROUP
# prod
---
spring:
profiles: prod
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: 91785852-93d6-4696-b20a-ba97c57989b7
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: 91785852-93d6-4696-b20a-ba97c57989b7
# 注册服务的默认分组
group: DEFAULT_GROUP
---
# test
spring:
profiles: test
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: d441c00a-a930-4324-a71f-2751ec071f24
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: d441c00a-a930-4324-a71f-2751ec071f24
# 注册服务的默认分组
group: DEFAULT_GROUP
7.2.3 配置文件pom.xml
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>TM-Learn-SpringCloud-Alibaba</artifactId>
<groupId>tm.learn</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath/>
</parent>
<groupId>com.learn.seata</groupId>
<artifactId>consumeone</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>tm-springcloud-alibaba-seata-consumeone</name>
<description>Learn For Seata One</description>
<properties>
<java.version>1.8</java.version>
<common.version>1.0-SNAPSHOT</common.version>
<test.version>2.2.13.RELEASE</test.version>
</properties>
<dependencies>
<dependency>
<groupId>tm.learn</groupId>
<artifactId>tm-springcloud-alibaba-common</artifactId>
<version>${common.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${test.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
</dependencies>
</project>
7.3 创建第二个服务
7.3.1 业务代码
这里注意,由于是被调用方,所以不需要添加 @GlobalTransactional 注解
@Slf4j
@RefreshScope
@RestController
@RequestMapping("/tm")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/insertMsg")
public R insertMsg(@RequestBody User user){
return userService.saveUser(user);
}
}
//----------------------------------------------
@Data
@TableName("user")
@ApiModel
public class User implements Serializable {
@ApiModelProperty(position = 0,value = "用户ID")
@TableId(value = "id",type = IdType.AUTO)
private Long id;
@ApiModelProperty(position = 1,value = "用户姓名")
@TableField("name")
private String name;
@ApiModelProperty(position = 2,value = "用户年龄")
private Long age;
@ApiModelProperty(position = 3,value = "用户电话号")
private String tel;
@ApiModelProperty(position = 4,value = "用户性别")
private Long sex;
@ApiModelProperty(position = 5,value = "用户地址")
private String address;
@ApiModelProperty(position = 6,value = "用户邮箱")
private String email;
@ApiModelProperty(position = 7,value = "用户生日")
private Date birthday;
}
//----------------------------------------------
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
//----------------------------------------------
public interface UserService extends IService<User> {
R saveUser(User user);
}
//----------------------------------------------
@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public R saveUser(User user) {
userMapper.insert(user);
//int a = 1/0;
return R.ok("保存成功");
}
}
//----------------------------------------------
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
@MapperScan(basePackages = "com.learn.seata.consumetwo.mapper")
public class ConsumetwoApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumetwoApplication.class, args);
}
}
//----------------------------------------------
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.learn.seata.consumetwo.mapper.UserMapper">
</mapper>
7.3.2 配置文件bootstrap.yml
主要注意添加如下配置信息 :
#分布式事务 seata 配置
seata:
service:
vgroupMapping:
default_tx_group: default #default_tx_group分组名称必须要跟tx-service-group的值一样
#指定事务分组 分组必须在 nacos seata-dev.properties配置中有
tx-service-group: default_tx_group
config:
type: nacos
nacos:
#nacos地址
serverAddr: 192.168.198.100:8848
group: DEFAULT_GROUP
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
userName: nacos
password: nacos
#读取配置文件的 dataId
dataId: "seata-dev.properties"
registry:
type: nacos
nacos:
application: seata-server
server-addr: 192.168.198.100:8848
group: DEFAULT_GROUP
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
userName: nacos
password: nacos
server:
port: 8095
spring:
profiles:
active: dev
application:
name: api-seatatwo
datasource:
url: jdbc:mysql://192.168.198.100:3309/learn?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false&allowMultiQueries=true
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
type-aliases-package: com.learn.seata.consumetwo.entity
feign:
client:
# 添加此配置后修改超时时间就不需要重启服务
refresh-enabled: true
config:
default:
connectTimeout: 1000
readTimeout: 1000
#分布式事务 seata 配置
seata:
service:
vgroupMapping:
default_tx_group: default #default_tx_group分组名称必须要跟tx-service-group的值一样
#指定事务分组 分组必须在 nacos seata-dev.properties配置中有
tx-service-group: default_tx_group
config:
type: nacos
nacos:
#nacos地址
serverAddr: 192.168.198.100:8848
group: DEFAULT_GROUP
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
userName: nacos
password: nacos
#读取配置文件的 dataId
dataId: "seata-dev.properties"
registry:
type: nacos
nacos:
application: seata-server
server-addr: 192.168.198.100:8848
group: DEFAULT_GROUP
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
userName: nacos
password: nacos
# dev
---
spring:
profiles: dev
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
# 注册服务的默认分组
group: DEFAULT_GROUP
# prod
---
spring:
profiles: prod
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: 91785852-93d6-4696-b20a-ba97c57989b7
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: 91785852-93d6-4696-b20a-ba97c57989b7
# 注册服务的默认分组
group: DEFAULT_GROUP
---
# test
spring:
profiles: test
cloud:
nacos:
config:
# 配置中心地址
server-addr: 192.168.198.100:8848
# 文件后缀,可以省略不配置
file-extension: yml
# 命名空间 默认public
namespace: d441c00a-a930-4324-a71f-2751ec071f24
# 配置中心的配置文件分组
group: DEFAULT_GROUP
# prefix: nacos-provider
discovery:
# 服务发现地址
server-addr: 192.168.198.100:8848
# 需要注册到的命名空间
namespace: d441c00a-a930-4324-a71f-2751ec071f24
# 注册服务的默认分组
group: DEFAULT_GROUP
7.3.3 配置文件pom.xml
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>TM-Learn-SpringCloud-Alibaba</artifactId>
<groupId>tm.learn</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath/>
</parent>
<groupId>com.learn.seata</groupId>
<artifactId>consumetwo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>tm-springcloud-alibaba-seata-consumetwo</name>
<description>Learn For Seata</description>
<properties>
<java.version>1.8</java.version>
<common.version>1.0-SNAPSHOT</common.version>
<test.version>2.2.13.RELEASE</test.version>
</properties>
<dependencies>
<dependency>
<groupId>tm.learn</groupId>
<artifactId>tm-springcloud-alibaba-common</artifactId>
<version>${common.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${test.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
</dependencies>
</project>
7.4 网关gateway配置
将两个服务配置上
spring:
cloud:
gateway:
routes:
- id: tm-seataone
# 请求要转发到的地址
uri: lb://api-seataone
# 路由的优先级,数字越小,优先级越高
order: 1
# 断言(路由转发要满足的条件)
predicates:
- Path=/api-seataone/**
# 过滤器,即转发之前去掉1层路径
filters:
- StripPrefix=1
- id: tm-seatatwo
# 请求要转发到的地址
uri: lb://api-seatatwo
# 路由的优先级,数字越小,优先级越高
order: 1
# 断言(路由转发要满足的条件)
predicates:
- Path=/api-seatatwo/**
# 过滤器,即转发之前去掉1层路径
filters:
- StripPrefix=1
7.5 测试
使用postman访问 localhost:8091/api-seataone/tm/insertMsg
成功 : 两个数据库对应的user表都保存成功一条数据
失败 : 在第二个服务的代码中故意添加错误代码,1/0,使其报错,结果是两个表都没有保存成功,效果实现了。
8. 创建tm-springcloud-alibaba-sentinal 模块
文档地址 : sentinelguard.io/zh-cn/docs/…
8.1 引入依赖
<!--sentinel启动器-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
8.2 添加配置
feign:
sentinel:
#开启openFeign对sentinel的整合
enabled: true
8.3 降级处理
8.3.1 编写业务代码
@Slf4j
@RefreshScope//实现nacos配置自动更新
@RestController
@RequestMapping("/tm")
public class SentinelController {
@Autowired
private FeignService feignService;
@GetMapping("/getMsgById/{id}")
public R getMsgById(@PathVariable("id") Long id) {
return feignService.getMsgById(id);
}
}
@Service
@FeignClient(name = "nacos-provider",fallback = FeignFailServiceImpl.class)
public interface FeignService {
@GetMapping("/tm/getMsgById/{id}")
public R getMsgById(@PathVariable("id") Long id);
}
@Component
public class FeignFailServiceImpl implements FeignService {
@Override
public R getMsgById(Long id) {
return R.failed("降级了");
}
}
//被调用服务故意写入报错代码1/0
@GetMapping("/getMsgById/{id}")
public R getMsgById(@PathVariable("id") Long id) throws InterruptedException {
int a = 1/0;
return R.ok("查询成功,id为"+id);
}
8.3.2 测试
访问 :http://localhost:8091/api-sentinel/tm/getMsgById/1 GET请求,结果成功降级
8.4 sentinel-dashboard
8.4.1 添加配置
这里注意 : 用docker部署的sentinel需要在yml配置client-ip:本地ip才行
spring:
cloud:
sentinel:
transport:
# sentinel-dashboard地址
dashboard: 192.168.198.100:8858
# 默认为8719,如果被占用会自动+1,直到找到为止
port: 8719
# 本地机器ip (注意事项,用docker部署的sentinel需要在yml配置client-ip:本地ip才行)
clientIp: 172.10.18.205
8.4.2 测试
浏览器访问 http://192.168.198.100:8858/ 默认账号 sentinel 密码 sentinel
调用一次接口,可以看到下图所示,不调用,可能看不到,懒加载
8.5 限流处理
8.5.1 添加@SentinelResource注解
value将该方法定义为sentinel的资源,blockHandler是流控时调用的方法,也可以使用blockHandlerClass指明流控处理的类。
@GetMapping("/getMsgById/{id}")
@SentinelResource(value = "getMsgById",blockHandler = "getMsgByIdHandler")
public R getMsgById(@PathVariable("id") Long id) {
return feignService.getMsgById(id);
}
public R getMsgByIdHandler(Long id, BlockException e){
log.info(e.getMessage());
return R.failed("限流异常,id: "+id);
}
8.5.2 配置sentinel流控规则
接口一秒钟之内访问超过1次,就会被限流
8.5.3 测试
1s内多次调用接口,效果如下 : 即确实触发了限流
8.6 sentinel配置持久化到nacos
Sentinel规则有默认的三种管理模式。
原始模式:Sentinel的默认模式,将规则保存到内存里,重启就会丢失。
pull模式:控制台将配置的规则推送到Sentinel客户端,Sentinel客户端首先会在内存里更新规则,然后将规则持久化到本地文件数据库。其他Sentinel客户端会定时询问数据库文件是否更改,更改的话进行同步数据。(数据容易不一致)
push模式:控制台将规则推送到nacos,Sentinel微服务监听nacos,一旦发现nacos的规则数据发生变化,就对规则进行更新。(推荐)
生产中一般采用push模式
8.6.1 引入依赖
重启sentinel-dashboard。通过测试,可以看到之前定义的流控规则已经消失了,限流也不好使了。
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
8.6.2 添加配置
spring:
cloud:
sentinel:
transport:
# sentinel-dashboard地址
dashboard: 192.168.198.100:8858
# # 默认为8719,如果被占用会自动+1,直到找到为止
port: 8719
# # 本地机器ip (注意事项,用docker部署的sentinel需要在yml配置client-ip:本地ip才行)
clientIp: 172.10.18.205
datasource:
# 自定义命名
ds1:
# 支持多种持久化数据源:file、nacos、zk、apollo、redis、consul
nacos:
server-addr: 192.168.198.100:8848
dataId: sentinel-dashboard-dev.json
groupId: DEFAULT_GROUP
namespace: 0c8d097b-2aaa-45f4-889a-44545ae50d3c
# 仅支持JSON和XML类型
data-type: json
# 规则类型:flow、degrade、param-flow、system、authority 如果还要做这些限流规则持久化,可以在datasource下加这些持久化规则。
rule-type: flow
# nacos开启了认证需要配置username、password
username: nacos
password: nacos
8.6.3 nacos添加配置
根据上步里的配置,这里我在dev环境下创建文件。文件的名字为sentinel-dashboard-dev.json、类型为json、内容如下 :
[
{
"resource":"getMsgById",
"limitApp":"default",
"grade":1,
"count":1,
"strategy":0,
"controlBehavior":0,
"clusterMode":false
}
]
各个含义为 :
-
resource: 资源名称 -
limitApp: 来源应用 -
grade: 阈值类型,0 表示线程数,1 表示 QPS -
count:单机阈值 -
strategy:流控模式,0 表示直接,1表示关联,2表示链路 -
controlBehavior: 流控效果,0 表示快速失败 ,1 表示 Warm Up ,2 表示排队等待 -
clusterMode: 是否集群
8.6.4 测试
重启sentinel-dashboard服务,可以看到配置已经自动持久化进来了。测试接口,也生效。完成!