SpringCloud Alibaba - Sentinel篇

柔情只为你懂 2024-03-02 10:21 175阅读 0赞

一、Sentinel快速入门


image-20230920210017106

Sentinel官网地址:https://sentinelguard.io/zh-cn/index.html

Sentinel项目地址:https://github.com/alibaba/Sentinel

Sentinel是阿里巴巴开源的一款微服务流量治理组件,主要以流量为切入点,从流量限流、熔断降级、系统负载保护等多个维度来帮助开发者保障微服务的稳定性。(对标产品:Springcloud Hystrix 豪猪哥)

Sentinel分为两个部分:

  • 核心库(Java客户端):该jar包不依赖任何框架,能够运行于 Java 8 及以上版本,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
  • 控制台(Dashboard):相当于是Sentinel框架的管理中心,可以通过图形化界面对Sentinel进行配置、监控(可以对服务的流量、请求、响应等指标进行监控)等操作,从而更好地保障应用的稳定性和可靠性。

image-20230920213830678

两款熔断框架对比:









































功能 Sentinel Hystrix(豪猪哥)
线程隔离 信号量隔离 线程池隔离/信号量隔离
熔断策略 基于慢调用比例或异常比例 基于异常比例
限流 基于QPS,支持流量整形 有限的支持
Fallback 支持 支持
控制台 开箱即用,可配置规则、查看秒级监控、机器发现等 不完善
配置方式 基于控制台,重启后失效 基于注解或配置文件,永久生效

1. 启动sentinel-dashboard控制台


通过可视化更方便操作Sentinel。

1、下载sentinel-dashboard的jar包:https://github.com/alibaba/Sentinel/releases/tag/1.8.6

image-20230921001906722

2、使用命令行运行jar包的方式启动控制台:(或者构建镜像丢到容器中启动)

  1. java -Dserver.port=8090 -Dcsp.sentinel.dashboard.server=localhost:8090 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.6.jar

参数介绍:

  • -Dserver.port=8090:指定Sentinel控制台程序的端口为8090。
  • -Dcsp.sentinel.dashboard.server=localhost:8090:Sentinel控制台的访问地址,客户端会自动向该地址发送心跳包。
  • -Dproject.name=sentinel-dashboard:指定Sentinel控制台程序显示的名称。
  • 文档地址:https://github.com/alibaba/Sentinel/wiki/%E5%90%AF%E5%8A%A8%E9%85%8D%E7%BD%AE%E9%A1%B9

image-20230921004704830

3、访问sentinel的控制台:http://localhost:8090/,默认账号/密码:都是sentinel。

image-20230921005003769

登录成功后,便可查看控制台内部信息,默认会监控sentinel-dashboard服务本身:

image-20230921005247618

image-20230921005457889

image-20230921005524797

2. 构建微服务环境


