目錄
前言
源碼地址
官方中文文檔
使用版本
spring
Spring Boot 3.1.0
中間件
使用到的組件與功能
環(huán)境安裝
虛擬機(jī)
nexus
nacos
集成過程
工程搭建
父工程搭建
子工程
服務(wù)集成
nacos集成
配置文件
服務(wù)注冊與發(fā)現(xiàn)-discovery
服務(wù)注冊
啟動
服務(wù)發(fā)現(xiàn)
測試
配置管理-config
新增配置
?測試
Sentinel集成
官方文檔
服務(wù)端安裝
集成步驟
配置修改?
?測試
SpringCloud Gateway集成
配置文件修改
參數(shù)說明
測試
拓展
SpringCloud OpenFeign集成
集成過程
測試
Seata 整合實現(xiàn)分布式事務(wù)
概念介紹及Server搭建
集成過程
數(shù)據(jù)庫腳本
業(yè)務(wù)表腳本
代碼模塊改造
POM依賴
配置文件
詳細(xì)代碼
client集成openFeign實現(xiàn)遠(yuǎn)程調(diào)用
測試
Knife4J整合gateway接口文檔
需求
官方文檔
集成
網(wǎng)關(guān)模塊修改
業(yè)務(wù)模塊修改
測試
Rocketmq消息隊列集成
服務(wù)安裝
前置準(zhǔn)備
Spring Cloud Stream基礎(chǔ)
配置文件修改
業(yè)務(wù)代碼
provider
consumer
測試
進(jìn)階
消息丟失問題
tag與key的設(shè)置
Sleuth+Zipkin集成分布式鏈路追蹤
zipkin可視化服務(wù)安裝
業(yè)務(wù)集成
問題及大坑
Micrometer Tracing 集成實現(xiàn)分布式鏈路追蹤
資料
集成
依賴
?配置修改
測試
Spring Boot Admin 集成實現(xiàn)服務(wù)監(jiān)控
前置準(zhǔn)備
?配置修改
父工程
admin工程
客戶端consumer
測試
效果
集成Spring Authorization Server 與Spring Security Oauth2.1統(tǒng)一認(rèn)證
過程
前言
只介紹如何集成及使用,概念性的東西就不細(xì)說了。慢慢更新
源碼地址
代碼我傳到了gitHub上,地址如下:
ricardo-m-yu/spring-cloud-alibaba (github.com)
官方中文文檔
spring-cloud-alibaba/README-zh.md at 2022.x · alibaba/spring-cloud-alibaba · GitHub
使用版本
spring
我這邊使用的都是最新版?
spring.cloud.alibaba.version | 2022.0.0.0-RC2 |
spring.cloud.version | 2022.0.0 |
spring.boot.version | 3.1.0 |
spring-cloud-alibaba、spring-cloud、springboot 三者的版本關(guān)系說明
https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E
Spring Boot 3.1.0
因為需要使用新版本的springboot及spring.cloud.alibaba。
springboot3.1x版本特性:
- 調(diào)整 JDK 基線到 17 版本,兼容 JDK19,即最低的JDK要求17
- 將 Java EE 依賴遷移到 Jakarta EE;比如?javax.servlet.Servlet 已經(jīng)成了?jakarta.servlet.Servlet
- 支持應(yīng)用使用 GraalVM 技術(shù)生成原生鏡像,取代了之前實驗性質(zhì)的 Spring Native 項目,讓 Spring Boot 應(yīng)用直接邁向 GraalVM;
- 使用 Micrometer 和 Micrometer Tracing 提升了應(yīng)用可觀測性,比如 sleuth已經(jīng)廢棄,使用了Micrometer Tracing
- Docker Compose的支持
- ssl的配置
- 授權(quán)服務(wù)器的自動配置: Spring Authorization Server
中間件
組件關(guān)系
使用到的組件與功能
- 服務(wù)注冊與發(fā)現(xiàn):Nacos?
- 分布式事務(wù):Seata
- 網(wǎng)關(guān):Spring Cloud Gateway
- 服務(wù)調(diào)用:OpenFeign
- 鑒權(quán):Spring Authorization Server 、Oauth2.1
- 消息隊列:rocketmq
- 限流、熔斷:sentinel
- 鏈路追蹤:Micrometer Tracing
- 接口文檔:knife4j
環(huán)境安裝
虛擬機(jī)
我是用的VMware虛擬機(jī)里面跑的。
具體怎么裝,看下面
(312條消息) VMware16安裝 CentOS7_ricardo.M.Yu的博客-CSDN博客
nexus
我這邊搭建了一個nexus maven私服
(310條消息) docker-compose 搭建maven私服 nexus與配置_ricardo.M.Yu的博客-CSDN博客
nacos
(310條消息) docker-compose安裝nacos 2.2.1及配置_ricardo.M.Yu的博客-CSDN博客
集成過程
工程搭建
我這邊使用的是springboot多模塊項目,最終效果如下
父工程搭建
POM文件
<?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>org.example</groupId>
<artifactId>cloud-alibaba</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>common</module>
<module>file</module>
<module>auth</module>
<module>gateway</module>
<module>admin</module>
<module>data</module>
<module>biz</module>
<module>log</module>
<module>consumer</module>
</modules>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.cloud.alibaba.version>2022.0.0.0-RC2</spring.cloud.alibaba.version>
<spring.cloud.version>2022.0.0</spring.cloud.version>
<spring.boot.version>3.1.0</spring.boot.version>
<spring.boot.admin.version>2.5.1</spring.boot.admin.version>
<lombok.version>1.18.20</lombok.version>
<fastjson.version>1.2.73</fastjson.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.0</version>
<relativePath/>
</parent>
<dependencyManagement>
<!-- cloud -->
<dependencies>
<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.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>
<!-- admin -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>${spring.boot.admin.version}</version>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${spring.boot.admin.version}</version>
</dependency>
<!-- 第三方工具 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<!--統(tǒng)一環(huán)境-->
<profiles>
<profile>
<id>prod</id>
<properties>
<profiles.active>prod</profiles.active>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>dev</id>
<properties>
<profiles.active>dev</profiles.active>
</properties>
</profile>
</profiles>
<!--maven插件-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>none</mainClass> <!-- 取消查找本項目下的Main方法:為了解決Unable to find main class的問題 -->
<classifier>execute</classifier> <!-- 為了解決依賴模塊找不到此模塊中的類或?qū)傩?-->
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
子工程
服務(wù)集成
nacos集成
部分可以參考官方的示例
Nacos Spring Cloud 快速開始
配置文件
這邊我定義了4組配置文件,說一下他們的作用:
引導(dǎo)類配置;?
bootstrap.yaml:定義當(dāng)前生效的配置
spring:
profiles:
active: dev
bootstrap-dev.yaml:定義引導(dǎo)類當(dāng)前生效的參數(shù)
spring:
cloud:
nacos:
server-addr: http://192.168.1.115:8108/
discovery:
group: dev
應(yīng)用級配置:
application.yaml
應(yīng)用級別的基礎(chǔ)配置
logging:
level:
root: info
com:
sy: debug
application-dev.yaml
定義應(yīng)用的名稱以及端口等信息
server:
port: 9110
spring:
application:
name: biz
服務(wù)注冊與發(fā)現(xiàn)-discovery
服務(wù)注冊
引入依賴
<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>
啟動
啟動后,查看nacos控制臺服務(wù)列表,已經(jīng)能看到這個實例
服務(wù)發(fā)現(xiàn)
需要在新建一個consumer服務(wù),來測試
分別在兩個模塊建兩個controller, biz模塊下:
@RestController
@RefreshScope
@RequestMapping("/")
public class BizController {
@GetMapping(value = "/echo/{string}")
public String echo(@PathVariable String string) {
return "Hello Nacos Discovery " + string;
}
}
consumer模塊下
@Slf4j
@RestController
@RequestMapping("/")
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
@Value("${spring.application.name}")
private String appName;
@GetMapping("/echo/app-name")
public String echoAppName() {
//使用 LoadBalanceClient 和 RestTemolate 結(jié)合的方式來訪問
ServiceInstance serviceInstance = loadBalancerClient.choose("biz");
String url = String.format("http://%s:%s/echo/%s", serviceInstance.getHost(), serviceInstance.getPort(), appName);
System.out.println("request url:" + url);
String result = restTemplate.getForObject(url, String.class);
log.info("result -> {}", result);
return result;
}
}
測試
用consumer下的http測試接口,發(fā)現(xiàn)已經(jīng)能正常返回數(shù)據(jù),appName即為consumer
配置管理-config
配置管理測試,主要集成從nacos拉取公共配置并測試,
新增配置
biz模塊下新增依賴和配置文件
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
增加配置中心config配置,文件擴(kuò)展為yaml
spring:
cloud:
nacos:
server-addr: http://192.168.1.115:8108/
discovery:
group: dev
#配置中心
config:
server-addr: http://192.168.1.115:8108/
group: dev
file-extension: yaml
# 共享配置
# shared-configs:
# - data-id: application-dev.yaml
# group: dev
# extension-configs:
# - dataId: test01.yml
# group: dev
application:
name: biz
nacos? web頁面配置列表新增一個配置,命名格式和group要對,dataId格式
${spring.application.name}-${profile}.${file-extension:properties}
示例:? biz-dev.yaml
?我這邊建了個示例
?測試
修改?BizController 增加方法:
@Value("${username}")
private String username;
@GetMapping("/get")
public String get() {
return username;
}
http測試:可以看到username的值已經(jīng)為 nacos的設(shè)置值
Sentinel集成
官方文檔
quick-start | Sentinel (sentinelguard.io)
demo
spring-cloud-alibaba/readme-zh.md at 2022.x · alibaba/spring-cloud-alibaba · GitHub
服務(wù)端安裝
詳細(xì)的看下面文章
(305條消息) Spring Cloud Alibaba 之 sentinel-dashboard 安裝及docker-compose鏡像制作_ricardo.M.Yu的博客-CSDN博客
集成步驟
配置修改?
pom文件,新增依賴
<!-- sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
修改bootstrap-dev.yaml, 增加 sentinel相關(guān)配置,
dashboard即為 sentinel控制臺的地址,
port為當(dāng)前項目需要暴露的接口,與控制臺通信使用
spring:
cloud:
nacos:
server-addr: http://192.168.1.115:8108/
discovery:
group: dev
sentinel:
transport:
dashboard: localhost:9988
port: 8899
?測試
啟動biz項目,調(diào)用下之前的 get接口,然后刷新 sentinel控制臺,已經(jīng)看到了biz的相關(guān)監(jiān)控數(shù)據(jù),其他詳細(xì)的功能,可以看官方文檔
SpringCloud Gateway集成
nacos整合Spring Cloud Gateway 實現(xiàn)路由與服務(wù)動態(tài)發(fā)現(xiàn)
配置文件修改
pom集成
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
gateway模塊配置文件增加
spring:
main:
web-application-type: reactive
cloud:
nacos:
server-addr: http://192.168.1.115:8108/
discovery:
group: dev
sentinel:
transport:
dashboard: 192.168.1.115:9988
port: 8899
gateway:
# discovery:
# locator:
# enabled: true
routes:
- id: consumer-service
uri: https://www.qq.com
predicates:
- Method=GET,POST
- Path=/consumer-service/**
# - id: biz
# uri: http://192.168.1.125:9110
# predicates:
# - Method=GET,POST
# - Path=/biz/**
- id: biz
uri: lb://biz
predicates:
- Method=GET,POST
- Path=/biz/**
參數(shù)說明
id:路由的ID,名稱可以隨意定義,但必須保證唯一
uri: 目標(biāo)URI,路由到微服務(wù)的地址
上面的配置中第一個是直接轉(zhuǎn)發(fā)到 qq 網(wǎng)站;
下面是 采用 LoadBalanceClient 方式請求,以 lb:// 開頭,后面的是注冊在 Nacos 上的服務(wù)名
order:路由的優(yōu)先級,數(shù)字越小,優(yōu)先級越高。
predicates:配置斷言,通過PredicateDefinition類進(jìn)行接收配置
discovery:
????????locator: # 是否與服務(wù)發(fā)現(xiàn)組件結(jié)合,通過serviceId轉(zhuǎn)發(fā)到具體服務(wù)實例
????????????????enabled: true # 是否開啟基于服務(wù)發(fā)現(xiàn)的路由規(guī)則
如:
上面的方式中:lb://biz 配置即可找到 nacos中的biz服務(wù)
測試
postman測試
?已經(jīng)收到了回復(fù)的消息
拓展
關(guān)于路由規(guī)則,過濾器、自定義的規(guī)則等知識,詳細(xì)見官網(wǎng)。
Spring Cloud Gateway
SpringCloud OpenFeign集成
集成過程
引入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
?biz模塊新增一個API
@GetMapping(value = "/info")
public Map<String, Object> getInfo(@RequestParam String username) {
HashMap<String, Object> map = new HashMap<>();
map.put("username", username);
map.put("password", "123456");
return map;
}
consumer模塊啟動類增加注解@EnableFeignClients
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
consumer模塊新增一個 client,意思是調(diào)用biz模塊的上面方法
@Component
@FeignClient(value = "biz")
public interface BizClient {
@GetMapping("/biz/info")
Object getInfo(@RequestParam String username);
}
consumer模塊controller新增一個方法供調(diào)用
@Resource
private BizClient bizClient;
@GetMapping("/username")
public Object getUserInfo(@RequestParam String username) {
return bizClient.getInfo(username);
}
測試
postmant調(diào)用 consumer的方法,效果如下:
可以看到已經(jīng)成功調(diào)用
Seata 整合實現(xiàn)分布式事務(wù)
Seata 是 阿里巴巴 開源的 分布式事務(wù)中間件,以 高效 并且對業(yè)務(wù) 0 侵入 的方式,解決 微服務(wù) 場景下面臨的分布式事務(wù)問題。
概念介紹及Server搭建
有些麻煩,放在了另一處,鏈接
(319條消息) Spring Cloud Alibaba 整合Seata 之概念介紹及Seata-server搭建_ricardo.M.Yu的博客-CSDN博客
集成過程
數(shù)據(jù)庫腳本
我使用的是seata默認(rèn)的AT模式,可以通過注解的方式無侵入的方式實現(xiàn)集成,需要額外的一張表如下
Seata AT 模式 需要使用到 undo_log 表。
-- 注意此處0.3.0+ 增加唯一索引 ux_undo_log
CREATE TABLE `undo_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`branch_id` bigint(20) NOT NULL,
`xid` varchar(100) NOT NULL,
`context` varchar(128) NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int(11) NOT NULL,
`log_created` datetime NOT NULL,
`log_modified` datetime NOT NULL,
`ext` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
業(yè)務(wù)表腳本
幾個測試表,提供測試
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for account_tbl
-- ----------------------------
DROP TABLE IF EXISTS `account_tbl`;
CREATE TABLE `account_tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`money` int(11) NULL DEFAULT 0,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of account_tbl
-- ----------------------------
INSERT INTO `account_tbl` VALUES (11, '1001', 981);
-- ----------------------------
-- Table structure for order_tbl
-- ----------------------------
DROP TABLE IF EXISTS `order_tbl`;
CREATE TABLE `order_tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`commodity_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`count` int(11) NULL DEFAULT 0,
`money` int(11) NULL DEFAULT 0,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of order_tbl
-- ----------------------------
INSERT INTO `order_tbl` VALUES (6, '1001', '2001', 1, 5);
INSERT INTO `order_tbl` VALUES (8, '1001', '2001', 1, 5);
INSERT INTO `order_tbl` VALUES (9, '1001', '2001', 1, 5);
INSERT INTO `order_tbl` VALUES (10, '1001', '2001', 1, 5);
-- ----------------------------
-- Table structure for stock_tbl
-- ----------------------------
DROP TABLE IF EXISTS `stock_tbl`;
CREATE TABLE `stock_tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`commodity_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`count` int(11) NULL DEFAULT 0,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `commodity_code`(`commodity_code`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of stock_tbl
-- ----------------------------
INSERT INTO `stock_tbl` VALUES (2, '2001', 11107);
代碼模塊改造
之前的biz模塊修改為provider模塊,新建1個新的父模塊 biz,并在下面建4個子模塊? biz-account,biz-order,biz-stock,biz-web,新的結(jié)構(gòu)如下
POM依賴
在biz父模塊引入依賴
<dependency>
<groupId>com.sy</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
子模塊pom,這里我為了方便,使用了 knife4j的最新接口文檔,支持springboot3.0
<?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>
<parent>
<groupId>com.sy</groupId>
<artifactId>biz</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>biz-web</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>
</dependencies>
</project>
配置文件
每個文件都添加seata的配置,如下
spring:
cloud:
nacos:
server-addr: http://192.168.1.115:8108/
discovery:
group: dev
sentinel:
transport:
dashboard: 192.168.1.115:8109
port: 8900
application:
name: provider
seata:
enabled: true
application-id: ${spring.application.name}
tx-service-group: my-tx-group
service:
vgroup-mapping:
my-tx-group: seata-server
grouplist:
seata-server: 192.168.1.115:8091
詳細(xì)代碼
完整的就不弄了,到時下下來源碼去看,主要說幾個重要的
controller,提供接口
@RequestMapping("/api/business")
@RestController
public class BusinessController {
@Autowired
private BusinessService businessService;
/**
* 購買下單,模擬全局事務(wù)提交
*
* @return
*/
@GetMapping("/purchase/commit")
public Boolean purchaseCommit(HttpServletRequest request) {
businessService.purchase("1001", "2001", 1);
return true;
}
/**
* 購買下單,模擬全局事務(wù)回滾
*
* @return
*/
@GetMapping("/purchase/rollback")
public Boolean purchaseRollback() {
try {
businessService.purchase("1002", "2001", 1);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
}
?service提供多個服務(wù)的接口調(diào)用,方便測試
@Slf4j
@Service
public class BusinessService {
@Autowired
private StockClient stockClient;
@Autowired
private OrderClient orderClient;
/**
* 減庫存,下訂單
*
* @param userId
* @param commodityCode
* @param orderCount
*/
@GlobalTransactional
public void purchase(String userId, String commodityCode, int orderCount) {
log.info("purchase begin ... xid: " + RootContext.getXID());
stockClient.deduct(commodityCode, orderCount);
orderClient.create(userId, commodityCode, orderCount);
}
}
client集成openFeign實現(xiàn)遠(yuǎn)程調(diào)用
@FeignClient(value = "biz-stock")
public interface StockClient {
@GetMapping("/api/stock/deduct")
Object deduct(@RequestParam String commodityCode, @RequestParam Integer count);
}
mapper及xml文件不一一列出了,下載源碼去看,結(jié)構(gòu)如下
?knife4j配置
@Configuration
@EnableKnife4j
public class SwaggerConfiguration {
@Value("${spring.application.name}")
private String appName;
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title(appName + "系統(tǒng)API")
.version("1.0")
.description( "Knife4j集成springdoc-openapi示例")
.termsOfService("http://doc.xiaominfo.com")
.license(new License().name("Apache 2.0")
.url("http://doc.xiaominfo.com")));
}
}
測試
打開biz-web的接口
http://192.168.1.125:9203/doc.html
測試
?如果打斷點,undo_log這個表會有相關(guān)的信息
事務(wù)完成后,會刪除
biz-web調(diào)用控制臺效果圖
seata-server端打印的日志
Knife4J整合gateway接口文檔
需求
因為開發(fā)需求,需要整合各個服務(wù)的接口文檔,發(fā)現(xiàn)了knife4j最新版本(2023.3)出來了一個好用的插件,可以方便整合?SpringCloud Gateway 與各個業(yè)務(wù)服務(wù)的接口文檔,不需要之前我們再硬編碼寫各種過濾器和攔截器去手動整合了。
官方文檔
Spring Cloud Gateway網(wǎng)關(guān)聚合 | Knife4j (xiaominfo.com)
集成
網(wǎng)關(guān)模塊修改
在之前的網(wǎng)關(guān)模塊新增依賴
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-gateway-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>
修改網(wǎng)關(guān)模塊的??bootstrap-dev.yaml配置文件,增加 knife4j的配置
excluded-services:即為排除的網(wǎng)關(guān)服務(wù)的名稱,
此處?strategy: discover 是依賴 nacos的注冊中心的服務(wù)發(fā)現(xiàn)模式,可以自動發(fā)現(xiàn)注冊的業(yè)務(wù)服務(wù)
knife4j:
gateway:
enabled: true
strategy: discover
discover:
version: openapi3
enabled: true
excluded-services:
- gateway
業(yè)務(wù)模塊修改
在上面集成seata模塊的過程中,每個服務(wù)都集成knife4j的配置
測試
啟動4個業(yè)務(wù)服務(wù)即一個網(wǎng)關(guān)服務(wù),訪問網(wǎng)關(guān)的接口文檔,發(fā)現(xiàn)每個業(yè)務(wù)模塊都被集成了進(jìn)來,如下圖?
測試一下接口,調(diào)用以下之前biz-web模塊下的方法,發(fā)現(xiàn)已經(jīng)正常與網(wǎng)關(guān)集成了
?集成完畢
Rocketmq消息隊列集成
服務(wù)安裝
參考下面另一篇文章
(324條消息) docker-compose安裝 rocketmq server、dashboard_ricardo.M.Yu的博客-CSDN博客
前置準(zhǔn)備
準(zhǔn)備兩個服務(wù):基于之前的改造:需要provider(最為生產(chǎn)者)以及consumer(作為消費者)
?依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
<version>2022.0.0.0-RC2</version>
</dependency>
<!-- 接口文檔方便調(diào)用-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
</dependency>
Spring Cloud Stream基礎(chǔ)
因為rocketmq依賴Spring Cloud Stream,先介紹下Spring Cloud Stream。
注意,因為我們使用最新版本一來的 stream版本為最新的 4.0,需要注意3.0以后的版本,寫法有很大區(qū)別,一些遺留問題,如@EnableBInding、@StreamListener都已經(jīng)不再使用(deprecated)
SpringCloud Stream是一個構(gòu)建消息驅(qū)動微服務(wù)的框架,應(yīng)用程序通過inputs或者 outputs來與SpringCloud Stream中的binder進(jìn)行交互,我們可以通過配置來binding ,而 SpringCloud Stream 的binder負(fù)責(zé)與中間件交互,弄清楚兩個概念:
- binder:Binder是SpringCloud Stream的一個抽象概念,是應(yīng)用與消息中間件之間的粘合劑,目前SpringCloud Stream實現(xiàn)了Kafka和RabbitMQ的binder, 但是我們這里引用 rocket自己的依賴也可以實現(xiàn)
- binding :相當(dāng)于定義消息級別的組、topic等信息,和binder解耦,和binders進(jìn)行綁定,指定是input或output。
注意:
bindings:命名 格式? ? {name}-out-0? ?這是是 4.x 的一種約定
配置文件修改
這邊我用了兩個組,兩個topic來測試
provider下?bootstrap-dev.yaml,增加 rocketmq配置
spring:
application:
name: provider
cloud:
nacos:
server-addr: http://192.168.1.115:8108/
discovery:
group: dev
#配置中心
config:
server-addr: http://192.168.1.115:8108/
group: dev
file-extension: yaml
# 共享配置
# shared-configs:
# - data-id: application-dev.yaml
# group: dev
# extension-configs:
# - dataId: test01.yml
# group: dev
sentinel:
transport:
dashboard: 192.168.1.115:8109
port: 8900
# rocket mq 配置
stream:
rocketmq:
binder:
name-server: 192.168.1.115:9876
bindings:
test-out-0:
destination: test-topic
content-type: application/json
group: test-group
dev-out-0:
destination: dev-topic
content-type: application/json
group: dev-group
consumer下?bootstrap-dev.yaml,增加 rocketmq配置
spring:
cloud:
nacos:
server-addr: http://192.168.1.115:8108/
discovery:
group: dev
sentinel:
transport:
dashboard: 192.168.1.115:9988
port: 8899
# rocket mq 配置
stream:
rocketmq:
binder:
name-server: 192.168.1.115:9876
function:
definition: test;dev
bindings:
test-in-0:
destination: test-topic
content-type: application/json
group: test-group
consumer:
instance-count: 3
concurrency: 5
dev-in-0:
destination: dev-topic
content-type: application/json
group: dev-group
consumer:
instance-count: 3
concurrency: 5
業(yè)務(wù)代碼
寫一個person的測試類
@Data
public class Person {
private String name;
}
provider
controller
@RestController
@Tag(name = "消息-消息隊列發(fā)送")
@RequestMapping("/message/send")
public class MqSendController {
@Resource
private MqSendService mqSendService;
@Operation(summary = "發(fā)送")
@PostMapping
public void send(@RequestParam String channel, @RequestParam String message) {
mqSendService.send(channel, message);
}
}
service
@Service
public class MqSendService {
@Resource
private StreamBridge streamBridge;
public void send(String channel, String message) {
Person person = new Person();
person.setName(message);
Message<Person> build = MessageBuilder.withPayload(person).build();
streamBridge.send(channel, build);
}
}
consumer
service
@Slf4j
@Service
public class MqSubService {
@Bean
public Consumer<Message<Person>> test() {
return message -> {
MessageHeaders headers = message.getHeaders();
Person payload = message.getPayload();
log.info("消息 test:" + payload + "__" + headers);
};
}
@Bean
public Consumer<Message<Person>> dev() {
return message -> {
MessageHeaders headers = message.getHeaders();
Person payload = message.getPayload();
log.info("消息 dev:" + payload + "__" + headers);
};
}
}
測試
調(diào)用provider的controller方法,
注意,channel必須和配置文件里面的?destination 一致,否則收不到消息。
consumer打印:
web界面
已經(jīng)正常集成完畢。
進(jìn)階
消息丟失問題
幾個問題,一個是多組多訂閱的問題,即一個組下的consumer訂閱的topic要一直,不然消費組訂閱關(guān)系不一致,會導(dǎo)致消息丟失問題,下面這個文章結(jié)束的比較好
RocketMQ的tag還有這個“坑”! - 知乎 (zhihu.com)
tag與key的設(shè)置
通過 stream 的header設(shè)置,來設(shè)置這兩個參數(shù)
public void send(String channel, String message, String tag, String keys) {
Person person = new Person();
person.setName(message);
Message<Person> build = MessageBuilder.withPayload(person)
.setHeader(MessageConst.PROPERTY_TAGS, tag).setHeader(MessageConst.PROPERTY_KEYS, keys).build();
streamBridge.send(channel, build);
}
可以看到,這兩個參數(shù)已經(jīng)被設(shè)置上
Sleuth+Zipkin集成分布式鏈路追蹤
Zipkin是Twitter開源的分布式實時數(shù)據(jù)跟蹤系統(tǒng),主要功能是收集系統(tǒng)的時序數(shù)據(jù),從而追蹤微服務(wù)架構(gòu)的系統(tǒng)延時等問題,從而達(dá)到鏈路調(diào)用監(jiān)控跟蹤作用,還提供了一個非常友好的UI界面,來幫助分析追蹤數(shù)據(jù)。
zipkin可視化服務(wù)安裝
安裝的鏈接在這里
(291條消息) docker-compose 搭建 zipkin 服務(wù)端_ricardo.M.Yu的博客-CSDN博客
業(yè)務(wù)集成
事先沒做調(diào)研,從maven倉庫選擇了個最新的依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
<version>2.2.8.RELEASE</version>
</dependency>
修改?bootstrap-dev.yaml
增加配置,
zipkin:
base-url: http://192.168.1.115:8112/
sender:
type: web
enabled: true
sleuth:
sampler:
probability: 1
問題及大坑
啟動后
看著有點變化,測試后沒用,一通找文檔
最后到了官方文檔?
Spring Cloud Sleuth Reference Documentation
?sleuth停止支持, springboot 3.0.x之后的版本已經(jīng)不再支持了,
Spring Cloud Sleuth will not work with Spring Boot 3.x onward. The last major version of Spring Boot that Sleuth will support is 2.x.
待尋找其他方案。
Micrometer Tracing 集成實現(xiàn)分布式鏈路追蹤
springboot 3.0.x之后,官方移除了對 sleuth的支持,將可觀測性這部分遷移到了?Micrometer? 項目中,下面實現(xiàn)這部分的功能,通過?Micrometer Tracing 實現(xiàn)日志以及通過 zipkin實現(xiàn)收集。
資料
Micrometer Tracing官方文檔
Micrometer Application Observability
sleuth遷移官方文檔
Spring Cloud Sleuth 3.1 Migration Guide · micrometer-metrics/tracing Wiki (github.com)
集成
依賴
需要下面的幾個依賴
引入依賴管理器
<micrometer-tracing.version>1.1.1</micrometer-tracing.version>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bom</artifactId>
<version>${micrometer-tracing.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
需要用到的依賴
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
?配置修改
基于之前biz模塊下面的4個應(yīng)用,都增加如下配置
management:
tracing:
sampling:
probability: 1.0
zipkin:
tracing:
endpoint: http://192.168.1.115:8112/api/v2/spans
connect-timeout: 3s
logging:
pattern:
level: ${spring.application.name:},%X{traceId:-},%X{spanId:-} %5p
注意:
endpoint為zipkin配置
格式配置必須要為:??http://{ip:port}/api/v2/spans,詳見ZipkinProperties
?日志格式為 應(yīng)用名+ traceId +spanId
測試
服務(wù)起來之后,還是調(diào)用biz-web下面的 接口,控制臺輸出的日志格式如下:
?查看 zipkin的控制臺已經(jīng)能看到日志的收集
Spring Boot Admin 集成實現(xiàn)服務(wù)監(jiān)控
功能:集成以實現(xiàn)健康 (Health)信息、內(nèi)存信息、JVM 系統(tǒng)和環(huán)境屬性、垃圾回收信息、日志設(shè)置和查看、定時任務(wù)查看、Spring Boot 緩存查看和管理等功能
前置準(zhǔn)備
準(zhǔn)備兩個服務(wù),一個是 admin server端,另一個用來做客戶端監(jiān)控
?配置修改
父工程
<spring.boot.admin.version>3.0.4</spring.boot.admin.version>
<!-- admin -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>${spring.boot.admin.version}</version>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${spring.boot.admin.version}</version>
</dependency>
admin工程
pom
<dependency>
<groupId>com.sy</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- admin -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>
配置文件
server:
port: 9002
spring:
application:
name: admin
management:
endpoint:
health:
show-details: always
客戶端consumer
pom
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
配置文件
spring:
application:
name: consumer
boot:
admin:
client:
url: http://localhost:9002
management:
endpoint:
health:
show-details: always
endpoints:
web:
exposure:
include: ["*"]
測試
分別啟動兩個服務(wù),訪問 admin的web界面
http://localhost:9002/
效果
?已經(jīng)成功啟動,并且可以看見兩個實例
點擊應(yīng)用墻
查看 consumer實例詳情
?可以看到更多詳細(xì)配置
至此,集成完畢?
集成Spring Authorization Server 與Spring Security Oauth2.1統(tǒng)一認(rèn)證
過程
這塊整體比較復(fù)雜,我專門開了一篇新文章,專門介紹概念與集成,鏈接在下面?文章來源:http://www.zghlxwxcb.cn/news/detail-520679.html
(305條消息) Spring Security Oauth2.1 最新版 1.1.0 整合 (基于 springboot 3.1.0)gateway 完成授權(quán)認(rèn)證_ricardo.M.Yu的博客-CSDN博客文章來源地址http://www.zghlxwxcb.cn/news/detail-520679.html
到了這里,關(guān)于Spring Cloud Alibaba 最新版本(基于Spring Boot 3.1.0)整合完整使用及與各中間件集成 Sleuth+Zipkin集成分布式鏈路追蹤的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!