使用polaris-java

环境准备

准备polaris后台环境

您需要先下载 Polaris并启动,详细可参考服务端安装指南

准备编译/运行环境

Polaris-JAVA的集成依赖maven环境,需要预先配置maven,并且需要确保是在以下版本环境中进行编译使用:

  1. 64 bit操作系统,支持Linux/Unix/Windows,推荐选用 Linux/Unix
  2. JDK 64bit 1.8.0+,下载地址:https://openjdk.java.net/install/

快速接入

包依赖

可以在polaris-java的release note上获取到Polaris的所有版本以及相关介绍。推荐使用最新的稳定版本。

在工程根目录的pom中的<dependencyManagement>添加如下配置,即可在项目中引用需要的polaris-java子模块依赖。

依赖管理

  1. <dependencyManagement>
  2. <dependencies>
  3. <dependency>
  4. <groupId>com.tencent.polaris</groupId>
  5. <artifactId>polaris-dependencies</artifactId>
  6. <version>${version}</version>
  7. <type>pom</type>
  8. <scope>import</scope>
  9. </dependency>
  10. </dependencies>
  11. </dependencyManagement>

使用全量功能

  1. <dependency>
  2. <groupId>com.tencent.polaris</groupId>
  3. <artifactId>polaris-factory</artifactId>
  4. </dependency>

仅服务注册服务发现

  1. <dependency>
  2. <groupId>com.tencent.polaris</groupId>
  3. <artifactId>polaris-discovery-factory</artifactId>
  4. </dependency>

仅使用服务熔断

  1. <dependency>
  2. <groupId>com.tencent.polaris</groupId>
  3. <artifactId>polaris-circuitbreaker-factory</artifactId>
  4. </dependency>

仅使用服务限流

  1. <dependency>
  2. <groupId>com.tencent.polaris</groupId>
  3. <artifactId>polaris-ratelimit-factory</artifactId>
  4. </dependency>

配置服务端地址

在应用的classpath当前目录下,添加polaris.yml文件,配置服务端地址信息

  1. global:
  2. serverConnector:
  3. addresses:
  4. - 127.0.0.1:8091

开启监控上报

polaris-java支持上报监控数据到prometheus,如需开启,需要执行以下2步

  1. 添加监控数据采集服务实例

    打开polaris控制台,点击“服务列表->新建”,选择命名空间为“Polaris”,服务名为polaris.monitor,并确认后新建服务。

    image

    回到服务列表,点击polaris.monitor服务进入实例列表,点击“新建”后,填入push-gateway的实例IP(实例IP需要确保SDK所在机器可达)以及端口(默认9091),权重选择100,并确认后新建实例 image

  2. 开启监控上报配置

    修改polaris.yml文件,开启statReporter功能

    1. global:
    2. #描述: 监控及日志数据上报相关配置
    3. statReporter:
    4. #描述: 是否启用上报
    5. enable: true

服务注册与心跳上报

  1. 添加依赖

    在项目中加入polaris-discovery-factory依赖即可使用Polaris的服务注册与发现功能。如Maven项目中,在pom中添加如下配置:

    1. <dependency>
    2. <groupId>com.tencent.polaris</groupId>
    3. <artifactId>polaris-discovery-factory</artifactId>
    4. </dependency>
  2. 创建ProviderAPI

    ProviderAPI的所有方法都是线程安全的,所以一个进程创建一个ProviderAPI来使用就足够了,最后进程退出前要调用一下destroy()方法

    1. ProviderAPI providerAPI = DiscoveryAPIFactory.createProviderAPI()
    2. //before process exits
    3. providerAPI.destroy()
  3. 执行服务注册

    1. InstanceRegisterRequest request = new InstanceRegisterRequest();
    2. request.setNamespace("Test");
    3. request.setService("dummy");
    4. request.setHost("127.0.0.1");
    5. request.setPort(12380);
    6. request.setTtl(2);
    7. InstanceRegisterResponse instanceRegisterResponse = providerAPI.register(request);
  4. 执行心跳上报

    1. InstanceHeartbeatRequest request = new InstanceHeartbeatRequest();
    2. request.setNamespace("Test");
    3. request.setService("dummy");
    4. request.setHost("127.0.0.1");
    5. request.setPort(12380);
    6. providerAPI.heartbeat(request);
  5. 执行服务反注册

    1. InstanceDeregisterRequest request = new InstanceDeregisterRequest();
    2. request.setNamespace("Test");
    3. request.setService("dummy");
    4. request.setHost("127.0.0.1");
    5. request.setPort(12380);
    6. providerAPI.deRegister(request);