数据库准备:

  1. CREATE DATABASE cloud_demo DEFAULT CHARACTER SET utf8mb4;
  2. use cloud_demo;
  3. DROP TABLE IF EXISTS `tb_user`;
  4. CREATE TABLE `tb_user` (
  5. `id` bigint(20) NOT NULL AUTO_INCREMENT,
  6. `username` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '收件人',
  7. `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地址',
  8. PRIMARY KEY (`id`) USING BTREE,
  9. UNIQUE INDEX `username`(`username`) USING BTREE
  10. ) ENGINE = InnoDB AUTO_INCREMENT = 109 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
  11. INSERT INTO `tb_user` VALUES (1, '潘掌柜', '黑龙江省牡丹江市');
  12. INSERT INTO `tb_user` VALUES (2, '文二狗', '陕西省西安市');
  13. INSERT INTO `tb_user` VALUES (3, '华沉鱼', '湖北省十堰市');
  14. INSERT INTO `tb_user` VALUES (4, '张必沉', '天津市');
  15. INSERT INTO `tb_user` VALUES (5, '郑爽爽', '辽宁省沈阳市大东区');
  16. INSERT INTO `tb_user` VALUES (6, 'kunkun', '山东省青岛市');
  17. DROP TABLE IF EXISTS `tb_order`;
  18. CREATE TABLE `tb_order` (
  19. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '订单id',
  20. `user_id` bigint(20) NOT NULL COMMENT '用户id',
  21. `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品名称',
  22. `price` bigint(20) NOT NULL COMMENT '商品价格',
  23. `num` int(10) NULL DEFAULT 0 COMMENT '商品数量',
  24. PRIMARY KEY (`id`) USING BTREE,
  25. UNIQUE INDEX `username`(`name`) USING BTREE
  26. ) ENGINE = InnoDB AUTO_INCREMENT = 109 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
  27. INSERT INTO `tb_order` VALUES (101, 1, 'Apple 苹果 iPhone 12 ', 699900, 1);
  28. INSERT INTO `tb_order` VALUES (102, 2, '雅迪 yadea 新国标电动车', 209900, 1);
  29. INSERT INTO `tb_order` VALUES (103, 3, '骆驼(CAMEL)休闲运动鞋女', 43900, 1);
  30. INSERT INTO `tb_order` VALUES (104, 4, '小米10 双模5G 骁龙865', 359900, 1);
  31. INSERT INTO `tb_order` VALUES (105, 5, 'OPPO Reno3 Pro 双模5G 视频双防抖', 299900, 1);
  32. INSERT INTO `tb_order` VALUES (106, 6, '美的(Midea) 新能效 冷静星II ', 544900, 1);
  33. INSERT INTO `tb_order` VALUES (107, 2, '西昊/SIHOO 人体工学电脑椅子', 79900, 1);
  34. INSERT INTO `tb_order` VALUES (108, 3, '梵班(FAMDBANN)休闲男鞋', 31900, 1);

image-20230921020130649

2.1 创建父工程

springboot版本2.7.12,springcloud版本2021.0.3。

创建maven工程,删除src目录,并向pom文件中引入一些依赖:

image-20230921011829295

image-20230921012711687

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <groupId>cn.z3inc</groupId>
  7. <artifactId>sentinel-demo</artifactId>
  8. <packaging>pom</packaging><!--pom代表聚合工程-->
  9. <version>1.0</version>
  10. <!-- springboot工程 -->
  11. <parent>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-parent</artifactId>
  14. <version>2.7.12</version>
  15. <relativePath/> <!-- lookup parent from repository -->
  16. </parent>
  17. <properties>
  18. <maven.compiler.source>8</maven.compiler.source>
  19. <maven.compiler.target>8</maven.compiler.target>
  20. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  21. <org.projectlombok.version>1.18.20</org.projectlombok.version>
  22. <spring-cloud.version>2021.0.3</spring-cloud.version>
  23. <spring-cloud-alibaba.version>2021.0.4.0</spring-cloud-alibaba.version>
  24. <mybatis-plus.version>3.4.3</mybatis-plus.version>
  25. <hutool.version>5.8.11</hutool.version>
  26. <mysql.version>8.0.23</mysql.version>
  27. </properties>
  28. <!-- 对依赖包进行管理 -->
  29. <dependencyManagement>
  30. <dependencies>
  31. <!-- spring cloud -->
  32. <dependency>
  33. <groupId>org.springframework.cloud</groupId>
  34. <artifactId>spring-cloud-dependencies</artifactId>
  35. <version>${spring-cloud.version}</version>
  36. <type>pom</type>
  37. <scope>import</scope>
  38. </dependency>
  39. <!-- spring cloud alibaba -->
  40. <dependency>
  41. <groupId>com.alibaba.cloud</groupId>
  42. <artifactId>spring-cloud-alibaba-dependencies</artifactId>
  43. <version>${spring-cloud-alibaba.version}</version>
  44. <type>pom</type>
  45. <scope>import</scope>
  46. </dependency>
  47. <!-- 数据库驱动 -->
  48. <dependency>
  49. <groupId>mysql</groupId>
  50. <artifactId>mysql-connector-java</artifactId>
  51. <version>${mysql.version}</version>
  52. </dependency>
  53. <!-- mybatis plus -->
  54. <dependency>
  55. <groupId>com.baomidou</groupId>
  56. <artifactId>mybatis-plus-boot-starter</artifactId>
  57. <version>${mybatis-plus.version}</version>
  58. </dependency>
  59. <!-- hutool工具类 -->
  60. <dependency>
  61. <groupId>cn.hutool</groupId>
  62. <artifactId>hutool-all</artifactId>
  63. <version>${hutool.version}</version>
  64. </dependency>
  65. </dependencies>
  66. </dependencyManagement>
  67. <dependencies>
  68. <!-- lombok -->
  69. <dependency>
  70. <groupId>org.projectlombok</groupId>
  71. <artifactId>lombok</artifactId>
  72. <version>${org.projectlombok.version}</version>
  73. </dependency>
  74. <!--单元测试-->
  75. <dependency>
  76. <groupId>org.springframework.boot</groupId>
  77. <artifactId>spring-boot-starter-test</artifactId>
  78. <scope>test</scope>
  79. </dependency>
  80. </dependencies>
  81. <build>
  82. <plugins>
  83. <!--打包跳过单元测试-->
  84. <plugin>
  85. <groupId>org.apache.maven.plugins</groupId>
  86. <artifactId>maven-surefire-plugin</artifactId>
  87. <configuration>
  88. <skipTests>true</skipTests>
  89. </configuration>
  90. </plugin>
  91. </plugins>
  92. </build>
  93. </project>

