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
-
方案
-
为调用方熔添加断保护
-
调用方手动指定远程服务降级策略,
-
- 远程服务会被降级处理,触发熔断回调方法
- 超大流量的时候,必须牺牲一些远程服务,在服务的提供方(远程服务)指定降级策略,这样做的好处就是,提供方在这期间是运行中的,但是不会运行自己的业务逻辑,只会返回默认的降级数据。
-
-
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 -谷粒商城的主要内容,如果未能解决你的问题,请参考以下文章