SpringCloud Alibaba - Sentinel篇

news2024/11/18 9:25:33

一、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

两款熔断框架对比:

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

1. 启动sentinel-dashboard控制台


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

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

image-20230921001906722

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

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. 构建微服务环境


数据库准备:

CREATE DATABASE cloud_demo DEFAULT CHARACTER SET utf8mb4;

use cloud_demo;

DROP TABLE IF EXISTS `tb_user`;

CREATE TABLE `tb_user`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '收件人',
  `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `username`(`username`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 109 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

INSERT INTO `tb_user` VALUES (1, '潘掌柜', '黑龙江省牡丹江市');
INSERT INTO `tb_user` VALUES (2, '文二狗', '陕西省西安市');
INSERT INTO `tb_user` VALUES (3, '华沉鱼', '湖北省十堰市');
INSERT INTO `tb_user` VALUES (4, '张必沉', '天津市');
INSERT INTO `tb_user` VALUES (5, '郑爽爽', '辽宁省沈阳市大东区');
INSERT INTO `tb_user` VALUES (6, 'kunkun', '山东省青岛市');


DROP TABLE IF EXISTS `tb_order`;

CREATE TABLE `tb_order`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '订单id',
  `user_id` bigint(20) NOT NULL COMMENT '用户id',
  `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品名称',
  `price` bigint(20) NOT NULL COMMENT '商品价格',
  `num` int(10) NULL DEFAULT 0 COMMENT '商品数量',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `username`(`name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 109 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

INSERT INTO `tb_order` VALUES (101, 1, 'Apple 苹果 iPhone 12 ', 699900, 1);
INSERT INTO `tb_order` VALUES (102, 2, '雅迪 yadea 新国标电动车', 209900, 1);
INSERT INTO `tb_order` VALUES (103, 3, '骆驼(CAMEL)休闲运动鞋女', 43900, 1);
INSERT INTO `tb_order` VALUES (104, 4, '小米10 双模5G 骁龙865', 359900, 1);
INSERT INTO `tb_order` VALUES (105, 5, 'OPPO Reno3 Pro 双模5G 视频双防抖', 299900, 1);
INSERT INTO `tb_order` VALUES (106, 6, '美的(Midea) 新能效 冷静星II ', 544900, 1);
INSERT INTO `tb_order` VALUES (107, 2, '西昊/SIHOO 人体工学电脑椅子', 79900, 1);
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

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.z3inc</groupId>
    <artifactId>sentinel-demo</artifactId>
    <packaging>pom</packaging><!--pom代表聚合工程-->
    <version>1.0</version>

    <!-- springboot工程 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.12</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <org.projectlombok.version>1.18.20</org.projectlombok.version>
        <spring-cloud.version>2021.0.3</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.0.4.0</spring-cloud-alibaba.version>
        <mybatis-plus.version>3.4.3</mybatis-plus.version>
        <hutool.version>5.8.11</hutool.version>
        <mysql.version>8.0.23</mysql.version>
    </properties>

    <!-- 对依赖包进行管理 -->
    <dependencyManagement>
        <dependencies>
            <!-- spring cloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- spring cloud alibaba -->
            <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>
            <!-- 数据库驱动 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <!-- mybatis plus -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis-plus.version}</version>
            </dependency>
            <!-- hutool工具类 -->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>${hutool.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${org.projectlombok.version}</version>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

   <build>
    <plugins>
        <!--打包跳过单元测试-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <skipTests>true</skipTests>
            </configuration>
        </plugin>
    </plugins>
</build>
    
</project>

2.2 创建用户微服务

1、创建用户模块

image-20230921013420839

2、引入依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>cn.z3inc</groupId>
        <artifactId>sentinel-demo</artifactId>
        <version>1.0</version>
    </parent>

    <artifactId>user-service</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--nacos注册中心依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <!--springmvc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mp-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--hutool工具类-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>
    </dependencies>

    <!--打包插件-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

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

server:
  port: 9001

spring:
  application:
    name: user-service #服务名称
  cloud:
    nacos:
      # nacos注册中心配置
      discovery:
        server-addr: 127.0.0.1:8848 #nacos服务器地址
  # 数据库配置
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/cloud_demo?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
    username: root
    password: 123456

# mp配置
mybatis-plus:
  mmapper-locations: classpath:mapper/*.xml #mapper配置文件存放路径
  type-aliases-package: cn.z3inc.user.pojo # 类型别名(实体类所在包)
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  #配置标准sql输出
    map-underscore-to-camel-case: true #开启驼峰映射

#日志级别
logging:
  level:
    cn.z3inc: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS # 格式化输出日期


4、编写启动类:

@SpringBootApplication
@MapperScan("cn.z3inc.user.mapper")
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

5、编写业务:

实体类:

package cn.z3inc.user.pojo;

import lombok.Data;

@Data
public class User {
    private Long id;
    private String username;
    private String address;
}

mapper接口:

package cn.z3inc.user.mapper;

import cn.z3inc.user.pojo.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends BaseMapper<User> {
    
}

service接口:

package cn.z3inc.user.service;

import cn.z3inc.user.pojo.User;
import com.baomidou.mybatisplus.extension.service.IService;

public interface UserService extends IService<User> {
}
package cn.z3inc.user.service.impl;

import cn.z3inc.user.mapper.UserMapper;
import cn.z3inc.user.pojo.User;
import cn.z3inc.user.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

controller:

package cn.z3inc.user.controller;

import cn.z3inc.user.pojo.User;
import cn.z3inc.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 根据ID获取用户信息
     *
     * @param id 用户ID
     * @return
     */
    @GetMapping("/{id}")
    public User findById(@PathVariable("id") Long id) {
        return userService.getById(id);
    }

    /**
     * 修改用户信息
     *
     * @param user 用户信息
     */
    @PutMapping("/update")
    public void updateUser(@RequestBody User user) {
        userService.updateById(user);
    }

    /**
     * 根据ID删除用户
     *
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable("id") Long id) {
        userService.removeById(id);
    }

    /**
     *  新增用户
     * @param user
     */
    @PostMapping("/save")
    public void saveUser(@RequestBody User user) {
        userService.save(user);        
    }
}

image-20230921153653979

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

.\startup.cmd -m standalone

image-20230921102040129

image-20230921154742489


2.3 创建订单微服务

1、创建订单模块

image-20230921155433895

2、引入依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.z3inc</groupId>
        <artifactId>sentinel-demo</artifactId>
        <version>1.0</version>
    </parent>

    <artifactId>order-service</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!-- openfeign 微服务远程调用  -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- loadbalancer 实现客户端做负载均衡 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <!--nacos注册中心依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <!--springmvc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mp-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--hutool工具类-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>
    </dependencies>

    <!--打包插件-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

3、编写application.yml配置:

server:
  port: 9001

spring:
  application:
    name: user-service #服务名称
  cloud:
    nacos:
      # nacos注册中心配置
      discovery:
        server-addr: 127.0.0.1:8848 #nacos服务器地址
  # 数据库配置
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/cloud_demo?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
    username: root
    password: 123456

# mp配置
mybatis-plus:
  mmapper-locations: classpath:mapper/*.xml #mapper配置文件存放路径
  type-aliases-package: cn.z3inc.order.pojo # 类型别名(实体类所在包)
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  #配置标准sql输出
    map-underscore-to-camel-case: true #开启驼峰映射
  global-config:
    db-config:
      id-type: auto # 主键策略
      table-prefix: tb_ # 表名前缀配置

#日志级别
logging:
  level:
    cn.z3inc: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS # 格式化输出日期

4、编写启动类:

package cn.z3inc.order;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;


@EnableFeignClients(basePackages = "cn.z3inc.order.feign") //开启feign远程调用
@SpringBootApplication
@MapperScan("cn.z3inc.order.mapper")
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

5、编写业务:

实体类:

//用户实体
@Data
public class User {
    private Long id;
    private String username;
    private String address;
}

// 订单实体
@Data
public class Order {
    private Long id;
    private String name;
    private Long price;
    private Integer num;
    private Long userId;
    @TableField(exist = false) // 排除数据表中不存在的字段
    private User user;
}

mapper接口:

package cn.z3inc.order.mapper;

import cn.z3inc.order.pojo.Order;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface OrderMapper extends BaseMapper<Order> {

}

service接口:

package cn.z3inc.order.service;

import cn.z3inc.order.pojo.Order;
import com.baomidou.mybatisplus.extension.service.IService;

public interface OrderService extends IService<Order> {
    //根据id查订单
    Order findById(Long id);
}

feign接口:

package cn.z3inc.order.feign;

import cn.z3inc.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 *  用户服务Feign接口
 */
@FeignClient("user-service")//指定要调用的服务名称
public interface UserClient {

    /*
        主要是基于SpringMVC的注解来声明远程调用的信息,比如:
            - 服务名称:userservice
            - 请求方式:GET
            - 请求路径:/user/{id}
            - 请求参数:Long id
            - 返回值类型:User
     */

    // 定义远程调用方法
    // 通过id查用户
    @GetMapping("/user/{id}") //调用对应controller的方法路径
    User findById(@PathVariable("id") Long id);// @PathVariable注解一定要指定参数名称,否则会报错
}

service接口实现类:

@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Autowired
    private UserClient userClient;

    @Override
    public Order findById(Long id) {
        Order order = super.getById(id);
        User user = userClient.findById(order.getUserId());//微服务远程调用
        order.setUser(user);
        return order;
    }
}

controller:

package cn.z3inc.order.controller;

import cn.z3inc.order.pojo.Order;
import cn.z3inc.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @GetMapping("/{orderId}")
    public Order findById(@PathVariable("orderId") Long orderId) {
        return orderService.findById(orderId);
    }
}

6、测试:

image-20230921163715671


2.4 搭建网关微服务

1、创建网关模块

image-20230921164143848

2、引入依赖:

<dependencies>
    <!--gateway网关-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!--loadbalancer代替ribbon-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    </dependency>
    <!--nacos注册中心-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>

3、修改application.yml配置:

server:
  port: 10010 # 网关的服务端口
spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos服务地址
    # 网关的配置
    gateway:
      # 跨域配置
      globalcors:
        cors-configurations:
          '[/**]':
            allowed-origin-patterns: "*"
            allowed-headers: "*"
            allow-credentials: true
            allowed-methods:
              - GET
              - POST
              - DELETE
              - PUT
              - OPTION
      # 网关路由配置        
      routes: 
        - id: user-service # 路由id    
          uri: lb://user-service # 路由地址
          predicates: # 路由断言(匹配规则)
            - Path=/user/** 
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/order/**

4、编写启动类:

package cn.z3inc.gateway;

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);
    }
}

image-20230921202520666

5、测试:

image-20230921202050740

image-20230921202210196


3. 整合Sentinel


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

1、引入sentinel依赖:

<!--sentinel-->
<dependency>
    <groupId>com.alibaba.cloud</groupId> 
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

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

spring:
  cloud: 
    sentinel:
      transport:
        dashboard: localhost:8090 #控制台地址
      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功能:

feign:
  sentinel:
    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接口。

package cn.z3inc.order.fallback;

import cn.z3inc.order.feign.UserClient;
import cn.z3inc.order.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;

/**
 * UserClient降级处理类
 *
 */
@Slf4j
public class UserClientFallback implements FallbackFactory<UserClient> {

    // 定义userclient降级逻辑
    @Override
    public UserClient create(Throwable cause) {
        return new UserClient(){
            @Override
            public User findById(Long id) { 
                log.error("远程调用UserClient#findById方法出现异常,参数:{}", id, cause);
                return new User();
            }
        };
    }
}

image-20230923151519698

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

package cn.z3inc.order.config;

import cn.z3inc.order.fallback.UserClientFallback;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;

@Slf4j
public class DefaultFeignConfig {
    
    @Bean
    public UserClientFallback userClientFallback() {
        return new UserClientFallback();
    }
}

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

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

image-20230923152127413

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

image-20230923152307420


2. 服务熔断


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

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

状态机包括三个状态:

  • 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1036088.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机组成原理之初识计算机硬件,帮你拆开电脑看看里面的组成!!!

大家好&#xff0c;欢迎阅读《计算机组成原理》的系列文章&#xff0c;本系列文章主要教内容是从零学习计算机组成原理&#xff0c;内容通俗易懂&#xff0c;大家好好学习吧&#xff01;&#xff01;&#xff01; 更多的优质内容&#xff0c;请点击以下链接查看哦~~ ↓ ↓ ↓ …

Java实验案例(一)

目录 案例一&#xff1a;买飞机票 案例二&#xff1a;开发验证码 案例三&#xff1a;评委打分 案例四&#xff1a;数字加密 案例五&#xff1a;数组拷贝 案例六&#xff1a;抢红包 案例七&#xff1a;找素数的三种方法 案例八&#xff1a;打印乘法口诀表 案例九&#x…

若依微服务如何处理Long类型精度丢失问题?

当字段实体类为Long类型且值超过前端js显示的长度范围时会导致前端回显错误。 目录 1、ruoyi-common-security模块添加JacksonConfig配置全局序列化 2、增加指定配置类信息

20230924清远博物馆和图书馆

为了漂流来清远&#xff0c;但是一个城市&#xff0c;想快速了解她的年龄&#xff0c;不就得去博物馆图书馆吗&#xff0c;云想衣裳花想容&#xff0c;春风拂槛露华浓。若非群玉山头见&#xff0c;会向瑶台月下逢。 学校她也曾因历史而不断迁移。 清远她呀&#xff0c;原来已…

ortools在idea中导入失败解决方案

这里写目录标题 错误描述解决方案 <dependencies><!-- https://mvnrepository.com/artifact/com.google.ortools/ortools-java --><dependency><groupId>com.google.ortools</groupId><artifactId>ortools-java</artifactId><ver…

UWB高精度定位系统 超宽带技术

说到定位我们并不陌生&#xff0c;定位技术一直与我们的生活密不可分&#xff0c;比如最常见的车辆导航。 根据使用场景&#xff0c;定位技术分为室内定位和室外定位。 室外定位主要依靠GPS&#xff0c;北斗&#xff0c;GLONASS&#xff0c;伽利略等全球卫星定位导航系统。室内…

【linux】进程等待,进程替换

进程等待&#xff0c;进程替换 1.进程等待1.1进程等待必要性1.2进程等待的方法1.2.1wait方法1.2.2waitpid方法1.2.3通过宏得到退出码1.2.4 阻塞vs非阻塞 2.进程替换2.1进程替换的目的2.2execl替换函数2.3理解原理2.4其他替换接口2.4.1execl2.4.2execlp2.4.3execv2.4.4execvp2.4…

什么是JavaScript中的IIFE(Immediately Invoked Function Expression)?它的作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ JavaScript中的IIFE⭐ 示例⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们…

C++中实现一些特殊的类|设计模式

1.设计一个类 不能被拷贝 拷贝只会发生在两个场景中&#xff1a;拷贝构造以及赋值运算符重载。想要让一个类禁止拷贝&#xff0c;只需要该类不能调用拷贝构造和赋值运算符重载 c98中 将拷贝构造与赋值运算符重载只声明不定义&#xff0c;不定义是因为该函数根本不会调用&#x…

基于springboot+vue的校园外卖服务系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

静态路由与默认路由配置

实验原理&#xff1a; 路由分类 &#xff08;1&#xff09;根据目的网络的不同&#xff0c;路由可以划分为&#xff1a; 特定网络路由&#xff1a;目的网络为目的主机所在网络的IP地址&#xff0c;其子网掩码表示的前缀长度为32位&#xff08;对于IPv4地址&#xff09;&…

分布式搜索引擎01

1.初识elasticsearch 1.1.了解ES 1.1.1.elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容 例如: 在GitHub搜索代码 在电商网站搜索商品 在百度搜索答案 在打车软件搜索附近的车 1.1.2.ELK…

程序员的快乐如此简单

最近在GitHub上发起了一个关于Beego框架的小插件的开源仓库&#xff0c;这一举动虽然看似微小&#xff0c;但其中的快乐和意义却是无法用言语表达的。 Beego是一个开源的Go语言Web框架&#xff0c;它采用了MVC架构模式&#xff0c;并集成了很多常用的功能和中间件。小插件是指…

Linux chmod命令——修改权限信息

我们可以使用chmod命令&#xff0c;修改文件、文件夹的权限信息。注意&#xff0c;只有文件、文件夹的所属用户或root用户可以修改。 chmod [-R] 权限 文件或文件夹 -R&#xff0c;对文件夹内的全部内容应用同样的操作 例如&#xff1a; chmod urwx,grx,ox hello.txt &…

工业余能资源评价方法 标准学习

声明 本文是学习GB-T 1028-2018 工业余能资源评价方法. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准界定了工业余能相关术语&#xff0c;规定了工业余能的分类和评价方法。 本标准适用于工业余能资源的评价。 2 术语和定义 下列术…

oracle执行计划中,同一条语句块,在不同情况下执行计划不一样问题。子查询,union 导致索引失效。

场景&#xff1a; 需要获取部分数据集(视图)的业务时间最大值&#xff0c;希望只通过一条语句获取多个的最大值。 则使用select (视图1业务时间最大值),(视图2业务时间最大值),(视图3业务时间最大值) from dual 程序执行过程中&#xff0c;发现语句执行较慢&#xff0c;则进行s…

描述符——配置描述符

描述符定义 描述符实现 /*** brief USB configuration descriptor.*/ typedef struct __attribute__ ((packed)) {uint8_t bLength ; /**< Size of this descriptor in bytes. */uint8_t bDescriptorType ; /**< CONFIGURATION Descriptor Type. */ui…

使用ElementUI完成登入注册的跨域请求,结合vue-cli搭建的SPA项目,减少冗余代码提升开发效率

目录 一、跨域的概述 ( 1 ) 讲述 ( 2 ) 特点 如何跨域: 二、ElementUI ( 1 ) 导入 ( 2 ) 搭建 ( 3 ) 页面 三、数据交互 ( 1 ) 安装相关模块 安装模块 引用模块 ( 2 ) axios的get请求 ( 3 ) axios的post请求 四、注册功能 带来的收获 一、跨域的概述 …

安卓实现网格布局的效果

文章目录 页面子项布局 Activity适配器 运行结果其他文章 页面 RecyclerView是Android开发中常用的列表控件之一&#xff0c;可以用于展示大量数据以及实现各种布局效果。本文章使用RecyclerView的GridLayoutManager来实现网格布局&#xff0c;显示指定列数。 首先&#xff0c…

25. 图论 - 路径和算法

文章目录 拓展:顶点和边的互换最短路径问题Dijkstra算法Hi, 你好。我是茶桁。 在充分了解图的概念,构成以及种类之后,我们要开始进入稍微有点难度的部分了。这节课,咱们来了解一下路径和Dijkstra算法。 拓展:顶点和边的互换 在这节课正式开始之前,我们对上一节课稍微扩…