2.2 创建用户微服务

1、创建用户模块

image-20230921013420839

2、引入依赖:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <parent>
  7. <groupId>cn.z3inc</groupId>
  8. <artifactId>sentinel-demo</artifactId>
  9. <version>1.0</version>
  10. </parent>
  11. <artifactId>user-service</artifactId>
  12. <properties>
  13. <maven.compiler.source>8</maven.compiler.source>
  14. <maven.compiler.target>8</maven.compiler.target>
  15. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  16. </properties>
  17. <dependencies>
  18. <!--nacos注册中心依赖-->
  19. <dependency>
  20. <groupId>com.alibaba.cloud</groupId>
  21. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  22. </dependency>
  23. <!--单元测试-->
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-starter-test</artifactId>
  27. </dependency>
  28. <!--springmvc-->
  29. <dependency>
  30. <groupId>org.springframework.boot</groupId>
  31. <artifactId>spring-boot-starter-web</artifactId>
  32. </dependency>
  33. <!--mysql驱动-->
  34. <dependency>
  35. <groupId>mysql</groupId>
  36. <artifactId>mysql-connector-java</artifactId>
  37. </dependency>
  38. <!--mp-->
  39. <dependency>
  40. <groupId>com.baomidou</groupId>
  41. <artifactId>mybatis-plus-boot-starter</artifactId>
  42. </dependency>
  43. <!--lombok-->
  44. <dependency>
  45. <groupId>org.projectlombok</groupId>
  46. <artifactId>lombok</artifactId>
  47. </dependency>
  48. <!--hutool工具类-->
  49. <dependency>
  50. <groupId>cn.hutool</groupId>
  51. <artifactId>hutool-all</artifactId>
  52. </dependency>
  53. </dependencies>
  54. <!--打包插件-->
  55. <build>
  56. <plugins>
  57. <plugin>
  58. <groupId>org.springframework.boot</groupId>
  59. <artifactId>spring-boot-maven-plugin</artifactId>
  60. </plugin>
  61. </plugins>
  62. </build>
  63. </project>

