# springcloud-alibaba
**Repository Path**: actual-combat-study/springcloud-alibaba
## Basic Information
- **Project Name**: springcloud-alibaba
- **Description**: 基于alibaba spring cloud分布式框架,学习巩固
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2021-06-03
- **Last Updated**: 2021-06-28
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 1. 微服务环境搭建
## 1. 1 模板准备
### 1.1.1 技术选型(alibaba)
SpringCloud Alibaba
Sentinel,GateWay,Sleuth,ZipKin,Nacos Config,Seata
### 1.1.2 模块设计
springcloud-alibaba 父工程
- temp-common 公共模块
- temp-order 订单微服务
- temp-item 商品微服务
- temp-gateway 服务网关微服务
### 1.1.3 部署列表
| 应用服务名称 | IP | 端口 | 说明 |
| ------------ | --------- | ---------- | ------------- |
| temp-gateway | localhost | 7000 | |
| temp-order | localhost | 8081 | |
| temp-item | localhost | 8181、8182 | 测试openfeign |
安装服务端中间件列表
| 中间件 | IP | 端口 | 说明 |
| ------------------------ | --------- | ---- | ---------------------------------------- |
| nacos discovery(1.4.1) | localhost | 8848 | 服务发现 |
| nacos config(1.4.1) | localhost | 8848 | 服务配置 |
| sentinel dashbord | localhost | 8080 | 服务容错(服务降级、服务限流、服务熔断) |
| zipkin server+sleuth | localhost | 9411 | 服务链路追踪 |
| feign | | | 负载均衡的HTTP客户端 |
| seata | | | 分布式事务 |
| mysql | localhost | 3306 | 存储 |
### 1.1.4 微服务调用
简单需求:保存订单前,需调用商品微服务查询商品信息,以便校验库存和价格。
调用方:temp-order
提供方:temp-item
## 1.2 环境安装
### 1.2.1 安装nacos

> 下载地址:https://github.com/alibaba/nacos/releases/tag/1.4.1
>
> 下载zip格式的安装包,然后解压当前版本nacos-server-1.4.1.zip
解压目录:./run_env
#### 1.2.1.1 启动nacos
Windows
```bash
#切换目录
cd ./run_env/nacos/bin
#命令启动
nacos/bin> ./startup.cmd -m standalone
```
注意:如果端口被占用,可以去nacos\conf\application.properties修改8848到其他未使用端口
#### 1.2.1.2 访问nacos
打开浏览器输入http://localhost:8848/nacos,即可访问服务, 默认密码是nacos/nacos


### 1.2.2 安装Sentinel控制台
Sentinel 提供一个轻量级的控制台, 它提供机器发现、单机资源实时监控以及规则管理等功能。
#### 1.2.2.1 下载jar包,解压到文件夹
https://github.com/alibaba/Sentinel/releases/download/1.8.1/sentinel-dashboard-1.8.1.jar
#### 1.2.2.2 启动控制台
```bash
# 直接使用jar命令启动项目(控制台本身是一个SpringBoot项目) java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 - Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.0.jar
```
#### 1.2.2.3 访问控制台
地址:http://localhost:8080/
默认用户名密码是 sentinel/sentinel


提示: 控制台的使用原理
Sentinel的控制台其实就是一个SpringBoot编写的程序。我们需要将微服务程序注册到控制台
上(即在微服务中指定控制台的地址, 并且还要开启一个跟控制台传递数据的端口, 控制台也可以通
过此端口调用微服务中的监控程序获取微服务的各种信息。)
#### 1.2.2.4 添加有关控制台的配置
修改temp-order的application.yml
```yml
spring:
cloud:
sentinel:
transport:
port: 9999 # 和控制台交流的端口
dashboard: localhost:8080 # 指定控制台服务的地址
```
### 1.2.3 安装ZipKin服务端
#### 1.2.3.1 下载ZipKin的jar包
https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=LATEST&c=exec
访问上面的网址,即可得到一个zipkin-server-2.12.9-exec.jar
#### 1.2.3.2 通过命令行,启动ZipKin Server
```bash
java -jar zipkin-server-2.12.9-exec.jar
```
#### 1.2.3.3 通过浏览器访问 http://localhost:9411 访问

