🥝FANMR.CN热爱,追求
Sentinel

Sentinel是阿里开源的项目,提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性

服务雪崩

在微服务项目中,服务与服务之间的调用错综复杂,如果一个服务出现问题,就会引起整个链路的错误,导致服务雪崩

服务雪崩效应:因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程

容错机制

  • 超时机制:对服务的调用设置超时时间,超时后做其他处理
  • 限流机制:提前对服务做压测,设置服务能承受的流量值
  • 隔离:与限流类似,不过是根据线程或者信号量
  • 服务熔断:当服务不可用后,调用者直接进行熔断
  • 服务降级:当熔断后就需要执行其他逻辑,,即降级

控制台部署

Sentinel官方文档

nohup java -Dserver.port=8856 -jar sentinel-dashboard-1.8.0.jar &

客户端整合

依赖

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

配置

# sentinel控制台地址
spring.cloud.sentinel.transport.dashboard=127.0.0.1:8849

启动后访问服务任意接口后再控制台就有了对服务的信息

流量控制(QPS)

单独处理(推荐)

@RequestMapping("/test")
// 使用该注解对该接口的流控异常做处理
@SentinelResource(value = "test", blockHandler = "testBlockHandler")
public String test() {
    System.out.println("订单");
    return "order";
}

// 自定义流控处理,对应到blockHandler
public String testBlockHandler(BlockException e) {
    return "服务繁忙,稍后再试";
}

接口代码处理完成后在控制台进行QPS设置,注意是注解上value的值

当QPS达到阈值就会返回定义的内容

注意:Sentinel没有做持久化,服务重启后配置的流控将失效

全局处理

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
    Logger logger = LoggerFactory.getLogger(MyBlockExceptionHandler.class);
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
        // getRule()记录了哪个资源及其规则等详细信息,记录为日志
        logger.info("MyBlockExceptionHandler:{}", e.getRule());
        String msg;
        if (e instanceof FlowException) {
            msg = "接口限流了";
        } else if (e instanceof DegradeException) {
            msg = "服务降级了";
        } else if (e instanceof ParamFlowException) {
            msg = "热点参数限流了";
        } else if (e instanceof SystemBlockException) {
            msg = "触发系统保护规则了";
        } else if (e instanceof AuthorityException) {
            msg = "授权规则不通过";
        } else {
            msg = "系统繁忙,稍后再试";
        }
        httpServletResponse.setStatus(500);
        httpServletResponse.setCharacterEncoding("utf-8");
        httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
        new ObjectMapper().writeValue(httpServletResponse.getWriter(), msg);
    }
}

全局配置后控制台只需要针对接口进行配置流控即可

持久化

依赖

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

然后需要在Nacos中添加配置管理,配置的是JSON,详情看文档的流量控制

然后配置

# sentinel持久化配置
spring.cloud.sentinel.datasource.flow-rule.nacos.server-addr=127.0.0.1:8848
# Nacos中配置的名字
spring.cloud.sentinel.datasource.flow-rule.nacos.data-id=order-service-test