3、编写application.yml文件配置:

  1. server:
  2. port: 9001
  3. spring:
  4. application:
  5. name: user-service #服务名称
  6. cloud:
  7. nacos:
  8. # nacos注册中心配置
  9. discovery:
  10. server-addr: 127.0.0.1:8848 #nacos服务器地址
  11. # 数据库配置
  12. datasource:
  13. driver-class-name: com.mysql.cj.jdbc.Driver
  14. url: jdbc:mysql://localhost:3306/cloud_demo?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
  15. username: root
  16. password: 123456
  17. # mp配置
  18. mybatis-plus:
  19. mmapper-locations: classpath:mapper/*.xml #mapper配置文件存放路径
  20. type-aliases-package: cn.z3inc.user.pojo # 类型别名(实体类所在包)
  21. configuration:
  22. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #配置标准sql输出
  23. map-underscore-to-camel-case: true #开启驼峰映射
  24. #日志级别
  25. logging:
  26. level:
  27. cn.z3inc: debug
  28. pattern:
  29. dateformat: MM-dd HH:mm:ss:SSS # 格式化输出日期

4、编写启动类:

  1. @SpringBootApplication
  2. @MapperScan("cn.z3inc.user.mapper")
  3. public class UserServiceApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run(UserServiceApplication.class, args);
  6. }
  7. }

5、编写业务:

实体类:

  1. package cn.z3inc.user.pojo;
  2. import lombok.Data;
  3. @Data
  4. public class User {
  5. private Long id;
  6. private String username;
  7. private String address;
  8. }

mapper接口:

  1. package cn.z3inc.user.mapper;
  2. import cn.z3inc.user.pojo.User;
  3. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  4. import org.apache.ibatis.annotations.Mapper;
  5. @Mapper
  6. public interface UserMapper extends BaseMapper<User> {
  7. }

service接口:

  1. package cn.z3inc.user.service;
  2. import cn.z3inc.user.pojo.User;
  3. import com.baomidou.mybatisplus.extension.service.IService;
  4. public interface UserService extends IService<User> {
  5. }
  6. package cn.z3inc.user.service.impl;
  7. import cn.z3inc.user.mapper.UserMapper;
  8. import cn.z3inc.user.pojo.User;
  9. import cn.z3inc.user.service.UserService;
  10. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  11. import org.springframework.stereotype.Service;
  12. @Service
  13. public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
  14. }

controller:

  1. package cn.z3inc.user.controller;
  2. import cn.z3inc.user.pojo.User;
  3. import cn.z3inc.user.service.UserService;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.*;
  6. @RestController
  7. @RequestMapping("/user")
  8. public class UserController {
  9. @Autowired
  10. private UserService userService;
  11. /**
  12. * 根据ID获取用户信息
  13. *
  14. * @param id 用户ID
  15. * @return
  16. */
  17. @GetMapping("/{id}")
  18. public User findById(@PathVariable("id") Long id) {
  19. return userService.getById(id);
  20. }
  21. /**
  22. * 修改用户信息
  23. *
  24. * @param user 用户信息
  25. */
  26. @PutMapping("/update")
  27. public void updateUser(@RequestBody User user) {
  28. userService.updateById(user);
  29. }
  30. /**
  31. * 根据ID删除用户
  32. *
  33. * @param id
  34. * @return
  35. */
  36. @DeleteMapping("/{id}")
  37. public void deleteUser(@PathVariable("id") Long id) {
  38. userService.removeById(id);
  39. }
  40. /**
  41. * 新增用户
  42. * @param user
  43. */
  44. @PostMapping("/save")
  45. public void saveUser(@RequestBody User user) {
  46. userService.save(user);
  47. }
  48. }

image-20230921153653979

6、启动nacos、用户微服务测试

  1. .\startup.cmd -m standalone

image-20230921102040129

image-20230921154742489

2.3 创建订单微服务

1、创建订单模块

image-20230921155433895