### 1.2.4 安装Docker Mysql数据库
docker-compose.yaml
```yaml
version: '3'
services:
mysql_server:
container_name: mysql_temp
image: mysql:8.0.11
environment:
MYSQL_DATABASE: temp_db
MYSQL_USER: admin
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: rootpassword
expose:
- 3306
ports:
- 3306:3306
volumes:
# 启动脚本
- ./docker-compose/mysql/initdb:/docker-entrypoint-initdb.d/
# DB持久化
- ddd_mysql_db:/var/lib/mysql
volumes:
ddd_mysql_db:
driver: local
```
创建同级目录\docker-compose\mysql\initdb;并创建temp_db.sql
```sql
# CREATE DATABASE temp_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
USE temp_db;
SET CHARACTER_SET_CLIENT = utf8;
SET CHARACTER_SET_CONNECTION = utf8;
CREATE TABLE IF NOT EXISTS temp_item (
id bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
name varchar(30) NOT NULL COMMENT '商品名',
price decimal(9,2) NOT NULL COMMENT '价格',
stock_num int NOT NULL COMMENT '库存',
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='商品';
INSERT INTO temp_item VALUE(NULL,'iphone6',4000,50);
INSERT INTO temp_item VALUE(NULL,'iphone6s',4500,50);
INSERT INTO temp_item VALUE(NULL,'iphone7',5000,50);
INSERT INTO temp_item VALUE(NULL,'iphone7plus',5500,50);
```
安装并执行docker mysql
```bash
docker-compose up -d
```
## 1.3 创建父工程
创建一个maven工程,然后在pom.xml文件中添加以下内容
```xml
4.0.0
temp-common
temp-item
org.springframework.boot
spring-boot-starter-parent
2.3.2.RELEASE
com.temp
springcloud-alibaba
1.0-SNAPSHOT
pom
1.8
UTF-8
UTF-8
Hoxton.SR8
2.2.5.RELEASE
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
com.alibaba.cloud
spring-cloud-alibaba-dependencies
${spring-cloud-alibaba.version}
pom
import
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.cloud
spring-cloud-starter-sleuth
org.springframework.cloud
spring-cloud-starter-zipkin
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config
```
版本对应:
https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E
| Spring Cloud Alibaba Version | Sentinel Version | Nacos Version | RocketMQ Version | Dubbo Version | Seata Version | Spring Cloud Version | Spring Boot Version |
| ---------------------------- | ---------------- | ------------- | ---------------- | ------------- | ------------- | -------------------- | ------------------- |
| 2.2.5.RELEASE | 1.8.0 | 1.4.1 | 4.4.0 | 2.7.8 | 1.3.0 | Hoxton.SR8 | 2.3.2.RELEASE |
## 1.4 创建common模块
创建temp-common模块
### 1.4.1 在pom.xml中添加依赖
```xml
springcloud-alibaba
com.temp
1.0-SNAPSHOT
4.0.0
temp-common
org.springframework.boot
spring-boot-starter-data-jpa
org.projectlombok
lombok
com.alibaba
fastjson
${fastjson.version}
mysql
mysql-connector-java
${mysql.version}
5.1.6
1.2.56
14
14
```
### 1.4.2 创建实体类
Item.java
```java
package com.temp.po;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity(name = "temp_item")
@Data
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;//主键
private String name;//商品名称
private Double price;//商品价格
private Integer stockNum;//库存
}
```
Order.java
```java
package com.temp.po;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity(name = "temp_order")
@Data
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long oid;//订单id
private Integer uid;//用户id
private String uname;//用户名
private Integer itemid;//商品id
private String name;//商品名称
private Double price;//商品单价
private Integer number;//购买数量
}
```
## 1.5 创建商品微服务
创建一个名为temp-item模块
### 1.5.1 添加springboot依赖
```xml
springcloud-alibaba
com.temp
1.0-SNAPSHOT
4.0.0
temp-item
org.springframework.boot
spring-boot-starter-web
com.temp
temp-common
1.0-SNAPSHOT
14
14
```
### 1.5.2 创建工程的主类
```java
package com.temp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ItemApplication {
public static void main(String[] args) {
SpringApplication.run(ItemApplication.class, args);
}
}
```
### 1.5.3 创建配置文件application.yml
```yml
server:
port: 8181
spring:
application:
name: service-item
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/temp?useUnicode=true&characterEncoding=utf-8
username: root
password: root
jpa:
properties:
hibernate:
hbm2ddl:
auto: update
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
```
### 1.5.4 创建ItemDao接口
```java
package com.temp.dao;
import com.temp.po.Item;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* JPA接口
*/
public interface ItemDao extends JpaRepository- {
}
```
### 1.5.5 创建ItemService接口和实现类
ItemService.java
```java
package com.temp.service;
import com.temp.po.Item;
public interface ItemService {
Item queryItemById(Integer id);
}
```
ItemServiceImpl.java
```java
package com.temp.service;
import com.temp.dao.ItemDao;
import com.temp.po.Item;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ItemServiceImpl implements ItemService {
@Autowired
private ItemDao dao;
@Override
public Item queryItemById(Integer id) {
return dao.findById(id).get();
}
}
```
### 1.5.6 创建Controller
```java
package com.temp.controller;
import com.temp.po.Item;
import com.temp.service.ItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ItemController {
@Autowired
private ItemService itemService;
@RequestMapping("/item/{id}")
public Item query(@PathVariable Integer id) {
return itemService.queryItemById(id);
}
}
```
### 1.5.7 启动微服务并访问API

