# 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 ![nacos_landscape.png](https://camo.githubusercontent.com/1c968a619d39e6d63fbe3d3dd70ee3a27f5da4a2bf084420a6cd3b5355f02495/68747470733a2f2f63646e2e79757175652e636f6d2f6c61726b2f302f323031382f706e672f31353931342f313533303531343338303535302d33313235316137392d303262622d343135352d626334662d3561396634333635353161322e706e67) > 下载地址: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 ![image-20210527101213924](asset\image-20210527101213924.png) ![image-20210527101253525](asset\image-20210527101253525.png) ### 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 ![image-20210527101351593](asset\image-20210527101351593.png) ![image-20210526185057830](asset\image-20210526185057830.png) 提示: 控制台的使用原理 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 访问 ![image-20210526222051676](asset\image-20210526222051676.png) ### 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 ![image-20210527111458283](asset\image-20210527111458283.png) ## 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 启动工程,通过浏览器访问服务进行测试 ![image-20210527144622969](asset\image-20210527144622969.png) # 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微服务,查看效果 ![image-20210527160925172](asset\image-20210527160925172.png) # 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服务,访问请求,观察容错效果 ![image-20210531233120578](\asset\image-20210531233120578.png) # 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 ![image-20210601111927367](asset\image-20210601111927367.png) 其次通过网关7000去访问service-order和service-item服务 ![image-20210601112122264](asset\image-20210601112122264.png) ![image-20210601112217184](asset\image-20210601112217184.png) ## 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 测试 ![image-20210601115751114](asset\image-20210601115751114.png) ## 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 ,看限流是否起作用。 正常 ![image-20210601143753630](asset\image-20210601143753630.png) 频繁请求 ![image-20210601143842387](asset\image-20210601143842387.png) 可以看到限流起作用了。 ### 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); // } } ``` ![image-20210607205830633](asset\image-20210607205830633.png) 配置服务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为例 ![image-20210601174818498](asset\image-20210601174818498.png) ### 5.2.4 访问zipkin的UI界面,观察效果 ![image-20210601175102706](asset\image-20210601175102706.png) ![image-20210601175157189](asset\image-20210601175157189.png) # 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 的配置内容贴上,如下发布就可 ![image-20210601183536922](asset\image-20210601183536922.png) ![image-20210601184626572](asset\image-20210601184626572.png) 这里注意:每当配置变更时,最好微服务重启一下 ### 6.1.5 启动程序进行测试 service-order ![image-20210601185528097](asset\image-20210601185528097.png) service-item ![image-20210601185619287](asset\image-20210601185619287.png) service-gateway ![image-20210601185708011](asset\image-20210601185708011.png) 可以访问,说明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 启动 微服务进行测试 ![image-20210601202828722](asset\image-20210601202828722.png) # 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 ```