2、引入依赖:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <parent>
  7. <groupId>cn.z3inc</groupId>
  8. <artifactId>sentinel-demo</artifactId>
  9. <version>1.0</version>
  10. </parent>
  11. <artifactId>order-service</artifactId>
  12. <properties>
  13. <maven.compiler.source>8</maven.compiler.source>
  14. <maven.compiler.target>8</maven.compiler.target>
  15. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  16. </properties>
  17. <dependencies>
  18. <!-- openfeign 微服务远程调用 -->
  19. <dependency>
  20. <groupId>org.springframework.cloud</groupId>
  21. <artifactId>spring-cloud-starter-openfeign</artifactId>
  22. </dependency>
  23. <!-- loadbalancer 实现客户端做负载均衡 -->
  24. <dependency>
  25. <groupId>org.springframework.cloud</groupId>
  26. <artifactId>spring-cloud-starter-loadbalancer</artifactId>
  27. </dependency>
  28. <!--nacos注册中心依赖-->
  29. <dependency>
  30. <groupId>com.alibaba.cloud</groupId>
  31. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  32. </dependency>
  33. <!--单元测试-->
  34. <dependency>
  35. <groupId>org.springframework.boot</groupId>
  36. <artifactId>spring-boot-starter-test</artifactId>
  37. </dependency>
  38. <!--springmvc-->
  39. <dependency>
  40. <groupId>org.springframework.boot</groupId>
  41. <artifactId>spring-boot-starter-web</artifactId>
  42. </dependency>
  43. <!--mysql驱动-->
  44. <dependency>
  45. <groupId>mysql</groupId>
  46. <artifactId>mysql-connector-java</artifactId>
  47. </dependency>
  48. <!--mp-->
  49. <dependency>
  50. <groupId>com.baomidou</groupId>
  51. <artifactId>mybatis-plus-boot-starter</artifactId>
  52. </dependency>
  53. <!--lombok-->
  54. <dependency>
  55. <groupId>org.projectlombok</groupId>
  56. <artifactId>lombok</artifactId>
  57. </dependency>
  58. <!--hutool工具类-->
  59. <dependency>
  60. <groupId>cn.hutool</groupId>
  61. <artifactId>hutool-all</artifactId>
  62. </dependency>
  63. </dependencies>
  64. <!--打包插件-->
  65. <build>
  66. <plugins>
  67. <plugin>
  68. <groupId>org.springframework.boot</groupId>
  69. <artifactId>spring-boot-maven-plugin</artifactId>
  70. </plugin>
  71. </plugins>
  72. </build>
  73. </project>

3、编写application.yml配置:

  1. server:
  2. port: 9001
  3. spring:
  4. application:
  5. name: user-service #服务名称
  6. cloud:
  7. nacos:
  8. # nacos注册中心配置
  9. discovery:
  10. server-addr: 127.0.0.1:8848 #nacos服务器地址
  11. # 数据库配置
  12. datasource:
  13. driver-class-name: com.mysql.cj.jdbc.Driver
  14. url: jdbc:mysql://localhost:3306/cloud_demo?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
  15. username: root
  16. password: 123456
  17. # mp配置
  18. mybatis-plus:
  19. mmapper-locations: classpath:mapper/*.xml #mapper配置文件存放路径
  20. type-aliases-package: cn.z3inc.order.pojo # 类型别名(实体类所在包)
  21. configuration:
  22. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #配置标准sql输出
  23. map-underscore-to-camel-case: true #开启驼峰映射
  24. global-config:
  25. db-config:
  26. id-type: auto # 主键策略
  27. table-prefix: tb_ # 表名前缀配置
  28. #日志级别
  29. logging:
  30. level:
  31. cn.z3inc: debug
  32. pattern:
  33. dateformat: MM-dd HH:mm:ss:SSS # 格式化输出日期

4、编写启动类:

  1. package cn.z3inc.order;
  2. import org.mybatis.spring.annotation.MapperScan;
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.cloud.openfeign.EnableFeignClients;
  6. @EnableFeignClients(basePackages = "cn.z3inc.order.feign") //开启feign远程调用
  7. @SpringBootApplication
  8. @MapperScan("cn.z3inc.order.mapper")
  9. public class OrderServiceApplication {
  10. public static void main(String[] args) {
  11. SpringApplication.run(OrderServiceApplication.class, args);
  12. }
  13. }

5、编写业务:

实体类:

  1. //用户实体
  2. @Data
  3. public class User {
  4. private Long id;
  5. private String username;
  6. private String address;
  7. }
  8. // 订单实体
  9. @Data
  10. public class Order {
  11. private Long id;
  12. private String name;
  13. private Long price;
  14. private Integer num;
  15. private Long userId;
  16. @TableField(exist = false) // 排除数据表中不存在的字段
  17. private User user;
  18. }

mapper接口:

  1. package cn.z3inc.order.mapper;
  2. import cn.z3inc.order.pojo.Order;
  3. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  4. import org.apache.ibatis.annotations.Mapper;
  5. @Mapper
  6. public interface OrderMapper extends BaseMapper<Order> {
  7. }

service接口:

  1. package cn.z3inc.order.service;
  2. import cn.z3inc.order.pojo.Order;
  3. import com.baomidou.mybatisplus.extension.service.IService;
  4. public interface OrderService extends IService<Order> {
  5. //根据id查订单
  6. Order findById(Long id);
  7. }

feign接口:

  1. package cn.z3inc.order.feign;
  2. import cn.z3inc.order.pojo.User;
  3. import org.springframework.cloud.openfeign.FeignClient;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.PathVariable;
  6. /**
  7. * 用户服务Feign接口
  8. */
  9. @FeignClient("user-service")//指定要调用的服务名称
  10. public interface UserClient {
  11. /*
  12. 主要是基于SpringMVC的注解来声明远程调用的信息,比如:
  13. - 服务名称:userservice
  14. - 请求方式:GET
  15. - 请求路径:/user/{id}
  16. - 请求参数:Long id
  17. - 返回值类型:User
  18. */
  19. // 定义远程调用方法
  20. // 通过id查用户
  21. @GetMapping("/user/{id}") //调用对应controller的方法路径
  22. User findById(@PathVariable("id") Long id);// @PathVariable注解一定要指定参数名称,否则会报错
  23. }

