出自图灵学院

代码地址

https://gitee.com/zjj19941/ZJJ_Neaten5.10/tree/master/ZJJ_Sentinel/spring-cloud-alibaba-dubbo-sentinel

详细步骤

Sentinel 提供 Dubbo 的相关适配 Sentinel Dubbo Adapter,主要包括针对 Service Provider 和 Service Consumer 实现的 Filter。相关模块:

  • sentinel-apache-dubbo-adapter(兼容 Apache Dubbo 2.7.x 及以上版本,自 Sentinel 1.5.1 开始支持)
  • sentinel-dubbo-adapter(兼容 Dubbo 2.6.x 版本)

引入此依赖后,Dubbo 的服务接口和方法(包括调用端和服务端)就会成为 Sentinel 中的资源,在配置了规则后就可以自动享受到Sentinel 的防护能力。
Sentinel Dubbo Adapter 还支持配置全局的 fallback 函数,可以在 Dubbo 服务被限流/降级/负载保护的时候进行相应的 fallback 处理。用户只需要实现自定义的 DubboFallback 接口,并通过 DubboAdapterGlobalConfig注册即可。默认情况会直接将 BlockException 包装后抛出。同时,我们还可以配合 Dubbo 的 fallback 机制 来为降级的服务提供替代的实现。

Provider端
对服务提供方的流量控制可分为服务提供方的自我保护能力服务提供方对服务消费方的请求分配能力两个维度。
Provider 用于向外界提供服务,处理各个消费者的调用请求。为了保护 Provider 不被激增的流量拖垮影响稳定性,可以给 Provider 配置 QPS 模式的限流,这样当每秒的请求量超过设定的阈值时会自动拒绝多的请求。限流粒度可以是 服务接口服务方法 两种粒度。若希望整个服务接口的 QPS 不超过一定数值,则可以为对应服务接口资源(resourceName 为接口全限定名)配置 QPS 阈值;若希望服务的某个方法的 QPS 不超过一定数值,则可以为对应服务方法资源(resourceName 为接口全限定名:方法签名)配置 QPS 阈值。
限流粒度可以是服务接口和服务方法两种粒度:

  • 服务接口:resourceName 为 接口全限定名,如 com.tuling.mall.service.UserService
  • 服务方法:resourceName 为 接口全限定名:方法签名,如 com.tuling.mall.service.UserService:getById(java.lang.Integer)


    Consumer端
    对服务提供方的流量控制可分为控制并发线程数服务降级两个维度。

    控制并发线程数
    Service Consumer 作为客户端去调用远程服务。每一个服务都可能会依赖几个下游服务,若某个服务 A 依赖的下游服务 B 出现了不稳定的情况,服务 A 请求 服务 B 的响应时间变长,从而服务 A 调用服务 B 的线程就会产生堆积,最终可能耗尽服务 A 的线程数。我们通过用并发线程数来控制对下游服务 B 的访问,来保证下游服务不可靠的时候,不会拖垮服务自身。基于这种场景,推荐给 Consumer 配置线程数模式的限流,来保证自身不被不稳定服务所影响。采用基于线程数的限流模式后,我们不需要再显式地去进行线程池隔离,Sentinel 会控制资源的线程数,超出的请求直接拒绝,直到堆积的线程处理完成,可以达到信号量隔离的效果。

    服务降级
    当服务依赖于多个下游服务,而某个下游服务调用非常慢时,会严重影响当前服务的调用。这里我们可以利用 Sentinel 熔断降级的功能,为调用端配置基于平均 RT 的降级规则。这样当调用链路中某个服务调用的平均 RT 升高,在一定的次数内超过配置的 RT 阈值,Sentinel 就会对此调用资源进行降级操作,接下来的调用都会立刻拒绝,直到过了一段设定的时间后才恢复,从而保护服务不被调用端短板所影响。同时可以配合 fallback 功能使用,在被降级的时候提供相应的处理逻辑。

    1.引入依赖

  1. <dependency>
  2. <groupId>com.alibaba.cloud</groupId>
  3. <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
  4. </dependency>
  5. <!--Sentinel 对 Dubbo的适配 Apache Dubbo 2.7.x 及以上版本-->
  6. <dependency>
  7. <groupId>com.alibaba.csp</groupId>
  8. <artifactId>sentinel-apache-dubbo-adapter</artifactId>
  9. </dependency>

2.接入sentinel dashboard,yml中增加配置

spring:
  cloud:
    sentinel:
      transport:
        # 添加sentinel的控制台地址
        dashboard: 127.0.0.1:8080

#暴露actuator端点   
management:
  endpoints:
    web:
      exposure:
        include: '*'

3.consumer端配置流控规则测试

@RequestMapping("/info/{id}")
    public User info(@PathVariable("id") Integer id) {
        User user = null;
        try {
            user = userService.getById(id);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return user;
    }

    @PostConstruct
    public void init() {
        DubboAdapterGlobalConfig.setConsumerFallback(
                (invoker, invocation, ex) -> AsyncRpcResult.newDefaultAsyncResult(
                        new User(0,"===fallback=="), invocation));
    }

image.png
测试: http://localhost:8082/user/info/1
image.png

4.provider端配置流控规则测试
image.png

@RequestMapping("/getById/{id}")
@SentinelResource("getById")
public User getById(@PathVariable("id") Integer id) {
    User user = null;
    try {
        user = userMapper.getById(id);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return user;
}

@PostConstruct
public void init() {
    DubboAdapterGlobalConfig.setProviderFallback(
        (invoker, invocation, ex) -> AsyncRpcResult.newDefaultAsyncResult(new User(0,"===provider fallback=="), invocation));
}

image.png
5. consumer中配置mock实现,关闭provider服务,测试mock降级

@DubboReference(mock = "com.tuling.mall.user.mock.UserServiceDubboMock")
private UserService userService;

public class UserServiceDubboMock implements UserService {
    @Override
    public List<User> list() {
        return null;
    }

    @Override
    public User getById(Integer id) {
        return new User(0,"====mock===");
    }
}

image.png