## 1.6 创建订单微服务
### 1.6.1 添加springboot依赖
```xml
springcloud-alibaba
com.temp
1.0-SNAPSHOT
4.0.0
temp-order
org.springframework.boot
spring-boot-starter-web
com.temp
temp-common
1.0-SNAPSHOT
14
14
```
### 1.6.2 创建工程的主类
```java
package com.temp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}
}
```
### 1.6.3 创建配置文件application.yml
```yml
server:
port: 8081
spring:
application:
name: service-order
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/temp_db?useUnicode=true&characterEncoding=utf-8
username: root
password: rootpassword
jpa:
properties:
hibernate:
hbm2ddl:
auto: update
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
```
### 1.6.4 创建OrderDao接口
```java
package com.temp.dao;
import com.temp.po.Order;
import org.springframework.data.jpa.repository.JpaRepository;
public interface OrderDao extends JpaRepository {
}
```
### 1.6.5 创建OrderService接口和实现类
OrderService.java
```java
package com.temp.service;
import com.temp.po.Order;
public interface OrderService {
public void save(Order order);
}
```
OrderServiceImpl.java
```java
package com.temp.service;
import com.temp.dao.OrderDao;
import com.temp.po.Order;
import org.springframework.beans.factory.annotation.Autowired;
@Service
public class OrderServiceImpl implements OrderService{
@Autowired
private OrderDao orderDao;
@Override
public void save(Order order) {
orderDao.save(order);
}
}
```
### 1.6.6 在原有主类基础上,追加RestTemplate
```java
package com.temp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}
/**
* 新追加的RestTemplate
* @return RestTemplate
*/
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
```
### 1.6.7 创建Controller
```java
package com.temp.controller;
import com.temp.po.Item;
import com.temp.po.Order;
import com.temp.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private OrderService orderService;
@GetMapping("/order/item/{id}")
public Order saveOrder(@PathVariable("id") Integer id){
Item item = restTemplate.getForObject(
"http://localhost:8181/item/"+id,Item.class);
Order order = new Order();
order.setUid(1);
order.setUname("订单包裹");
order.setItemid(item.getId());
order.setName(item.getName());
order.setPrice(item.getPrice());
order.setNumber(1);
orderService.save(order);
return order;
}
}
```
### 1.6.8 启动工程,通过浏览器访问服务进行测试