service接口实现类:

  1. @Service
  2. public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
  3. @Autowired
  4. private UserClient userClient;
  5. @Override
  6. public Order findById(Long id) {
  7. Order order = super.getById(id);
  8. User user = userClient.findById(order.getUserId());//微服务远程调用
  9. order.setUser(user);
  10. return order;
  11. }
  12. }

controller:

  1. package cn.z3inc.order.controller;
  2. import cn.z3inc.order.pojo.Order;
  3. import cn.z3inc.order.service.OrderService;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.*;
  6. @RestController
  7. @RequestMapping("/order")
  8. public class OrderController {
  9. @Autowired
  10. private OrderService orderService;
  11. @GetMapping("/{orderId}")
  12. public Order findById(@PathVariable("orderId") Long orderId) {
  13. return orderService.findById(orderId);
  14. }
  15. }

6、测试:

image-20230921163715671

2.4 搭建网关微服务

1、创建网关模块

image-20230921164143848

2、引入依赖:

  1. <dependencies>
  2. <!--gateway网关-->
  3. <dependency>
  4. <groupId>org.springframework.cloud</groupId>
  5. <artifactId>spring-cloud-starter-gateway</artifactId>
  6. </dependency>
  7. <!--loadbalancer代替ribbon-->
  8. <dependency>
  9. <groupId>org.springframework.cloud</groupId>
  10. <artifactId>spring-cloud-starter-loadbalancer</artifactId>
  11. </dependency>
  12. <!--nacos注册中心-->
  13. <dependency>
  14. <groupId>com.alibaba.cloud</groupId>
  15. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  16. </dependency>
  17. </dependencies>