服务发现

  1. 创建ConsumerAPI

    ConsumerAPI的所有方法都是线程安全的,所以一个进程创建一个ConsumerAPI来使用就足够了,最后进程退出前要调用一下destroy()方法

    1. ConsumerAPI consumerAPI = DiscoveryAPIFactory.createConsumerAPI()
    2. //before process exits
    3. consumerAPI.destroy()
  2. 拉取所有的服务实例

    1. GetAllInstancesRequest request = new GetAllInstancesRequest();
    2. request.setNamespace(namespace);
    3. request.setService(service);
    4. InstancesResponse instancesResponse = consumerAPI.getAllInstance(request);
    5. for (Instance instance : instancesResponse.getInstances()) {
    6. System.out.printf("instance is %s:%d%n", instance.getHost(), instance.getPort());
    7. }

服务路由与负载均衡

  1. 使用场景

    dummyGrey服务下,有5个实例,3个实例部署了version 1.0的应用,2个实例部署了version 2.0的应用,需要保证只有灰度用户才能请求到version 2.0的应用。

  2. 添加不同分组的多个实例

    注册version 1.0的服务实例

    1. for (int i = 0; i < 3; i++) {
    2. InstanceRegisterRequest request = new InstanceRegisterRequest();
    3. request.setNamespace("Test");
    4. request.setService("dummyGrey");
    5. request.setHost("127.0.0.1");
    6. request.setPort(12390 + i);
    7. request.setVersion("1.0")
    8. InstanceRegisterResponse instanceRegisterResponse = providerAPI.register(request);
    9. }

    注册version 2.0的服务实例

    1. for (int i = 0; i < 2; i++) {
    2. InstanceRegisterRequest request = new InstanceRegisterRequest();
    3. request.setNamespace("Test");
    4. request.setService("dummyGrey");
    5. request.setHost("127.0.0.1");
    6. request.setPort(12370 + i);
    7. request.setVersion("2.0")
    8. InstanceRegisterResponse instanceRegisterResponse = providerAPI.register(request);
    9. }
  3. 添加路由规则

    路由规则中声明,带有灰度标签(grey=true)的请求,路由到version 2.0的实例分组,否则路由到version 1.0的实例分组,规则文本如下:

    1. [
    2. {
    3. "service":"dummyGrey",
    4. "namespace":"Test",
    5. "inbounds":[
    6. {
    7. "sources": [
    8. {
    9. "service": "*",
    10. "namespace": "*",
    11. "metadata": {
    12. "grey": {
    13. "value": "true"
    14. }
    15. }
    16. }
    17. ],
    18. "destinations": [
    19. {
    20. "service": "dummyGrey",
    21. "namespace": "Test",
    22. "metadata": {
    23. "version": {
    24. "value": "2.0"
    25. }
    26. },
    27. "priority": 0,
    28. "weight": 100,
    29. "isolate": false
    30. }
    31. ]
    32. },
    33. {
    34. "sources": [
    35. {
    36. "service": "*",
    37. "namespace": "*"
    38. }
    39. ],
    40. "destinations": [
    41. {
    42. "service": "dummyGrey",
    43. "namespace": "Test",
    44. "metadata": {
    45. "version": {
    46. "value": "1.0"
    47. }
    48. },
    49. "priority": 0,
    50. "weight": 100,
    51. "isolate": false
    52. }
    53. ]
    54. }
    55. ],
    56. "outbounds":[]
    57. }
    58. ]

    将规则文本保存为data.json文件,通过接口写入到Polaris服务端

    1. curl -XPOST -H'Content-Type:application/json' -d @data.json 'http://127.0.0.1:8090/naming/v1/routings'
  4. 拉取经过路由及负载均衡后的单个实例

    1. GetOneInstanceRequest request = new GetOneInstanceRequest();
    2. ServiceInfo serviceInfo = new ServiceInfo();
    3. Map<String, String> metadata = new HashMap<>();
    4. metadata.put("grey", "true");
    5. serviceInfo.setMetadata(metadata);
    6. request.setServiceInfo(serviceInfo);
    7. request.setNamespace(namespace);
    8. request.setService(service);
    9. InstancesResponse oneInstance = consumerAPI.getOneInstance(request);
    10. Instance instance = oneInstance.getInstance();
    11. System.out.printf("selected instance is %s:%d%n", instance.getHost(), instance.getPort());

故障节点熔断