# 2. 服务治理(Nacos Discovery)
## 2.1 nacos注册服务
### 2.1.1 将商品微服务注册到nacos
进一步修改temp-item模块的代码,并注册到nacos服务上
#### 2.1.1.1 在主类上添加@EnableDiscoveryClient
```java
package com.temp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class ItemApplication {
```
#### 2.1.1.2 在application.yml中添加nacos地址
```yml
spring:
application:
name: service-item
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/temp_db?useUnicode=true&characterEncoding=utf-8
username: root
password: rootpassword
jpa:
properties:
hibernate:
hbm2ddl:
auto: update
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
#服务治理--nacos注册服务
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
```
#### 2.1.1.3 到nacos控制台查看是否注册成功
在订单微服务注册完,统一查看
### 2.1.2 将订单微服务注册到nacos
#### 2.1.2.1 在主类上添加@EnableDiscoveryClient和Fegin的注解
```java
package com.temp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients //开启Feigin
public class OrderApplication {
```
#### 2.1.2.2 在application.yml中添加nacos服务地址
```yml
server:
port: 8081
spring:
application:
name: service-order
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/temp_db?useUnicode=true&characterEncoding=utf-8
username: root
password: rootpassword
jpa:
properties:
hibernate:
hbm2ddl:
auto: update
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
#服务治理--nacos注册服务
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
```
#### 2.1.2.3 创建一个service,并使用Feigin实现微服务调用
ItemService.java
```java
package com.temp.service;
import com.temp.po.Item;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient("service-item")//声明调用的提供者名
public interface ItemService {
Item queryItemById(@PathVariable("id") Integer id);
}
```
#### 2.1.2.4 修改controller代码,并启动验证
```java
@Autowired
private RestTemplate restTemplate;
@Autowired
private OrderService orderService;
@Autowired
private ItemService itemService;
@GetMapping("/order/item/{id}")
public Order saveOrder(@PathVariable("id") Integer id){
// Item item = restTemplate.getForObject(
// "http://localhost:8181/item/"+id,Item.class);
// 基于OpenFeign的远程调用,默认集成Robbin实现负载均衡
Item item = itemService.queryItemById(id);
Order order = new Order();
order.setUid(1);
order.setUname("订单包裹");
order.setItemid(item.getId());
order.setName(item.getName());
order.setPrice(item.getPrice());
order.setNumber(1);
orderService.save(order);
return order;
}
```
#### 2.1.2.5 重启order微服务,查看效果

