文章目录
前言
对于练习时长两年半的Java练习生而言,微服务或许是大家接触的最普遍、最火热的软件架构,尤其是Spring Cloud系列技术栈。笔者初学时也是从微服务开始的,然而框架虽然简单易用,但毕竟是架构师或者第三方开源脚手架集成好的,我只会用,想要自己集成一套却没那么容易。本文源于笔者想要在实际项目中集成seata分布式事务的一个本地练习项目,想着干脆从0开始一步步集成一套基本的脚手架吧。
基础条件准备
IDE工具:IntelliJ IDEA
(笔者用的是2024最新版)
JDK:17
Maven:3.6以上
Nacos:2.0以上
上面这些用的基本工具自行安装哈,笔者这里就不展示了,应该没什么问题
主体项目结构
producer-module: 生产者服务模块
consumer-module: 消费者服务模块
gateway-module: 网关模块
api-module: 微服务api接口模块
common-module: 核心库模块
上面的几个模块中只有producer-module、consumer-module、gateway-module是springboot应用,有独立的启动类。本项目完成了gateway网关、openfeign、sentinel、seata分布式事务、mybatis-plus(包括自动填充字段、配置逻辑删除字段等)、mysql数据库等常见开发组件的集成整合工作
。废话不多说,下面详细展示搭建过程
项目地址
:microservice-project
Nacos配置和项目结构图示
笔者创建了一个新的命名空间:microservice-project
,没有使用默认的public
这些配置文件笔者已经导出成了压缩包上传到代码仓库中一起了,直接导入你自己的nacos中即可
数据库和脚本准备
seata数据库
在你的本地mysql或者你的mysql服务器上创建名字为seata
的数据库,在seata
数据库中执行如下脚本
-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
CREATE TABLE IF NOT EXISTS `global_table`
(
`xid` VARCHAR(128) NOT NULL,
`transaction_id` BIGINT,
`status` TINYINT NOT NULL,
`application_id` VARCHAR(32),
`transaction_service_group` VARCHAR(32),
`transaction_name` VARCHAR(128),
`timeout` INT,
`begin_time` BIGINT,
`application_data` VARCHAR(2000),
`gmt_create` DATETIME,
`gmt_modified` DATETIME,
PRIMARY KEY (`xid`),
KEY `idx_status_gmt_modified` (`status` , `gmt_modified`),
KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
-- the table to store BranchSession data
CREATE TABLE IF NOT EXISTS `branch_table`
(
`branch_id` BIGINT NOT NULL,
`xid` VARCHAR(128) NOT NULL,
`transaction_id` BIGINT,
`resource_group_id` VARCHAR(32),
`resource_id` VARCHAR(256),
`branch_type` VARCHAR(8),
`status` TINYINT,
`client_id` VARCHAR(64),
`application_data` VARCHAR(2000),
`gmt_create` DATETIME(6),
`gmt_modified` DATETIME(6),
PRIMARY KEY (`branch_id`),
KEY `idx_xid` (`xid`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(
`row_key` VARCHAR(128) NOT NULL,
`xid` VARCHAR(128),
`transaction_id` BIGINT,
`branch_id` BIGINT NOT NULL,
`resource_id` VARCHAR(256),
`table_name` VARCHAR(32),
`pk` VARCHAR(36),
`status` TINYINT NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',
`gmt_create` DATETIME,
`gmt_modified` DATETIME,
PRIMARY KEY (`row_key`),
KEY `idx_status` (`status`),
KEY `idx_branch_id` (`branch_id`),
KEY `idx_xid` (`xid`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
CREATE TABLE IF NOT EXISTS `distributed_lock`
(
`lock_key` CHAR(20) NOT NULL,
`lock_value` VARCHAR(20) NOT NULL,
`expire` BIGINT,
primary key (`lock_key`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);
seata数据库事务相关的脚本在seata安装路径下:D:\devSofts\seata\script\server\db,去自己的seata安装路径下找到执行即可
注意:这里数据库名为seata,和后面的 seata-server.properties文件中数据库配置命名一致
transaction_database数据库
在自己的mysql服务器上再创建名为transaction_database
,执行如下脚本
create table if not exists transaction_database.consumer
(
id bigint auto_increment
primary key,
name varchar(100) not null,
delete_flag int default 0 not null
)
charset = utf8mb4;
create table if not exists transaction_database.producer
(
id bigint auto_increment
primary key,
name varchar(100) not null,
create_time datetime not null,
update_time datetime null,
delete_flag int default 0 not null
)
charset = utf8mb4;
create table if not exists transaction_database.undo_log
(
id bigint auto_increment comment '主键ID'
primary key,
branch_id bigint not null comment '分支事务ID',
xid varchar(100) not null comment '全局事务唯一标识',
context varchar(128) not null comment '上下文',
rollback_info longblob not null comment '回滚信息',
log_status int not null comment '状态,0正常,1全局已完成(防悬挂)',
log_created datetime not null comment '创建时间',
log_modified datetime not null comment '修改时间',
constraint ux_undo_log
unique (xid, branch_id)
)
comment 'AT模式回滚日志表';
上面的数据库producer、consumer分别为笔者创建的业务相关的数据库,undo_log也是seata分布式事务用到的数据库
一、Spring Boot、Spring Cloud、Sping Cloud Alibaba
-
Spring Boot
:- Spring Boot 是一个基于 Spring 框架的简化新框架,它的设计目的是用来简化新Spring应用的初始搭建以及开发过程。
- 它使得配置Spring应用变得更加简单,同时也提供了很多非功能性特性,如内嵌服务器、安全、健康检查、指标等。
- Spring Boot 的主要特点是约定优于配置,通过starter依赖管理简化了第三方库的集成。
-
Spring Cloud
:- Spring Cloud 是一系列框架的集合,它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如配置管理、服务发现、断路器、路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态等。
- 它允许开发者将这些功能中的每一个都作为一个独立的服务进行开发,然后添加到应用中,从而避免了复杂的分布式系统开发。
-
Spring Cloud Alibaba
:- Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含了一系列已经准备好的微服务组件,包括服务发现注册、分布式配置中心、消息驱动能力等。
- 它集成了阿里巴巴开源项目Dubbo、Nacos、Sentinel等,提供与Spring Cloud 相似的微服务开发体验,同时利用阿里巴巴在微服务领域的经验提供了更加健壮的服务治理方案。
- 对于使用Java生态进行微服务开发的团队来说,Spring Cloud Alibaba 提供了一个更贴近中国开发者习惯的工具包。
注意:Spring Cloud 本身并不是一个开箱即用的框架,它是一套微服务规范,共有两代实现。
- Spring Cloud Netflix 是 Spring Cloud 的第一代实现,主要由 Eureka、Ribbon、Feign、Hystrix 等组件组成。
- Spring Cloud Alibaba 是 Spring Cloud 的第二代实现,主要由 Nacos、Sentinel、Seata 等组件组成。
说实话,阿里对国内Java相关的技术发展起到了很大的领头作用,提供了很多适合国人的开发工具和开发规范,笔者用的最多的微服务框架即是alibaba的这套。
二、seata安装
seata配置修改
windows下安装seata-server服务,这个网上有很多博客介绍,这里不再展示了,仅上传一个压缩包资源,压缩包中包含了1.7.0和1.8.0两个版本,笔者使用的是1.8.0版本,解压如下
进入conf目录下,打开application.yml文件
# Copyright 1999-2019 Seata.io Group.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
server:
port: 7091
spring:
application:
name: seata-server
logging:
config: classpath:logback-spring.xml
file:
path: ${log.home:${user.home}/logs/seata}
extend:
logstash-appender:
destination: 127.0.0.1:4560
kafka-appender:
bootstrap-servers: 127.0.0.1:9092
topic: logback_to_logstash
console:
user:
username: seata
password: seata
seata:
config:
# support: nacos, consul, apollo, zk, etcd3
type: nacos
nacos:
serverAddr: 127.0.0.1:8848
namespace: microservice-project
group: SEATA_GROUP
username: nacos
password: nacos
dataId: seata-server.properties
registry:
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: nacos
nacos:
application: seata-server
server-addr: 127.0.0.1:8848
group: SEATA_GROUP
namespace: microservice-project
cluster: default
username: nacos
password: nacos
store:
# support: file 、 db 、 redis
mode: db
session:
mode: db
lock:
mode: db
db:
datasource: durid
db-type: mysql
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/seata?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
user: root
password: 123456
min-conn: 10
max-conn: 100
global-table: global-table
branch-table: branch-table
lock-table: lock-table
distributed-lock-table: distributed_lock
query-limit: 1000
max-wait: 5000
# server:
# service-port: 8091 #If not configured, the default is '${server.port} + 1000'
security:
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
tokenValidityInMilliseconds: 1800000
ignore:
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login
其中的数据库信息,nacos配置相关信息根据自己的配置修改即可,注意上面的命名空间:namespace: microservice-project
,这个是笔者使用的Nacos命名空间,要对应上
Nacos新建配置文件seata-server.properties
#For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html
#Transport configuration, for client and server
transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableTmClientBatchSendRequest=false
transport.enableRmClientBatchSendRequest=true
transport.enableTcServerBatchSendResponse=false
transport.rpcRmRequestTimeout=30000
transport.rpcTmRequestTimeout=30000
transport.rpcTcRequestTimeout=30000
transport.threadFactory.bossThreadPrefix=NettyBoss
transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
transport.threadFactory.shareBossWorker=false
transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
transport.threadFactory.clientSelectorThreadSize=1
transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
transport.threadFactory.bossThreadSize=1
transport.threadFactory.workerThreadSize=default
transport.shutdown.wait=3
transport.serialization=seata
transport.compressor=none
#Transaction routing rules configuration, only for the client
service.vgroupMapping.default_tx_group=default
#If you use a registry, you can ignore it
service.default.grouplist=127.0.0.1:8091
service.enableDegrade=false
service.disableGlobalTransaction=false
#Transaction rule configuration, only for the client
client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.reportRetryCount=5
client.rm.tableMetaCheckEnable=true
client.rm.tableMetaCheckerInterval=60000
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.rm.sagaJsonParser=fastjson
client.rm.tccActionInterceptorOrder=-2147482648
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
client.tm.interceptorOrder=-2147482648
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
#For TCC transaction mode
tcc.fence.logTableName=tcc_fence_log
tcc.fence.cleanPeriod=1h
#Log rule configuration, for client and server
log.exceptionRate=100
#Transaction storage configuration, only for the server. The file, db, and redis configuration values are optional.
store.mode=file
store.lock.mode=file
store.session.mode=file
#Used for password encryption
store.publicKey=
#If `store.mode,store.lock.mode,store.session.mode` are not equal to `file`, you can remove the configuration block.
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
#These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block.
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&rewriteBatchedStatements=true
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
#These configurations are required if the `store mode` is `redis`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `redis`, you can remove the configuration block.
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.sentinel.sentinelPassword=
store.redis.maxConn=10
store.redis.minConn=1
store.redis.maxTotal=100
store.redis.database=0
store.redis.password=
store.redis.queryLimit=100
#Transaction rule configuration, only for the server
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
server.distributedLockExpireTime=10000
server.xaerNotaRetryTimeout=60000
server.session.branchAsyncQueueSize=5000
server.session.enableBranchAsyncRemove=false
server.enableParallelRequestHandle=false
#Metrics configuration, only for the server
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898
store相关的信息自行修改,包括db和redis相关连接配置,需要注意的是如下一行
#Transaction routing rules configuration, only for the client
service.vgroupMapping.default_tx_group=default
这个 default_tx_group 是默认的分布式事务组名称,这个可以随便写,但是后面的producer-module-dev.yml中的一些配置需要和此处对应上。
三、创建Microservice-Project项目
笔者要创建的是一个Spring Cloud微服务项目,所以需要一个Maven聚合项目把各个微服务组件聚合起来组成一个完整的项目。
打开IDEA 的New->Project
,选择 Maven Archetype
,设置好整个微服务项目的名称 Microservice-Project
JDK版本选择17,右击右边的Add填写Maven项目的GAV坐标信息
Group ID
:这是项目的唯一标识符,通常采用反向域名的形式来避免冲突,例如com.alibaba。Artifact ID
:表示具体项目的名称,它与Group ID一起构成了项目的坐标。Version
:指定项目的具体版本号,如1.0.0,2.3.1等
创建好的Maven项目的pom文件如下,如果groupId不是com.microservice这个值而是其他值,自行修改即可
<?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.microservice</groupId>
<artifactId>Microservice-Project</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
比较重要的是 <properties>标签里的内容,下面是一些解释
- <maven.compiler.source>: 指定了项目编译时所使用的Java源代码版本。在这个例子中,值为17表示使用Java 17的语法和特性。
- <maven.compiler.target>: 指定了输出的字节码版本。这里同样设置为17,意味着编译后的class文件将兼容Java 17运行环境。
- <project.build.sourceEncoding>: 定义了项目源代码的字符编码方式。设置为UTF-8确保了对各种字符的良好支持,包括中文和其他多语言文本。
注意:后续的一些依赖库版本管理也会在这里进行,更改版本时可以比较方便的找到
项目结构如下,没什么问题
注意:我们需要在pom文件中加入如下一行
<packaging>pom</packaging>
在Maven中,packaging
元素指定了构建项目时生成的包的类型。不同的packaging类型决定了Maven如何构建项目及其输出形式。以下是两种常见的packaging类型:
pom
:- pom类型的项目主要用于聚合其他Maven项目,本身并不编译任何Java代码或生成可执行 的JAR文件。
- 它主要用于管理和组织多个子模块或子项目的依赖关系和生命周期。
- 示例配置:
<packaging>pom</packaging>
- jar
:
- jar类型的项目会编译Java源代码,并将编译后的类文件打包成一个JAR文件。
- 这是最常见的Maven项目类型,适用于大多数Java应用程序和库。
- 示例配置:
<packaging>jar</packaging>
另外就是我们需要设置下IDEA针对当前项目的文件编码格式,File->Settins->Editor->File Encodings,防止一些文件比如yaml文件出现中文乱码
最顶级父工程 Microservice-Project
添加一些必要的基础依赖,为了统一子工程中的依赖版本,需要在最顶级父工程的pom文件中做好第三方各种依赖的版本控制,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>com.microservice</groupId>
<artifactId>Microservice-Project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud.version>2022.0.0</spring-cloud.version>
<spring-cloud-alibaba.version>2022.0.0.0</spring-cloud-alibaba.version>
<spring-boot.version>3.0.1</spring-boot.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- SpringCloudAlibaba 依赖配置-->
<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>
<!-- SpringBoot 依赖配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
加入了spring-cloud-alibaba-dependencies、spring-cloud-dependencies、spring-boot-dependencies
,并在上面的 <properties> 中规定了各个依赖的版本,这三个依赖本身都是一些常用依赖的合集,我们引入时不用担心其内部依赖的版本适配问题,但是这个三个依赖的版本要有一定的适配关系,具体版本适配关系请参考 spring cloud alibaba
官方网址:Spring Cloud Alibaba
除了以上部分,最顶级父工程文件还需要添加如下部分
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<basedir/>
<buildDirectory/>
<mainOutputDirectory/>
<outputDirectory/>
<projectArtifact/>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
maven-compiler-plugin
:Maven 构建过程中使用的插件,这个插件主要是编译Java源代码spring-boot-maven-plugin
: 这个插件Spring Boot 应用程序的构建和打包,加在这里是为了统一控制版本,方便子模块引用
需要注意的是下面这个部分
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
这个配置的作用是让当前模块在打包时打包成一个可执行的jar包,当然是子模块为Spring Boot应用时需要显示的在子模块中加上。笔者使用的Spring Boot版本是3.0.1,如果是3.0.2或者之后的Spring Boot版本时,这个配置甚至直接失效飘红,3.0.1其实也是没必要加的,spring-boot-maven-plugin会自动将其打包成可执行的jar包,前提是你的模块有springboot启动器(即启动类)。
四、创建api-module聚合Maven
笔者为本项目设置了一个api接口模块,由于可能会存在多个模块的接口,所以api-module
是一个Maven聚合模块,在其下继续建立各个微服务模块对应的api接口模块
api-module模块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>
<parent>
<groupId>com.microservice</groupId>
<artifactId>Microservice-Project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>api-module</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>consumer-api-module</module>
</modules>
</project>
可以看到其聚合了consumer-api-module
模块,consumer-api-module
就是consumer-module
模块对外提供的远程接口服务consumer-api-module
模块的内容如下
<?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>
<groupId>com.microservice</groupId>
<artifactId>api-module</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>consumer-api-module</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>consumer-api-module</name>
<description>consumer-api-module消费者接口</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- SpringCloud Openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- SpringCloud Loadbalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!--核心库core-->
<dependency>
<groupId>com.microservice</groupId>
<artifactId>common-core</artifactId>
<scope>compile</scope>
</dependency>
<!--lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
其中的代码,笔者这里就不展示了,具体从代码仓库查看即可
五、创建common-module
这个模块是一个核心类库模块,和api-module类似,common-module也是一个Maven聚合模块
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>
<parent>
<groupId>com.microservice</groupId>
<artifactId>Microservice-Project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>common-module</artifactId>
<packaging>pom</packaging>
<modules>
<module>common-core</module>
</modules>
</project>
其中的子模块common-core
子模块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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.microservice</groupId>
<artifactId>common-module</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>common-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>common-core</name>
<description>common-core核心模块</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Apache Lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- Commons Io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<!-- Spring Context Support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!--mybatis-plus依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
</dependencies>
</project>
其中的代码笔者不展示了
六、创建gateway-module模块
gateway就是做网关路由转发的,可以用来限流,安全控制等等,笔者这里没有搞得很复杂,单纯只是用来做路由的统一转发
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.microservice</groupId>
<artifactId>Microservice-Project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>gateway-module</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway-module</name>
<description>gateway-module网关模块</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!--gateway网关模块依赖,引入后无须再引入spring-boot-starter-web,否则启动不了-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--包含了很多测试库工具,非必须强制引入-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--nacos服务发现中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--nacos配置中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--必须引入,否则会无法读取nacos上的配置信息,注意你的配置文件名也要是bootstrap-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!--必须要引入负载均衡,请求通过gateway的路由配置转发到服务提供者时需要负载均衡lb://service-name,否则报错503-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
注意:spring-cloud-starter-gateway
依赖引入后无需再引入spring-boot-starter-web
,因为前者已经包含了后者,再引入便会发生冲突,启动报错
yml内容
spring:
application:
name: gateway-module
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
username: nacos
password: nacos
namespace: microservice-project
server-addr: localhost:8848
config:
file-extension: yml
username: nacos
password: nacos
namespace: microservice-project
server-addr: localhost:8848
group: DEFAULT_GROUP
import-check:
enabled: false
# 共享配置
shared-configs:
- share-config-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
server:
port: 8080
另外在Nacos上建立一个配置文件: gateway-module-dev.yml
,配置上需要其他服务的路由转发策略配置
spring:
cloud:
gateway:
discovery:
locator:
lowerCaseServiceId: true
enabled: true
routes:
- id: producer-module
uri: lb://producer-module
predicates:
- Path=/producer/**
filters:
- StripPrefix=1
- id: consumer-module
uri: lb://consumer-module
predicates:
- Path=/consumer/**
filters:
- StripPrefix=1
七、创建producer-module
鼠标放在 Microservice-Project
文件目录上右击 New->Module,选择Spring Boot应用,填写好关键信息
pom文件修改
这个producer-module
是一个Spring Boot应用了,但是其应该是作为Microservice-Project
的一个子模块,所以我们需要对其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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.microservice</groupId>
<artifactId>Microservice-Project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>producer-module</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>producer-module</name>
<description>producer-module生产者模块</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!--springboot的web应用必须依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--包含了很多测试库工具,强制引入-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
可以看到 <parent>标签中的变化,变成其父模块Miroservice-Project的信息,一般来说groupId是整个项目中所有模块统一不变的,而artifactId则根据每个模块自身决定,一般就是模块的名称。
其中的两个spring-boot-starter-web和spring-boot-starter-test也是从父工程pom文件继承下来,不用显示指定版本了。最后的<build>表明这个是一个Spring Boot应用。
<finalName>${project.artifactId}</finalName>
则是规定了打包后的jar包名称producer-module.jar
,如果不写这个配置,则打包后的名称默认为为artifactId+version.jar,即为 producer-module-0.0.1-SNAPSHOT.jar
,很长,所以还是加上的好。
另外,顶级父工程Microservice-Project的pom文件需要加入如下内容,才能真正的作为Maven聚合工程,后续再有其他子模块,也需要加入这个<modules>中
<modules>
<module>producer-module</module>
</modules>
引入nacos依赖
因为所有的配置和服务注册均是放在Nacos上的,所以producer-module
模块的pom文件需要引入如下三个依赖
<!--nacos服务发现中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--nacos配置中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--必须引入,否则会无法读取nacos上的配置信息,注意你的yml配置文件名也要是bootstrap或者bootstrap开头-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
bootstrap.yml文件配置
点开Resource目录下可以看到applications.properties文件
将其改名为bootstrap.yml
(bootstrap.yaml也可以),并写入如下内容
spring:
application:
name: producer-module
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
username: nacos
password: nacos
server-addr: localhost:8848
namespace: microservice-project
config:
username: nacos
password: nacos
namespace: microservice-project
server-addr: localhost:8848
group: DEFAULT_GROUP
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- share-config-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
server:
port: 8081
上面的配置主要是配置了nacos作为服务发现和配置中心的信息,以及一个共享配置shared-configs。
启动类添加注解@EnableDiscoveryClient
@EnableDiscoveryClient 是 Spring Cloud 中的一个注解,用于启用服务发现客户端的功能。具体来说,它有以下几个作用:
服务注册与发现
:
当一个微服务应用使用 @EnableDiscoveryClient 注解时,该应用会自动注册到服务发现服务器(如 Eureka、Consul 或 Nacos)上。
同时,该应用也可以通过服务发现服务器获取其他服务的信息,并进行调用。自动配置
:
该注解会自动配置一些必要的组件,例如服务发现客户端实现类和服务实例注册器。
它会根据配置自动选择合适的服务发现客户端实现,比如 Nacos Discovery Client。简化开发
:
使用 @EnableDiscoveryClient 可以简化服务发现相关的开发工作,无需手动编写复杂的注册与发现逻辑。
这个注解非常重要,如果不加,就没法使用Nacos实现服务的自动注册发现功能。至于为什么加了@EnableDiscoveryClient
注解的启动类,就会自动注册到Nacos,笔者这里不做探讨。原理也不复杂,其实就是我们引入的Nacos服务发现依赖,其中有一个 NacosDiscoveryClient
类实现了DiscoveryClient接口,这个就是Spring Cloud中服务注册与发现相关的处理接口,具体可以阅读这篇文章:深入理解DiscoveryClient
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
Nacos新建命名空间microservice-project
注意命名空间ID和命名空间名称,笔者这里都是一致的。我们的yml配置中的 namespace: microservice-project
其实是指命名空间ID而不是命名空间名称,这点要知晓。
producer-module-dev.yml配置文件
在配置管理中点击选中命名空间 microservice-project
新建一个Data Id名称为producer-module-dev.yml
的配置文件,初步加入数据库连接配置,数据源使用得是阿里巴巴得druid
spring:
datasource:
url: jdbc:mysql://localhost:3306/transaction_database?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
Nacos上创建的默认配置文件名就是<应用名称>.<环境>.<扩展名>
,具体如下
引入mybatis-plus、mysql、druid依赖
由于要使用到数据库,所以需要引入这三个依赖,笔者的习惯是把所有的依赖现在顶级父工程的pom文件中引入,使用<dependencyManagement>统一管理版本,、子模块中需要用到时再引入
以下是Microservice-Project的pom文件引入内容
<!--mysql数据库连接驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybaits-plus.version}</version>
</dependency>
上面的本版本<properties>加入如下内容
producer-module的pom文件下再引入这三个依赖
<!--mysql数据库连接驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
引入openfeign依赖
和上面的操作一样,但是父工程中的**spring-cloud-alibaba-dependencies
**依赖集已经包含了,无需在父工程中再显示引入
直接在producer-module子模块中引入依赖即可
<!--openfeign依赖,实现服务的远程调用-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 使用openfeign 负载均衡 必须引入loadbalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
启动类添加@EnableFeignClients
这里是producer-module模块调用openfeign接口发起http请求到consumer-module模块,所以producer-module模块的启动类必须添加注解
@EnableFeignClients(basePackages = "com.microservice.api")
后面的basePackages是为了扫描到api接口
引入seata依赖
Microservice-Project父工程pom引入如下
<!--seata依赖-->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>${seata.starter.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>2021.0.5.0</version>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
producer-module模块的pom文件引入内容如下
<!--seata依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</dependency>
引入sentinel依赖
本例中需要演示微服务之间接口调用发生异常时服务降级的方法,需要用到alibaba的一款开源工具sentinel(lombok依赖是顺带引入的,不属于sentinel),sentinel也是在**spring-cloud-alibaba-dependencies
**中包含了,父模块无需引入
<!--lombok依赖,简化代码,不用写getter、setter等方法-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!--调用远程服务异常时降级,本依赖一般加在服务调用者模块pom中-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
到这里为止,producer-module模块的依赖集成工作算是结束了,现在回过头再把Nacos上的produce-module-dev.yml配置补充完整
spring:
datasource:
url: jdbc:mysql://localhost:3306/transaction_database?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
mybatis-plus:
global-config:
db-config:
logic-delete-field: delete_flag
logic-delete-value: 2
logic-not-delete-value: 0
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
type-aliases-package: com.feign.producer
mapper-locations: classpath:mapper/**/*.xml
seata:
registry:
type: nacos
nacos:
server-addr: localhost:8848
namespace: microservice-project
group: SEATA_GROUP
application: seata-server
username: nacos
password: nacos
tx-service-group: default_tx_group
service:
vgroup-mapping:
default_tx_group: default
data-source-proxy-mode: AT
注意上面的配置,和文章第二节点中描述的对应上
service:
vgroup-mapping:
default_tx_group: default
启动类完善
package com.microservice.producer;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages = "com.microservice.api")
@MapperScan("com.microservice.**.mapper")
public class ProducerModuleApplication {
public static void main(String[] args) {
SpringApplication.run(ProducerModuleApplication.class, args);
}
}
@EnableFeignClients(basePackages = "com.microservice.api")
是为了扫描api模块的包
@MapperScan("com.microservice.**.mapper")
则是配置扫描持久层对应的Mapper接口
八、创建consumer-module
pom依赖
本模块相对来说就简单了,直接展示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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.microservice</groupId>
<artifactId>Microservice-Project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>consumer-module</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>consumer-module</name>
<description>consumer-module消费者模块</description>
<properties>
<java.version>17</java.version>
</properties>
<packaging>jar</packaging>
<dependencies>
<!--common core核心模块引入-->
<dependency>
<groupId>com.microservice</groupId>
<artifactId>common-core</artifactId>
</dependency>
<!--springboot的web应用必须依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--包含了很多测试库工具,非必须强制引入-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--nacos服务发现中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--nacos配置中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--必须引入,否则会无法读取nacos上的配置信息,注意你的配置文件名也要是bootstrap-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!--lombok插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!--调用远程服务异常时降级,本依赖一般加在服务调用者模块pom中,本模块如果没有调用其他远程服务的模块,可以不引入-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--mysql数据库驱动相关依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--druid驱动-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!--seata依赖-->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
<!--mybatis-plus依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
注意:consumer-module模块为什么没有引入openfeign相关依赖?因为这个模块只充当了服务提供者的角色,producer-module模块通过调用api-module下的consumer-api-module中提供的远程服务接口来完成请求,所以producer-module模块需要引入openfeign相关依赖
consumer-module-dev.yml
同样的在Nacos上创建consumer-module-dev.yml配置文件
spring:
datasource:
url: jdbc:mysql://localhost:3306/transaction_database?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
mybatis-plus:
global-config:
db-config:
logic-delete-field: delete_flag
logic-delete-value: 2
logic-not-delete-value: 0
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
type-aliases-package: com.microservice.consumer
mapper-locations: classpath:mapper/**/*.xml
seata:
registry:
type: nacos
nacos:
server-addr: localhost:8848
namespace: microservice-project
group: SEATA_GROUP
application: seata-server
username: nacos
password: nacos
tx-service-group: default_tx_group
service:
vgroup-mapping:
default_tx_group: default
data-source-proxy-mode: AT
到这里所有模块的集成工作已经完成了,接下来的最后一节内容展示sentinel、openfeign、seata的分布式事务
九、功能演示
openfeign演示
在producer-module模块中通过api接口远程调用
地址为:http://localhost:8080/producer/message/handle
是通过gateway的8080端口进入,再路由转发到producer-module模块的服务
sentinel演示
在consumer-module服务编写会抛出异常的代码
再次调用会发现consumer-module模块抛出异常了
producer-module模块没有抛出异常
设置的feign异常降级回调如下
使用apifox工具请求测试,说明成功使用sentinel降级
seata分布式事务演示
调用地址:http://localhost:8080/producer/message/commit
分别在producer和consumer表生成了两条数据
接着远程调用上面的地址
把consumer模块的接口中添加上抛出异常的代码
请求后发现数据并没有生成了,seata分布式事务产生回滚
十、总结
以上就是笔者搭建微服务过程的教程,步骤稍显杂乱,但整个集成过程是清晰的,有问题评论区找我,尽量回复。