熔断降级

熔断整个服务

配置熔断规则

配置服务熔断规则,针对default命名空间下所有的服务,对于时延大于500毫秒,或者返回码为500的请求,标识为错误请求,一旦一分钟内错误率30%及以上或连续错误数在5个以上,则对服务进行熔断。

使用SDK进行熔断判断

方法说明

北极星Java SDK提供以下熔断相关的方法,所有的方法都在com.tencent.polaris.circuitbreak.api.CircuitBreakAPI接口中提供。

  • check:检查资源是否可被调用,并对资源获取调用申请。对于半开的资源,如果半开的调用配额申请成功,返回true,否则返回false。
  • report:该方法供用户在资源调用完成后,上报调用的结果,包括返回码、时延等信息,供熔断逻辑判断。
  • makeFunctionalDecorator:创建一个函数调用装饰器FunctionalDecorator,装饰器可以对Java的函数接口进行装饰。装饰后的逻辑,会在函数逻辑调用前,先通过check方法检查资源是否可被调用,如果不能被调用,会抛出资源熔断异常(CallAbortedException)。调用完成后,会通过report接口上报本次调用结果。FunctionalDecorator包含以下方法:
    • decorateSupplier:对函数接口Supplier进行封装。
    • decorateConsumer:对函数接口Consumer进行封装。
    • decorateFunction:对函数Function进行封装。
    • decoratePredicate:对函数接口Predicate进行封装。

使用示例

// 创建CircuitBreakAPI实例
CircuitBreakAPI circuitBreakAPI = CircuitBreakAPIFactory.createCircuitBreakAPI();

// 通过传入服务名(testService1)和命名空间(default),创建FunctionalDecorator
FunctionalDecoratorRequest makeDecoratorRequest = new FunctionalDecoratorRequest();
        makeDecoratorRequest.setService(new ServiceKey("default", "testService1"));
FunctionalDecorator decorator = circuitBreakAPI.makeFunctionalDecorator(makeDecoratorRequest);

// 封装函数接口
Consumer<Integer> integerConsumer = decorator.decorateConsumer(new Consumer<Integer>() {
    @Override
    public void accept(Integer object) {
      // 执行服务调用...
    }
});

// 通过执行函数接口,进行服务调用
// 在调用过程中,如果出现熔断,会抛出CallAbortedException异常
for (int i = 0; i < 500; i++) {
    try {
       integerConsumer.accept(i);
    } catch(CallAbortedException e) {
       e.printStackTrace();
    }
}

样例地址

Github地址

熔断单个接口

配置熔断规则

配置接口熔断规则,针对default命名空间所有服务的foo接口,对于时延大于500毫秒,或者返回码为500的请求,标识为错误请求,一旦一分钟内错误率30%及以上或连续错误数在5个以上,则对接口进行熔断。

使用SDK进行熔断判断

熔断所使用的SDK接口及方法与服务级熔断相同,这里不再重复介绍。

使用示例

// 创建CircuitBreakAPI实例
CircuitBreakAPI circuitBreakAPI = CircuitBreakAPIFactory.createCircuitBreakAPI();

// 通过传入服务名(testService1)、命名空间(default)和方法名(foo),创建FunctionalDecorator
FunctionalDecoratorRequest makeDecoratorRequest = new FunctionalDecoratorRequest();
makeDecoratorRequest.setService(new ServiceKey("default", "testService1"));
makeDecoratorRequest.setMethod("foo");
FunctionalDecorator decorator = circuitBreakAPI.makeFunctionalDecorator(makeDecoratorRequest);

// 封装函数接口
Consumer<Integer> integerConsumer = decorator.decorateConsumer(new Consumer<Integer>() {
    @Override
    public void accept(Integer object) {
      // 执行服务接口调用...
    }
});

// 通过执行函数接口,进行服务调用
// 在调用过程中,如果出现熔断,会抛出CallAbortedException异常
for (int i = 0; i < 500; i++) {
    try {
       integerConsumer.accept(i);
    } catch(CallAbortedException e) {
       e.printStackTrace();
    }
}

样例地址

Github地址

熔断单个实例

配置熔断规则

配置实例熔断规则,针对default命名空间下所有的服务实例,对于时延大于500毫秒,或者返回码为500的请求,标识为错误请求,每个实例的错误率是单独统计的,一旦一分钟内错误率30%及以上或连续错误数在5个以上,则对被调实例(IP:PORT)进行熔断。

使用SDK进行熔断判断

当实例被熔断时,该实例会暂时不接收请求,原本路由到该实例的请求会路由到其他实例。这个过程在服务路由过程中自动完成,用户无需进行额外的熔断状态判断等操作。

引入依赖

修改应用根目录下的pom.xml,为 polaris-java 添加 dependencyManagement:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.tencent.polaris</groupId>
            <artifactId>polaris-dependencies</artifactId>
            <version>${version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

然后只需要在 标签中在添加 polaris-all 即可

<dependencies>
    <dependency>
        <groupId>com.tencent.polaris</groupId>
        <artifactId>polaris-all</artifactId>
    </dependency>
</dependencies>

配置北极星服务端地址

用户需要在项目的 main/resources 下创建一个 polaris.yml 文件用于初始化 polaris-java SDK。

global:
  serverConnector:
    # 北极星服务端地址,端口为8091
    addresses:
      - 127.0.0.1:8091

执行服务路由

import com.tencent.polaris.factory.api.DiscoveryAPIFactory;


public static void main(String[] args) throws Exception {
    CircuitBreakAPI circuitBreakAPI = CircuitBreakAPIFactory.createCircuitBreakAPI();
    ConsumerAPI consumerAPI = DiscoveryAPIFactory.createConsumerAPI();
    // 执行服务路由,筛选出单个实例,在这个过程中,会自动剔除熔断的实例
    GetOneInstanceRequest getOneInstanceRequest = new GetOneInstanceRequest();
    getOneInstanceRequest.setNamespace("default");
    getOneInstanceRequest.setService("testService1");
    InstancesResponse oneInstance = consumerAPI.getOneInstance(getOneInstanceRequest);
    Instance targetInstance = oneInstance.getInstances()[0];
    // 执行服务调用 --- 伪代码
    httpResult, delay = rpc(targetInstance.host, targetInstance.port, body);

    // invoke rpc call with targetInstance
    InstanceResource instanceResource = new InstanceResource(new ServiceKey(namespace, service),
            targetInstance.getHost(), targetInstance.getPort(), sourceService.getServiceKey());
    circuitBreakAPI.report(new ResourceStat(instanceResource, httpResult.code, delay));
}

样例地址

Github地址

启用主动探测

业务往往会存在高峰期和低峰期,低峰期流量比较少,不足以触发熔断,会出现当部分实例出现数据不可达的问题时,没法及时发现,导致高峰期到来时出现故障。

主动探测可以解决这个问题,启用主动探测后,主调方会定时根据探测规则,对被调实例进行探测,探测结果可作为熔断的判断依据,可实现对故障资源的快速熔断。

配置主动探测规则

配置一个主动探测规则,对服务(名为testService1,命名空间为default)进行探测。探测使用的协议是HTTP协议,由于服务开启了鉴权,因此探测时需要传入鉴权头。

注意:主动探测的规则,服务名可以选择全部服务,则规则针对全部服务生效。如果需要针对只接口进行探测,则可以在接口字段中填入对应的接口名。

在熔断规则中开启主动探测

需要在熔断规则中开启探测,这样才可以把探测结果用于熔断。