# 3. 服务容错Sentinel
## 3.1 微服务集成Sentinel
微服务集成Sentinel非常简单,只需要加入Sentinel的依赖即可
```java
package com.temp;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SentinelController {
@RequestMapping("/sentinel/test")
public String test(){
return "OK";
}
@RequestMapping("/sentinel/test2")
public String test2(){
return "OK-test2";
}
}
```
## 3.2 Feign整合Sentinel
### 3.2.1 在配置文件中开启Feign对Sentinel的支持
```yml
#服务治理--nacos注册服务
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
#开启Feign对Sentinel的支持
feign:
sentinel:
enabled: true
```
### 3.2.2 为容错的接口指定容错类
```java
import com.temp.po.Item;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//@FeignClient("service-item")=>@FeignClient(value = "service-item")
@FeignClient(value = "service-item")//声明调用的提供者名=>value用于指定调用nacos下哪个微服务
public interface ItemService {
@GetMapping(value="/item/{id}")//指定请求的URI部分
Item queryItemById(@PathVariable("id") Integer id);
}
```
### 3.2.3 修改Controller
```java
@RestController
@Slf4j
public class OrderController {
// @Autowired
// private RestTemplate restTemplate;
@Autowired
private OrderService orderService;
@Autowired
private ItemService itemService;
@GetMapping("/order/item/{id}")
public Order saveOrder(@PathVariable("id") Integer id){
// Item item = restTemplate.getForObject(
// "http://localhost:8181/item/"+id,Item.class);
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// 基于OpenFeign的远程调用,默认集成Robbin实现负载均衡
Item item = itemService.queryItemById(id);
Order order = new Order();
order.setUid(1);
order.setUname("订单包裹");
order.setItemid(item.getId());
order.setName(item.getName());
order.setPrice(item.getPrice());
order.setNumber(1);
// 暂时注释,防止频繁创建订单
// orderService.save(order);
return order;
}
}
```
### 3.2.4 停止所有temp-item服务,重启temp-order服务,访问请求,观察容错效果

# 4. 服务网关Gateway
## 4.1 快速入门
### 4.1.1 创建一个temp-gateway的模块,导入相关依赖
pom.xml
```xml
springcloud-alibaba
com.temp
1.0-SNAPSHOT
4.0.0
temp-gateway
14
14
org.springframework.cloud
spring-cloud-starter-gateway
```
### 4.1.2 创建主类
```java
package com.temp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args){
SpringApplication.run(GatewayApplication.class,args);
}
}
```
### 4.1.3 添加配置文件
```yml
server:
port: 7000
spring:
application:
name: temp-gateway
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yml
shared-dataids: temp-common-config.yml
refreshable-dataids: temp-common-config.yml
gateway:
discovery:
locator:
enabled: true # ゲートウェイが nacos でマイクロサービスを検出できるようにする
routes:
- id: temp_route
uri: lb://service-order # lb は、名前で nacos からマイクロサービスを取得し、負荷分散戦略に従うことです。
predicates:
- Path=/order-serv/**
filters:
- StripPrefix=1
```
### 4.1.4 启动项目,并通过网关去访问微服务
先查看nacos

其次通过网关7000去访问service-order和service-item服务


## 4.2 整合Nacos
目前在配置文件中写死了转发路径的地址,写死地址会带来很多问题,接下来我们从注册中心获取此地址。
### 4.2.1 加入nacos依赖
```xml
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
```
### 4.2.2 在主类上添加注解
```java
package com.temp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args){
SpringApplication.run(GatewayApplication.class,args);
}
}
```
### 4.2.3 修改配置文件
```yml
server:
port: 7000
spring:
application:
name: temp-gateway
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
# file-extension: properties
# shared-dataids: temp-gateway.properties
# refreshable-dataids: temp-gateway.properties
gateway:
discovery:
locator:
enabled: true
routes:
- id: item_route
uri: lb://service-item
predicates:
- Path=/item-serv/**
filters:
- StripPrefix=1
```
### 4.2.4 测试

## 4.3 网关限流
### 4.3.1 导入依赖
```xml
com.alibaba.csp
sentinel-spring-cloud-gateway-adapter
```
### 4.3.2 编写配置类
基于Sentinel的Gateway限流是通过其提供的Filter来完成的,使用时只需注入对应的SentinelGatewayFilter实例以及SentinelGatewayBlockExceptionHandler实例即可。
```java
public class GatewayConfiguration {
private final List viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(ObjectProvider
> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer){
this.viewResolvers =
viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
/**
* Initialize a current-limiting filter
*/
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter(){
return new SentinelGatewayFilter();
}
/**
* Configure initial current limiting parameters
*/
@PostConstruct
public void initGatewayRules(){
Set rules = new HashSet<>();
rules.add(
new GatewayFlowRule("item_route")// Resource name, corresponding to route id
.setCount(1) // Current limit threshold
.setIntervalSec(1) // Statistical time window, the unit is second, the default is 1 second
);
GatewayRuleManager.loadRules(rules);
}
/**
* Configure current limiting exception handler
* @return SentinelGatewayBlockExceptionHandler
*/
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler(){
return new SentinelGatewayBlockExceptionHandler(
viewResolvers,
serverCodecConfigurer
);
}
/**
* Custom current limit exception page
*/
@PostConstruct
public void initBlockHandlers(){
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public Mono handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map map = new HashMap<>();
map.put("code",0);
map.put("message","The interface is current limited");
return ServerResponse
.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(map));
}
};
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
}
```
### 4.3.3 测试
一秒内多次访问http://localhost:7000/item-serv/item/1 ,看限流是否起作用。
正常

