1、新建maven项目

在cloud-test pom.xml文件中导入基础包
xml
<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-test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>cloud-test</name>
<url>http://maven.apache.org</url>
<modules>
<module>order-server</module>
<module>product-server</module>
<module>model</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/>
</parent>
<properties>
<maven.complier.source>17</maven.complier.source>
<maven.complier.target>17</maven.complier.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud.version>2021.0.5</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<!--这些是cloud基础包-->
<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>
<!--这些是cloud基础包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.35</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.43</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2、配置nacos注册中心
2.1、启动nacos服务
启动文件startup.cmd下
bash
#默认cluster 集群版,standalone单机版
set MODE="standalone"
3、product-server服务

导入需要maven
xml
<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>org.example</groupId>
<artifactId>cloud-test</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>product-server</artifactId>
<packaging>jar</packaging>
<name>product-server</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<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>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
application.yml
yaml
server:
port: 8078
spring:
application:
name: product-server
#指定了nacos配置管理中数据源的配置文件
config:
import:
- nacos:database.yml?group=order
cloud:
#配置nacos
nacos:
server-addr: 127.0.0.1:8848
config:
# 指定命名空间
namespace: dev

controller
java
@RequestMapping("/product")
@RestController
public class ProductController {
@Autowired
private ProductService productService;
@Value("${server.port}")
private String port;
@RequestMapping("getById")
public String getById(@RequestParam("id") Integer id) {
System.out.println("当前服务端口号: " + port);
ProductDo productById = productService.getProductById(id);
return productById.toString()+"==端口号:"+port;
}
}
4、order-server服务

pom.xml
xml
<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>org.example</groupId>
<artifactId>cloud-test</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>order-server</artifactId>
<packaging>jar</packaging>
<name>order-server</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<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>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
application.yml
yaml
server:
port: 8077
spring:
application:
name: order-server
cloud:
nacos:
server-addr: 127.0.0.1:8848
ProductFeign
java
package org.example.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(value = "product-server", path = "product")
public interface ProductFeign {
@RequestMapping("getById")
String getById(@RequestParam("id") Integer id);
}
OrderController
java
@RequestMapping("/api/order")
@RestController
public class OrderController {
@Autowired
private ProductFeign productFeign;
@RequestMapping("create")
public String create(@RequestParam(value = "uId", required = false) Integer uId,
@RequestParam(value = "pId", required = false) Integer pId) {
return productFeign.getById(pId);
}
}
注意启动文件上必须加上@EnableFeignClients注解
java
@EnableFeignClients
@SpringBootApplication
public class OrderApplication
{
public static void main( String[] args )
{
SpringApplication.run(OrderApplication.class, args);
}
}
到这步就可以先实现openfeign调用nacos服务实例了(openfeign默认轮询负载均衡)
5、order-server整合Sentinel
在order-server服务中添加依赖
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
nacos中新增Sentinel限流配置

bash
[
{
"resource": "orderCreate", // 资源名(要限流的方法名/接口名)
"limitApp": "default", // 限制的调用方(default=不区分调用方,所有应用都限制)
"grade": 1, // 限流阈值类型(0=线程数,1=QPS)
"count": 1, // 单机阈值(每秒最多允许 1 个请求)
"strategy": 0, // 调用关系限流策略(0=直接,1=根据调用方,2=根据链路)
"controlBehavior": 0, // 流控效果(0=快速失败,1=预热,2=排队等待)
"clusterMode": false // 是否集群限流(false=单机限流)
}
]
nacos中新增Sentinel降级配置

配置application.yml 将Sentinel持久化到nacos中
yaml
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
datasource:
# 流控规则数据源
flow:
nacos:
server-addr: 127.0.0.1:8848 # Nacos 地址
dataId: service-order-flow-rules
groupId: DEFAULT_GROUP
rule-type: flow
data-type: json
# 熔断规则数据源
degrade:
nacos:
server-addr: 127.0.0.1:8848 # Nacos 地址
dataId: service-order-degrade-rules
groupId: DEFAULT_GROUP
rule-type: degrade
data-type: json
启动order-server服务之后,调用接口,就自动配置到Sentinel中了。

6、整合seata
在order-server和product-server服务中引入依赖
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
在cloud_product表和cloue_order表中 新增一个undo_log表
bash
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 DEFAULT CHARSET=utf8;
新建seata数据库
bash
-- -------------------------------- 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);
在order-server和product-server 中application.yml新增配置
yaml
spring:
alibaba:
seata:
tx-service-group: default_tx_group
seata:
registry:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
application: seata-server
group: SEATA_GROUP
config:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
application: seata-server
group: SEATA_GROUP
测试分布式事务
加上 @GlobalTransactional注解:
java
@RequestMapping("/api/order")
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
@RequestMapping("create")
@SentinelResource(value = "orderCreate", blockHandler = "createBlockHandler")
public String create(@RequestParam(value = "uId", required = false) Integer uId,
@RequestParam(value = "pId", required = false) Integer pId) {
return orderService.createOrder(uId, pId, 1);
}
public String createBlockHandler(Integer uId, Integer pId, BlockException e) {
return "新增order被限流,uId=" + uId;
}
}
java
@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderDo> implements OrderService {
@Resource
private ProductFeign productFeign;
@Override
@GlobalTransactional
@Transactional
public String createOrder(Integer userId, Integer pid, Integer total) {
OrderDo order = new OrderDo();
order.setCount(total);
order.setStorageId(pid);
baseMapper.insert(order);
//
log.info("扣减余额:"+Thread.currentThread().getName());
productFeign.deduct(pid, total);
int i = 1/0;
return "新增订单成功";
}
}
最终结果cloue_order表未新增,cloud_product表未修改。
7、整合gateway
新建gateway项目。

导入依赖
xml
<dependencies>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
修改application.yml
yaml
server:
port: 8055
spring:
application:
name: gateway-server
cloud:
nacos:
server-addr: 127.0.0.1:8848
gateway:
routes:
- id: order-api
uri: lb://order-server
predicates:
- Path=/api/order/**
- id: product-api
uri: lb://product-server
predicates:
- Path=/api/product/**
在order-server服务Controller中,新增一个方法
java
@RequestMapping("/api/order")
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
@RequestMapping("getOrder")
public String getOrder() {
return "getorder";
}