3、修改application.yml配置:

  1. server:
  2. port: 10010 # 网关的服务端口
  3. spring:
  4. application:
  5. name: gateway # 服务名称
  6. cloud:
  7. nacos:
  8. server-addr: localhost:8848 # nacos服务地址
  9. # 网关的配置
  10. gateway:
  11. # 跨域配置
  12. globalcors:
  13. cors-configurations:
  14. '[/**]':
  15. allowed-origin-patterns: "*"
  16. allowed-headers: "*"
  17. allow-credentials: true
  18. allowed-methods:
  19. - GET
  20. - POST
  21. - DELETE
  22. - PUT
  23. - OPTION
  24. # 网关路由配置
  25. routes:
  26. - id: user-service # 路由id
  27. uri: lb://user-service # 路由地址
  28. predicates: # 路由断言(匹配规则)
  29. - Path=/user/**
  30. - id: order-service
  31. uri: lb://order-service
  32. predicates:
  33. - Path=/order/**

4、编写启动类:

  1. package cn.z3inc.gateway;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. @SpringBootApplication
  5. public class GatewayApplication {
  6. public static void main(String[] args) {
  7. SpringApplication.run(GatewayApplication.class, args);
  8. }
  9. }

image-20230921202520666

5、测试:

image-20230921202050740

image-20230921202210196

3. 整合Sentinel


向订单微服中引入sentinel依赖,并连接sentinel-dashboard控制台进行监控。

1、引入sentinel依赖:

  1. <!--sentinel-->
  2. <dependency>
  3. <groupId>com.alibaba.cloud</groupId>
  4. <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
  5. </dependency>

2、修改订单服务的application.yml文件,添加sentinel控制台配置:

  1. spring:
  2. cloud:
  3. sentinel:
  4. transport:
  5. dashboard: localhost:8090 #控制台地址
  6. http-method-specify: true #开启请求方式前缀

image-20230922212832817

3、重启订单微服务

4、访问订单微服务接口:http://localhost:9002/order/102

5、访问sentinel-dashboard控制台,查看订单服务请求资源:http://localhost:8090

image-20230922113918905

image-20230922113445998

簇点链路:就是项目内的调用链路。链路中被Sentinel监控的每个接口就是一个资源。默认情况下Sentinel会监控SpringMVC的每一个Endpoint(http接口)。限流、熔断等都是针对簇点链路中的资源设置的,而资源名默认就是接口的请求路径。

二、请求限流


请求限流:限制访问接口的请求的并发量,避免服务因流量激增出现故障。

也是在sentinel控制台中配置,点击指定簇点链路后面的流控按钮,便可做限流处理:

image-20230922120334138

image-20230922120746025

使用 JMeter做压测:

(1)为测试计划创建线程组

image-20230922124550510

image-20230922125347750

(2)为线程组添加http取样器:

image-20230922125853615

image-20230922130155922

(3)为http取样器添加监听报告:

image-20230922130423316

(4)为http取样器添加查看结果树:

image-20230922130624205

(5)执行测试

image-20230922131029049

image-20230922131235248

image-20230922132722842

最后控制台查看监控结果:

image-20230922131159127

可以看出这个接口,通过的QPS为6,拒绝的QPS为4,符合我们的预期。

三、线程隔离


限流可以降低服务器压力,尽量减少因并发流量引起的服务故障的概率,但并不能完全避免服务故障。一旦某个服务出现故障,我们必须隔离对这个服务的调用,避免发生雪崩。

线程隔离:也叫做舱壁模式,模拟船舱隔板的防水原理。通过限定每个业务使用的线程数量,将故障业务隔离,避免故障扩散。(好处:即使服务崩了损失一部分线程,也不会影响到整个 tomcat 的资源)

image-20230922134001388

1. OpenFeign整合Sentinel


对订单服务的FeignClient接口做线程隔离。

修改订单服务的application.yml文件,配置开启Feign的sentinel功能:

  1. feign:
  2. sentinel:
  3. enabled: true # 开启feign对sentinel的支持

image-20230922135021576

重启订单服务,可以看到查询用户的FeignClient自动变成了一个簇点资源:

image-20230922135404445

2. 配置线程隔离


给查询用户feign接口的簇点资源配置并发线程数:(最多使用5个线程)

image-20230922140117810

image-20230922135836861

image-20230922200857542

执行JMeter测试脚步,每秒发送100个请求:

image-20230922140908719

测试结果如下:

image-20230922195816752

四、服务熔断


服务熔断:由 断路器 统计请求的异常比例或慢调用比例,如果超出阈值则会 熔断 该业务,则拦截该接口的请求。熔断期间,所有请求快速失败,全都走fallback降级逻辑,避免影响到当前服务。(Hystrix豪猪哥的做法:如果feign接口调不通,那就走feign接口实现类的逻辑,避免服务雪崩)

image-20230923144019242

1. 编写降级逻辑


跟豪猪哥的用法类似。

触发限流或熔断后的请求不一定要直接报错,也可以返回一些默认数据或者友好提示,用户体验会更好。

通常为FeignClient编写失败后的降级逻辑有两种方式:

  • 方式一:FallbackClass,无法对远程调用的异常做处理。
  • 方式二:FallbackFactory,可以对远程调用的异常做处理(推荐使用)。

1、为订单服务的UserClient定义降级处理类,实现FallbackFactory接口。

  1. package cn.z3inc.order.fallback;
  2. import cn.z3inc.order.feign.UserClient;
  3. import cn.z3inc.order.pojo.User;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.springframework.cloud.openfeign.FallbackFactory;
  6. /**
  7. * UserClient降级处理类
  8. *
  9. */
  10. @Slf4j
  11. public class UserClientFallback implements FallbackFactory<UserClient> {
  12. // 定义userclient降级逻辑
  13. @Override
  14. public UserClient create(Throwable cause) {
  15. return new UserClient(){
  16. @Override
  17. public User findById(Long id) {
  18. log.error("远程调用UserClient#findById方法出现异常,参数:{}", id, cause);
  19. return new User();
  20. }
  21. };
  22. }
  23. }