Polaris支持在主调方侧感知到被调实例出现异常,并且及时将其熔断剔除的能力,以及当实例异常解除后,通过主动探测或者超时放量等机制将其及时恢复。

  1. 添加2个服务实例

    1. //add 2 instances, one is 127.0.0.1:10010, second is 127.0.0.1:10011
    2. for (int i = 0; i < 2; i++) {
    3. InstanceRegisterRequest request = new InstanceRegisterRequest();
    4. request.setNamespace("Test");
    5. request.setService("dummy");
    6. request.setHost("127.0.0.1");
    7. request.setPort(10010 + i);
    8. InstanceRegisterResponse instanceRegisterResponse = providerAPI.register(request);
    9. }
  2. 针对其中一个实例连续上报10次失败(模拟业务调用10次失败)

    1. //report 10 continuous failure
    2. for (int i = 0; i < 10; i++) {
    3. ServiceCallResult serviceCallResult = new ServiceCallResult();
    4. serviceCallResult.setNamespace("Test");
    5. serviceCallResult.setService("dummy");
    6. serviceCallResult.setHost("127.0.0.1");
    7. serviceCallResult.setPort(10011);
    8. serviceCallResult.setRetStatus(RetStatus.RetFail);
    9. serviceCallResult.setRetCode(500);
    10. serviceCallResult.setDelay(1000);
    11. consumerAPI.updateServiceCallResult(serviceCallResult);
    12. }
  3. 实例被熔断,通过GetOneInstance无法再获取该实例(已经被剔除)

    1. for (int i = 0; i < 10; i++) {
    2. GetOneInstanceRequest request = new GetOneInstanceRequest();
    3. request.setNamespace("Test");
    4. request.setService("dummy");
    5. InstancesResponse oneInstance = consumerAPI.getOneInstance(request);
    6. Instance instance = oneInstance.getInstance();
    7. //instance port won't be 10010, it's been kick off
    8. System.out.printf("selected instance is %s:%d%n", instance.getHost(), instance.getPort());
    9. }

服务限流

  1. 使用场景

    dummyLimit服务有2个接口,接口/path1最大QPS为100,接口/path2最大QPS为300,规则文本如下:

    1. [
    2. {
    3. "service":"dummyLimit",
    4. "namespace":"Test",
    5. "resource":"QPS",
    6. "type":"LOCAL",
    7. "labels":{
    8. "method":{
    9. "type": "EXACT",
    10. "value":"/path1"
    11. }
    12. },
    13. "amounts":[
    14. {
    15. "maxAmount": 100,
    16. "validDuration": "1s"
    17. }
    18. ]
    19. },
    20. {
    21. "service":"dummyLimit",
    22. "namespace":"Test",
    23. "resource":"QPS",
    24. "type":"LOCAL",
    25. "labels":{
    26. "method":{
    27. "type": "EXACT",
    28. "value":"/path2"
    29. }
    30. },
    31. "amounts":[
    32. {
    33. "maxAmount": 300,
    34. "validDuration": "1s"
    35. }
    36. ]
    37. }
    38. ]

    将规则文本保存为data.json文件,通过接口写入到Polaris服务端

    1. curl -XPOST -H'Content-Type:application/json' -d @data.json 'http://127.0.0.1:8090/naming/v1/ratelimits'
  2. 创建RateLimitAPI

    dummyLimit服务有2个接口,接口/path1最大QPS为100,接口/path2最大QPS为300,规则文本如下:

    1. LimitAPI limitAPI = LimitAPIFactory.createLimitAPI();
    2. //before process exits
    3. limitAPI.destroy();
  3. 针对/path1获取配额

    1. QuotaRequest quotaRequest = new QuotaRequest();
    2. quotaRequest.setNamespace("Test");
    3. quotaRequest.setService("dummyLimit");
    4. Map<String, String> labels = new HashMap();
    5. labels.put("method", "/path1")
    6. QuotaResponse quotaResponse = limitAPI.getQuota(quotaRequest);
    7. if QuotaResultCode.QuotaResultOk == quotaResponse.getCode() {
    8. //quota acquired, now can continue the procedure process
    9. System.out.println("quota result ok")
    10. } else {
    11. //quota limited, we should block the user request
    12. log.Printf("quota result fail, info is %s%n", quotaResponse.getInfo())
    13. }
  4. 针对/path2获取配额

    1. QuotaRequest quotaRequest = new QuotaRequest();
    2. quotaRequest.setNamespace("Test");
    3. quotaRequest.setService("dummyLimit");
    4. Map<String, String> labels = new HashMap();
    5. labels.put("method", "/path2")
    6. QuotaResponse quotaResponse = limitAPI.getQuota(quotaRequest);
    7. if QuotaResultCode.QuotaResultOk == quotaResponse.getCode() {
    8. //quota acquired, now can continue the procedure process
    9. System.out.println("quota result ok")
    10. } else {
    11. //quota limited, we should block the user request
    12. log.Printf("quota result fail, info is %s%n", quotaResponse.getInfo())
    13. }

相关链接

Polaris使用polaris-java - 图3 (opens new window)

Polaris JAVA使用polaris-java - 图4 (opens new window)