操作场景
本文介绍在本地开发 Java 应用,通过 polaris-sdk 的方式接入 TSE 治理中心(北极星网格),并实现熔断降级功能。
前提条件
在开发前,请确保您已经下载并安装了 Java 和 Maven。
操作步骤
步骤1:引入北极星依赖
1. 引入 polaris 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>
说明:
2. 引入 polaris starter
<dependencies><dependency><groupId>com.tencent.polaris</groupId><artifactId>polaris-all</artifactId></dependency></dependencies>:
步骤2:添加北极星配置文件 polaris.yaml
1. 在项目的 main/resources 目录下创建 polaris.yml 文件用于初始化 polaris-java SDK。
2. 在 polaris.yml 文件中配置应用名、polaris(北极星)服务端地址等信息。服务端地址查看详细参见:引擎管理 > 客户端访问地址。
global:serverConnectors:- id: polarisprotocol: grpcaddresses:# 地址需要替换成您创建的北极星引擎的客户端访问地址。- 127.0.0.1:8091#描述: 监控及日志数据上报相关配置statReporter:#描述: 是否启用上报enable: trueplugin:prometheus:type: push# 描述: 设置 pushgateway 的地址, 仅 type == push 时生效# 地址需要替换成您创建的北极星引擎的客户端访问地址。address: 127.0.0.1:9091#描述:设置metric数据推送到pushgateway的执行周期#范围:[1s:...],默认值:10spushInterval: 10s
步骤3:使用说明
北极星支持三种维度的熔断降级:服务级、接口级、实例级。
1. 控制台配置熔断规则
熔断规则配置示例:针对 default 命名空间下所有的服务,对于时延大于500毫秒,或者返回码为500的请求,标识为错误请求,一旦一分钟内错误率30%及以上或连续错误数在5个以上,则对服务进行熔断。
2. 客户端使用 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 进行封装。
2.2 服务级熔断
// 创建CircuitBreakAPI实例CircuitBreakAPI circuitBreakAPI = CircuitBreakAPIFactory.createCircuitBreakAPI();// 通过传入服务名(testService1)和命名空间(default),创建FunctionalDecoratorFunctionalDecoratorRequest makeDecoratorRequest = new FunctionalDecoratorRequest();makeDecoratorRequest.setService(new ServiceKey("default", "testService1"));FunctionalDecorator decorator = circuitBreakAPI.makeFunctionalDecorator(makeDecoratorRequest);// 封装函数接口Consumer<Integer> integerConsumer = decorator.decorateConsumer(new Consumer<Integer>() {@Overridepublic void accept(Integer object) {// 执行服务调用...}});// 通过执行函数接口,进行服务调用// 在调用过程中,如果出现熔断,会抛出CallAbortedException异常for (int i = 0; i < 500; i++) {try {integerConsumer.accept(i);} catch(CallAbortedException e) {e.printStackTrace();}}
2.3 接口级熔断
// 创建CircuitBreakAPI实例CircuitBreakAPI circuitBreakAPI = CircuitBreakAPIFactory.createCircuitBreakAPI();// 通过传入服务名(testService1)、命名空间(default)和方法名(foo),创建FunctionalDecoratorFunctionalDecoratorRequest 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>() {@Overridepublic void accept(Integer object) {// 执行服务接口调用...}});// 通过执行函数接口,进行服务调用// 在调用过程中,如果出现熔断,会抛出CallAbortedException异常for (int i = 0; i < 500; i++) {try {integerConsumer.accept(i);} catch(CallAbortedException e) {e.printStackTrace();}}
2.4 实例级熔断
当实例被熔断时,该实例会暂时不接收请求,原本路由到该实例的请求会路由到其他实例。这个过程在服务路由过程中自动完成,用户无需进行额外的熔断状态判断等操作。
执行服务路由:
import com.tencent.polaris.factory.api.DiscoveryAPIFactory;public static void main(String[] args) throws Exception {ConsumerAPI consumerAPI = DiscoveryAPIFactory.createConsumerAPI();// 执行服务路由,筛选出单个实例,在这个过程中,会自动剔除熔断的实例GetOneInstanceRequest getOneInstanceRequest = new GetOneInstanceRequest();getOneInstanceRequest.setNamespace("default");getOneInstanceRequest.setService("testService1");InstancesResponse oneInstance = consumerAPI.getOneInstance(getOneInstanceRequest);Instance targetInstance = oneInstance.getInstances()[0];// 执行服务调用// invoke rpc call with targetInstance// 上报调用结果,调用结果用于进行熔断判断ServiceCallResult result = new ServiceCallResult();result.setNamespace(namespace);result.setService(service);result.setHost(targetInstance.getHost());result.setPort(targetInstance.getPort());// 设置返回码result.setRetCode(code);// 设置调用时延result.setDelay(delay);// 使用updateServiceCallResult上报调用结果consumerAPI.updateServiceCallResult(result);}