image-20230923151519698

2、创建一个配置类,把UserClientFallback注册为一个Bean:

  1. package cn.z3inc.order.config;
  2. import cn.z3inc.order.fallback.UserClientFallback;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.springframework.context.annotation.Bean;
  5. @Slf4j
  6. public class DefaultFeignConfig {
  7. @Bean
  8. public UserClientFallback userClientFallback() {
  9. return new UserClientFallback();
  10. }
  11. }

3、在UserClient中配置刚才创建的降级处理类:

  1. /**
  2. * 用户服务Feign接口
  3. */
  4. @FeignClient(value = "user-service", //指定要调用的服务名称
  5. configuration = DefaultFeignConfig.class, // 指定Feign的配置类
  6. fallbackFactory = UserClientFallback.class // 指定回退工厂类
  7. )
  8. public interface UserClient {

image-20230923152127413

4、重启订单服务,将用户服务停掉&测试:

image-20230923152307420

2. 服务熔断


当远程调用的服务挂掉后,直接走降级逻辑,避免影响到当前服务。也就是将feign接口进行熔断。当远程调用服务恢复正常后,再允许调用该接口。这其实就是断路器的工作模式了。

Sentinel中的断路器不仅可以统计某个接口的慢请求比例,还可以统计异常请求比例。当这些比例超出阈值时,就会熔断该接口,即拦截访问该接口的一切请求,降级处理;当该接口恢复正常时,再放行对于该接口的请求。
断路器的工作状态切换有一个状态机来控制:
47383fb3c199772b2fafc3e1a42c3818.jpeg
状态机包括三个状态:

  • closed:关闭状态,断路器放行所有请求,并开始统计异常比例、慢请求比例。超过阈值则切换到open状态
  • open:打开状态,服务调用被熔断,访问被熔断服务的请求会被拒绝,快速失败,直接走降级逻辑。Open状态持续一段时间后会进入half-open状态
  • half-open:半开状态,放行一次请求,根据执行结果来判断接下来的操作。

    • 请求成功:则切换到closed状态
    • 请求失败:则切换到open状态

我们可以在控制台通过点击簇点链路后的熔断按钮来配置熔断策略:(持久化需要写到nacos配置文件里)

image-20230923153302326

image-20230923153424668

这种是按照慢调用比例来做熔断,上述配置的含义是:

  • RT超过200毫秒的请求调用就是慢调用
  • 统计最近1000ms内的最少5次请求,如果慢调用比例不低于0.5,则触发熔断
  • 熔断持续时长20s

使用jmeter测试:

image-20230923154511253

image-20230923154811934

发表评论

表情:
评论列表 (有 0 条评论,175人围观)

还没有评论,来说两句吧...

相关阅读