Day440.Sentinel -谷粒商城

Posted 阿昌喜欢吃黄桃

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day440.Sentinel -谷粒商城相关的知识,希望对你有一定的参考价值。

Sentinel

一、Hystrix 与 Sentinel 的区别

1、隔离策略

  • Hystrix 使用线程池隔离,假设现在有 100 个人要访问 hello 请求,Hystrix 默认会为 hello 请求做一个线程池,假设这个线程池只有 50 的容量,那每有 1 个请求进来,线程池都会为其分配一个线程,这样整个线程池的最大容量就是 50 个请求,如果再有多的请求,Hystrix 就会直接退回

    这样做的缺点就是,如果再有一个 haha 请求,再有一个 enen 请求,这 3 请求,我们都想保护,这样 Hystrix 就会创建 3 个线程池,这样整个系统的线程池就会很多,线程池多了之后,线程之间的切换就会很浪费时间,所以这是对性能的极大影响,线程池可能用着用着就不够了,导致服务宕机

  • Sentinel则使用信号量隔离,它会为 hello、haha、enen 请求都设置一个信号量,假设都是50,请求一进来之后,访问的 hello 请求,如果 hello 的信号量为 0 了,那就直接退回这个请求,而 hello 里面的请求则是每有 1 个执行完了,就会让信号量 + 1,这样新的请求又能进来了

    当然线程池隔离也有一个很大的优点,就是隔离的非常彻底,每一个请求都有自己的线程池,就算是自己的线程池出问题,也不会影响其他请求,而信号量隔离,一旦有一个请求的信号量出问题了,那肯定会影响其他请求。


2、熔断降级策略

  • 基于响应时间:假设每个请求的访问频率超过1秒,就可以熔断

  • 基于异常比率:假设100次请求,有90次以上都出异常,异常比率超过90%,也可以熔断

  • 基于异常数:假设100次请求,有5个出现异常,也可以熔断


3、系统自适应保护

  • Sentinel在得知系统性能之后,可以在低峰期将流量都放进来,高峰期对流量进行限制

二、Docker 安装使用 Sentinel

# 下载
docker pull bladex/sentinel-dashboard:1.6.3

# 运行
docker run --name sentinel  -d -p 8858:8858 -d  bladex/sentinel-dashboard:1.6.3

# 开机自启
docker update sentinel --restart=always

三、SpringBoot 整合 Sentinel

  • achangmall-common/pom.xml
<!--sentinel-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--健康监控-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  • achangmall-seckill/src/main/resources/application.properties
# 控制台的安装位置
spring.cloud.sentinel.transport.dashboard=localhost:8333
# 与sentinel单独连接的端口
spring.cloud.sentinel.transport.port=8719
# 本机的ip,如果sentinel装在虚拟机,必须配这个
spring.cloud.sentinel.transport.clientIp=192.168.109.101

# 暴露应用信息
management.endpoints.web.exposure.include='*'
  • 小问题

启动项目后访问接口,发现 sentinel 实时监控中一直显示为空白状态,一般是 sentinel 服务器和项目服务器时间不一致造成的,此时就需要同步虚拟机与项目服务器的时间,重启服务器、项目服务器,测试即可。(采用懒加载

  • 自动同步时间
# 安装时间同步插件
yum install chrony -y

# 启动时间同步
systemctl start chronyd

# 开机自启
systemctl enable chronyd
  • 自定义限流后返回的内容

com.achang.achangmall.seckill.config.AchangmallSentinelConfig

给每一个服务都加上

/**
 * @Description: 自定义阻塞返回方法
 **/

@Configuration
public class AchangmallSentinelConfig implements BlockExceptionHandler 
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception 
        R error = R.error(BizCodeEnum.TO_MANY_REQUEST.getCode(), BizCodeEnum.TO_MANY_REQUEST.getMessage());
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setContentType("application/json");
        httpServletResponse.getWriter().write(JSON.toJSONString(error));
    

  • 给所有的服务都加入sentinel配置
# 控制台的安装位置
spring.cloud.sentinel.transport.dashboard=localhost:8333
# 与sentinel单独连接的端口
spring.cloud.sentinel.transport.port=8719
# 本机的ip,如果sentinel装在虚拟机,必须配这个
spring.cloud.sentinel.transport.clientIp=192.168.109.101

# 暴露应用信息
management.endpoints.web.exposure.include='*'

四、使用 Sentinel 保护 远程调用

A调用B,B因为未知原因调用失败

这样子我们可以给A配置如下启动

  • achangmall-product/src/main/resources/bootstrap.properties

给每一个服务都加上

# 保护远程调用
feign.sentinel.enabled=true
  • 方案

    1. 为调用方熔添加断保护

    2. 调用方手动指定远程服务降级策略,

      1. 远程服务会被降级处理,触发熔断回调方法
      2. 超大流量的时候,必须牺牲一些远程服务,在服务的提供方(远程服务)指定降级策略,这样做的好处就是,提供方在这期间是运行中的,但是不会运行自己的业务逻辑,只会返回默认的降级数据
  • com.achang.achangmall.product.fallback.SeckillFeignServiceFallBack

feign远程调用失败,指定调用的回调的方法implements SeckillFeignService

@Component
public class SeckillFeignServiceFallBack implements SeckillFeignService 
    @Override
    public R getSkuSeckilInfo(Long skuId) 
        return R.error(BizCodeEnum.TO_MANY_REQUEST.getCode(),BizCodeEnum.TO_MANY_REQUEST.getMessage());
    

  • com.achang.achangmall.product.feign.SeckillFeignService

在feign远程调用指定的接口中fallback指定哪个是触发后回调的方法

@FeignClient(value = "achangmall-seckill",fallback = SeckillFeignServiceFallBack.class)
public interface SeckillFeignService 

    /**
     * 根据skuId查询商品是否参加秒杀活动
     */
    @GetMapping(value = "/sku/seckill/skuId")
    R getSkuSeckilInfo(@PathVariable("skuId") Long skuId);


  • 自定义手动降级

推荐给调用方设置,不建议给提供方手动降级


五、自定义收保护资源

1、抛出异常的方式定义资源

// 1.5.0 版本开始可以利用 try-with-resources 特性(使用有限制)
// 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。

try (Entry entry = SphU.entry("resourceName")) 
    // 被保护的业务逻辑
    // do something here...
 catch (BlockException ex) 
    // 资源访问阻止,被限流或被降级
    // 在此处进行相应的处理操作


2、注解方式定义资源

在需要受保护的方法上面加上@SentinelResource注解并通过blockHandler来指定出现降级之后指定的方法名,一般是写同类中,这个方法会拿到原本执行方法的参数发生降级的原因BlockException e

// 原本的业务方法.
@SentinelResource(blockHandler = "blockHandlerForGetUser")
public User getUserById(String id) 
    throw new RuntimeException("getUserById command failed");


// blockHandler 函数,原方法调用被限流/降级/系统保护的时候调用
public User blockHandlerForGetUser(String id, BlockException ex) 
    return new User("admin");


3、结论

使用抛出异常的这种方式,也可以在方法外加上@SentinelResource注解,只要使用@SentinelResource注解就必须设置blockHandler属性来指定处理这次降级的方法内容

以上是关于Day440.Sentinel -谷粒商城的主要内容,如果未能解决你的问题,请参考以下文章

伸手党福利文,Python入门大全

目录大纲

自学it18大数据笔记-第一阶段Java-day05-day06-day07-day08

day56(2023.4.25)

Alpha阶段 - 博客链接合集

python-第一块,笔记整理和学习内容复习(day1 - day2 - day3)