频繁请求

可以看到限流起作用了。
### 4.3.4 配置类
把下面初始化部分注释掉,采用画面配置
```java
@Configuration
public class GatewayConfiguration {
private final List viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(ObjectProvider> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer){
this.viewResolvers =
viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
/**
* Initialize a current-limiting filter
*/
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter(){
return new SentinelGatewayFilter();
}
// /**
// * Configure initial current limiting parameters
// */
// @PostConstruct
// public void initGatewayRules(){
// Set rules = new HashSet<>();
// rules.add(
// new GatewayFlowRule("item_route")// Resource name, corresponding to route id
// .setCount(1) // Current limit threshold
// .setIntervalSec(1) // Statistical time window, the unit is second, the default is 1 second
// );
// rules.add(
// new GatewayFlowRule("order_route")// Resource name, corresponding to route id
// .setCount(1) // Current limit threshold
// .setIntervalSec(1) // Statistical time window, the unit is second, the default is 1 second
// );
// GatewayRuleManager.loadRules(rules);
// }
/**
* Configure current limiting exception handler
* @return SentinelGatewayBlockExceptionHandler
*/
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler(){
return new SentinelGatewayBlockExceptionHandler(
viewResolvers,
serverCodecConfigurer
);
}
// /**
// * Custom current limit exception page
// */
// @PostConstruct
// public void initBlockHandlers(){
// BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
// @Override
// public Mono handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
// Map map = new HashMap<>();
// map.put("code",0);
// map.put("message","The interface is current limited");
//
// return ServerResponse
// .status(HttpStatus.OK)
// .contentType(MediaType.APPLICATION_JSON)
// .body(BodyInserters.fromValue(map));
// }
// };
//
// GatewayCallbackManager.setBlockHandler(blockRequestHandler);
// }
}
```

配置服务service-gateway,追加以下配置:
```yml
spring:
cloud:
sentinel:
scg:
fallback:
mode: response
response-body: '{"code":403, "message":"限流了"}'
```
重启所有服务
# 5. 服务链路追踪Sleuth+ZipKin
## 5.1 Sleuth入门
加入依赖就行了,见父工程
## 5.2 Zipkin客户端集成
Zipkin客户端和Sleuth的集成非常简单,只需在微服务中添加其依赖和配置即可。
### 5.2.1 在每个微服务上添加依赖
> 加入依赖即可,见父工程
### 5.2.2 添加配置
```yml
spring:
application:
name: temp-gateway
zipkin:
base-url: http://127.0.0.1:9411/ #zipkin server of request address
discovery-client-enabled: false # Let nacos treat it as a URL, not as a service name
sleuth:
sampler:
probability: 1.0 #Sampled percentage
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
```
### 5.2.3 访问微服务
以gateway为例

### 5.2.4 访问zipkin的UI界面,观察效果


# 6. 服务配置Nacos Config
## 6.1 Nacos Config入门
### 6.1.1 搭建nacos环境
> 使用现有的nacos环境即可
### 6.1.2 引入nacos的依赖
> 加入依赖即可,见父工程
### 6.1.3 添加nacos config的配置
> 注意:不能使用原来的application.yml作为配置文件,而是新建一个bootstrap.yml作为配置文件
配置文件优先级(由高到低)
> bootstrap.properties -> bootstrap.yml -> application.properties -> application.yml
temp-item/src/resources/bootstrap.yml
```yml
spring:
application:
name: service-item
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 # nacos center address
file-extension: yaml # Configuration file format
```
### 6.1.4 在nacos中添加配置
直接把temp-item/src/resources/application.yml 的配置内容贴上,如下发布就可


这里注意:每当配置变更时,最好微服务重启一下
### 6.1.5 启动程序进行测试
service-order

service-item

service-gateway

可以访问,说明nacos config已经配置成功
## 6.2 Nacos Config高级
### 6.2.1 不同微服务共享配置(service-item,service-order)
> 不同微服务之间实现配置共享的原理类似于文件引入,就是定义一个公共配置,然后在当前配置中引入。
1. 在nacos中定义一个DataID为temp-common-service.yaml的配置,用于所有微服务共享
```yml
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/temp_db?useUnicode=true&characterEncoding=utf-8
username: root
password: rootpassword
jpa:
properties:
hibernate:
hbm2ddl:
auto: update
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
sentinel:
transport:
dashboard: 127.0.0.1:8888
zipkin:
base-url: http://127.0.0.1:9411/
discovery-client-enabled: false
sleuth:
sampler:
probability: 1.0
```
2 修改bootstrap.yaml
```yaml
server:
port: 8181
spring:
application:
name: service-item
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 # nacos center address
file-extension: yaml # Configuration file format
shared-dataids: temp-common-service.yaml
refreshable-dataids: temp-common-service.yaml
sentinel:
transport:
port: 8722
```
3 启动 微服务进行测试

# 7. 分布式事务Seata
## 7.1 安装Seata
### 7.1.1 下载Seata
https://github.com/seata/seata/releases/download/v1.4.2/seata-server-1.4.2.zip
### 7.1.2 修改配置文件
解压缩并进入conf目录,修改以下文件:
registry.conf
```conf
registry {
type = "nacos"
nacos {
application = "seata-server"
serverAddr = "127.0.0.1:8848"
group = "SEATA_GROUP"
namespace = "public"
cluster = "default"
username = "nacos"
password = "nacos"
}
}
config {
type = "nacos"
nacos {
serverAddr = "127.0.0.1:8848"
namespace = "public"
group = "SEATA_GROUP"
username = "nacos"
password = "nacos"
# dataId = "seataServer.properties"
}
}
```
config.txt(最初时无此文件,需要在seata-server-1.4.2创建)
注意:用于存放各种配置中心的初始化脚本,执行时都会读取 `config.txt`配置文件,并写入配置中心)
```txt
service.vgroup_mapping.service-item=default
service.vgroup_mapping.service-order=default
```
### 7.1.3 启动nacos初始化seata的配置
如果windows情况下,使用Git Bash Here来执行
从这里下载:https://github.com/seata/seata/blob/develop/script/config-center/nacos/nacos-config.sh 放到seata-server-1.4.2\conf
在git bash界面输入
```bash
sh nacos-config.sh -h 127.0.0.1 -p 8848 -g SEATA_GROUP -t public -u nacos -w nacos
$ sh nacos-config.sh -h 127.0.0.1 -p 8848 -g SEATA_GROUP -t public -u nacos -w nacos
set nacosAddr=127.0.0.1:8848
set group=SEATA_GROUP
Set service.vgroup_mapping.service-item=default successfully
Set service.vgroup_mapping.service-order=default successfully
=========================================================================
Complete initialization parameters, total-count:2 , failure-count:0
=========================================================================
Init nacos config finished, please start seata-server.
```
### 7.14 启动seata服务
```bash
cd bin
seata-server.bat -p 8900 -m file
```