目录

springcloudAlibaba_sentinel 和其他框架整合

nacos和openFeign整合

整合说明

  • 使用nacos作为服务注册中心
  • 使用openFeign作为http调用框架
  1. 使用工程cloudalibaba-consumer-nacos-order83作为客户端,cloudalibaba-provider-payment9001作为服务端,服务端会以伪集群方式启动,对外暴露9001端口和9002端口

  2. 以集群模式启动nacos,对外暴露nginx地址:localhost:8888,nacos集群方式安装参考:docker-compose搭建nacos集群

    1
    
    $ dcp -f cluster-hostname.yaml up -d
    
  3. cloudalibaba-provider-payment9001工程

    1. pom

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      
      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
          <parent>
              <artifactId>cloud2020</artifactId>
              <groupId>com.eh</groupId>
              <version>1.0-SNAPSHOT</version>
          </parent>
          <modelVersion>4.0.0</modelVersion>
            
          <artifactId>cloudalibaba-config-nacos-client3377</artifactId>
            
          <dependencies>
              <!--服务注册与发现nacos-->
              <dependency>
                  <groupId>com.alibaba.cloud</groupId>
                  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
              </dependency>
              <!--暴露监控端点供外部使用-->
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-actuator</artifactId>
              </dependency>
              <!--整合web-->
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
              <!--引入通用包,主要使用CommonResult类-->
              <dependency>
                  <groupId>org.eh</groupId>
                  <artifactId>cloud-common</artifactId>
                  <version>1.0-SNAPSHOT</version>
              </dependency>
          </dependencies>
            
      </project>
      
    2. yml

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      
      server:
        port: 9001
            
      spring:
        application:
          name: cloudalibaba-provider-payment9001
        cloud:
          nacos:
            discovery:
              #配置nacos地址
              server-addr: localhost:8888
            
      management:
        endpoints:
          web:
            exposure:
              include: '*'
      
    3. 主启动类

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      
      package com.eh.cloud.alibaba.nacos.payment;
            
      import com.eh.cloud2020.common.entity.CommonResult;
      import org.springframework.beans.factory.annotation.Value;
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.PathVariable;
      import org.springframework.web.bind.annotation.RestController;
            
      @EnableDiscoveryClient
      @SpringBootApplication
      public class NacosPaymentMain9001 {
          public static void main(String[] args) {
              SpringApplication.run(NacosPaymentMain9001.class, args);
          }
            
          @RestController
          class PaymentController {
              @Value("${server.port}")
              private String serverPort;
            
              @GetMapping(value = "/payment/{id}")
              public CommonResult<String> getPayment(@PathVariable("id") Integer id) {
                  return CommonResult.success("cloudalibaba-provider-payment9001,serverPort:" + serverPort + ",id:" + id);
              }
          }
      }
      
    4. 伪集群配置

      http://img.cana.space/picStore/20201115225922.png

    5. 启动9001和9002

    6. 测试

      • http://localhost:9001/payment/1

        1
        2
        3
        4
        5
        
        {
          "code": 200,
          "desc": "处理成功",
          "data": "cloudalibaba-provider-payment9001,serverPort:9001,id:1"
        }
        
      • http://localhost:9002/payment/1

        1
        2
        3
        4
        5
        
        {
          "code": 200,
          "desc": "处理成功",
          "data": "cloudalibaba-provider-payment9001,serverPort:9002,id:1"
        }
        
      • http://localhost:8888/nacos/ 服务列表

        http://img.cana.space/picStore/20201115230051.png

  4. cloudalibaba-consumer-nacos-order83工程

    1. pom

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      
      <dependencies>
          <!--服务注册与发现nacos-->
          <dependency>
              <groupId>com.alibaba.cloud</groupId>
              <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
          </dependency>
          <!--整合openFeign-->
          <!--SpringCloud openfeign -->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-openfeign</artifactId>
          </dependency>
          <!--整合web-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <!--引入通用包,主要使用CommonResult类-->
          <dependency>
              <groupId>org.eh</groupId>
              <artifactId>cloud-common</artifactId>
              <version>1.0-SNAPSHOT</version>
          </dependency>
      </dependencies>
      
    2. yml

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      
      server:
        port: 83
            
      spring:
        application:
          name: cloudalibaba-consumer-nacos-order83
        cloud:
          nacos:
            discovery:
              #配置nacos地址
              server-addr: localhost:8888
      
    3. 业务类

      使用feign引入服务端服务

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      
      package com.eh.cloud.alibaba.nacos.consumer.service;
            
      import com.eh.cloud2020.common.entity.CommonResult;
      import org.springframework.cloud.openfeign.FeignClient;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.PathVariable;
            
      @FeignClient(value = "cloudalibaba-provider-payment9001")
      public interface PaymentService {
            
          @GetMapping(value = "/payment/{id}")
          CommonResult<String> getPayment(@PathVariable("id") Integer id);
                
      }
      
    4. 主启动

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      
      package com.eh.cloud.alibaba.nacos.consumer;
            
      import com.eh.cloud.alibaba.nacos.consumer.service.PaymentService;
      import com.eh.cloud2020.common.entity.CommonResult;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
      import org.springframework.cloud.openfeign.EnableFeignClients;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.PathVariable;
      import org.springframework.web.bind.annotation.RestController;
            
      @EnableFeignClients // fegin
      @EnableDiscoveryClient // nacos 服务注册
      @SpringBootApplication
      public class NacosOrderMain83 {
          public static void main(String[] args) {
              SpringApplication.run(NacosOrderMain83.class, args);
          }
            
          @RestController
          class OrderController {
            
              @Autowired
              private PaymentService paymentService;
            
              @GetMapping(value = "/order/payment/{id}")
              public CommonResult<String> paymentInfo(@PathVariable("id") Integer id) {
                  CommonResult<String> paymentResult = paymentService.getPayment(id);
                  return CommonResult.success("from order consumer:" + paymentResult.getData());
              }
          }
      }
      
    5. 测试

      • nacos服务注册中心会多出客户端实例
      • 访问http://localhost:83/order/payment/1,多刷几次,端口号在9002和9001交替

至此,服务注册与发现nacos和服务调用openFeign的整合完毕,接下来开始整合熔断降级功能sentinel

整合sentinel

  1. 启动sentinel

    1
    
    $ java -jar sentinel-dashboard-1.8.0.jar
    
  2. 改造客户端 cloudalibaba-consumer-nacos-order83

    1. pom

      注意这里我将父pom中 cloud版本改成了Hoxton.SR5,因为2.2.3.RELEASE的cloudalibaba中的sentinel依赖feign中的一个方法parseAndValidateMetadata,这个方法在2.2.0.RELEASE版本拼写错误

      1
      2
      
      // TODO: break this and correct spelling at some point
      List<MethodMetadata> parseAndValidatateMetadata(Class<?> targetType);
      

      2.2.2.RELEASE改过来了

      1
      
      List<MethodMetadata> parseAndValidateMetadata(Class<?> targetType);
      

      如果用H.SR1依赖的还是2.2.0的方法名,启动时sentinel会报找不到方法

      引入sentinel

      1
      2
      3
      4
      5
      
      <!--限流、熔断降级sentinel -->
          <dependency>
              <groupId>com.alibaba.cloud</groupId>
              <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
          </dependency>
      

      完整配置:

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      
      <dependencies>
          <!--限流、熔断降级sentinel -->
          <dependency>
              <groupId>com.alibaba.cloud</groupId>
              <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
          </dependency>
          <!--服务注册与发现nacos-->
          <dependency>
              <groupId>com.alibaba.cloud</groupId>
              <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
          </dependency>
          <!--整合openFeign-->
          <!--SpringCloud openfeign -->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-openfeign</artifactId>
          </dependency>
          <!--整合web-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <!--引入通用包,主要使用CommonResult类-->
          <dependency>
              <groupId>org.eh</groupId>
              <artifactId>cloud-common</artifactId>
              <version>1.0-SNAPSHOT</version>
          </dependency>
      </dependencies>
      
    2. yml

      增加sentinel相关配置,完整配置如下:

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      
      server:
        port: 83
            
      spring:
        application:
          name: cloudalibaba-consumer-nacos-order83
        cloud:
          nacos:
            discovery:
              #配置nacos地址
              server-addr: localhost:8888
          # sentinel配置
          sentinel:
            transport:
              dashboard: localhost:8080
              # 指定应用与sentinel控制台交互的端口,应用本地会起一个该端口占用的httpserver
              # 默认8719,假如被占用了会自动从8719开始依次+1扫描,直至找到未被占用的端口
              port: 8719
      # 激活sentinel对feign的支持,可以像hystrix一样使用fallback进行降级
      feign:
        sentinel:
          enabled: true
      
    3. 业务类

      新增对服务端服务调用降级功能,针对服务级别的进行fallback处理,新增PaymentFallbackService类如下:

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      
      package com.eh.cloud.alibaba.nacos.consumer.service;
            
      import com.eh.cloud2020.common.entity.CommonResult;
      import org.springframework.stereotype.Service;
            
      @Service
      public class PaymentFallbackService implements PaymentService {
            
          @Override
          public CommonResult<String> getPayment(Integer id) {
              return CommonResult.error(444, "服务端繁忙,请稍后再试");
          }
      }
      

      改造服务调用类PaymentService,指定fallback处理类

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      
      package com.eh.cloud.alibaba.nacos.consumer.service;
            
      import com.eh.cloud2020.common.entity.CommonResult;
      import org.springframework.cloud.openfeign.FeignClient;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.PathVariable;
            
      @FeignClient(value = "cloudalibaba-provider-payment9001", fallback = PaymentFallbackService.class)
      public interface PaymentService {
            
          @GetMapping(value = "/payment/{id}")
          CommonResult<String> getPayment(@PathVariable("id") Integer id);
            
      }
      
    4. 启动主程序

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      
      package com.eh.cloud.alibaba.nacos.consumer;
            
      import com.eh.cloud.alibaba.nacos.consumer.service.PaymentService;
      import com.eh.cloud2020.common.entity.CommonResult;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
      import org.springframework.cloud.openfeign.EnableFeignClients;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.PathVariable;
      import org.springframework.web.bind.annotation.RestController;
            
      @EnableFeignClients // fegin
      @EnableDiscoveryClient // nacos 服务注册
      @SpringBootApplication
      public class NacosOrderMain83 {
          public static void main(String[] args) {
              SpringApplication.run(NacosOrderMain83.class, args);
          }
            
          @RestController
          class OrderController {
            
              @Autowired
              private PaymentService paymentService;
            
              @GetMapping(value = "/order/payment/{id}")
              public CommonResult<String> paymentInfo(@PathVariable("id") Integer id) {
                  CommonResult<String> paymentResult = paymentService.getPayment(id);
                  if (200 == paymentResult.getCode()) {
                      return CommonResult.success("from order consumer:" + paymentResult.getData());
                  } else {
                      return CommonResult.error(paymentResult.getCode(), "from order consumer:" + paymentResult.getDesc());
                  }
              }
          }
      }
      
    5. 访问http://localhost:83/order/payment/1,可以看到sentinel dashboard服务列表上能看到服务

      http://img.cana.space/picStore/20201116000224.png

  3. 配置客户端对服务调用降级规则

    http://img.cana.space/picStore/20201116002415.png

    如果对服务端调用耗时超过1ms就降级,降级规则如上

  4. 快速访问几次:http://localhost:83/order/payment/1,可以看到返回信息已经改成我们自定义的了

    http://img.cana.space/picStore/20201116002612.png

至此,nacos+feign+sentinel整合完毕

sentinel使用nacos作为数据源进行持久化

问题

到目前为止一切都进行地很好,但是还有一个问题,一旦我们重启配置了sentinel规则的应用,sentinel规则就将小时,如何将配置规则持久化呢?

解决

可以将限流配置规则持久化到Nacos配置中心,只要刷新应用的某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上Sentinel上的流控规则持续有效

首先需要在nacos配置中心增加数据源配置,如下:

  • Data ID:cloudalibaba-consumer-nacos-order83-datasource

  • Group:DEFAULT_GROUP

  • 配置格式:JSON

  • 配置内容

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    [
        {
            "resource": "GET:http://cloudalibaba-provider-payment9001/payment/{id}",
            "limitApp": "default",
            "grade": 1,
            "count": 1,
            "strategy": 0,
            "controlBehavior": 0,
            "clusterMode": false
        }
    ]
    

    参考:https://www.jianshu.com/p/fb3218b21da5

    属性解释如下:

    resource:资源名,即限流规则的作用对象

    **limitApp:流控针对的调用来源,**若为 default 则不区分调用来源

    grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1代表根据QPS来进行流量控制

    count:限流阈值

    strategy:调用关系限流策略

    controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)

    clusterMode:是否为集群模式

    注意:在完成了上面的整合之后,对于接口流控规则的修改就存在两个地方了:Sentinel控制台、Nacos控制台。

    这个时候,通过Nacos修改该条规则是可以同步到Sentinel的但是通过Sentinel控制台修改或新增却不可以同步到Nacos。因为当前版本的Sentinel控制台不具备同步修改Nacos配置的能力。

    而Nacos由于可以通过在客户端中使用Listener来实现自动更新。所以,在整合了Nacos做规则存储之后,需要知道在下面两个地方修改存在不同的效果:

    Sentinel控制台中修改规则:仅存在于服务的内存中,不会修改Nacos中的配置值,重启后恢复原来的值。Nacos控制台中修改规则:服务的内存中规则会更新,Nacos中持久化规则也会更新,重启后依然保持。

改造cloudalibaba-consumer-nacos-order83

  1. pom

    新引入

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    <!--持久化规则配置-->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-nacos</artifactId>
    </dependency>
    <!--由于要使用到nacos配置中心,需要暴露一些监控端点-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    

    完整配置

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    
    <dependencies>
        <!--持久化规则配置-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        <!--由于要使用到nacos配置中心,需要暴露一些监控端点-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--限流、熔断降级sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--服务注册与发现nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--整合openFeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--整合web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--引入通用包,主要使用CommonResult类-->
        <dependency>
            <groupId>org.eh</groupId>
            <artifactId>cloud-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
    
  2. yml

    增加数据源——nacos配置中心相关配置

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    
    server:
      port: 83
       
    spring:
      application:
        name: cloudalibaba-consumer-nacos-order83
      cloud:
        nacos:
          discovery:
            #配置nacos地址
            server-addr: localhost:8888
        # sentinel配置
        sentinel:
          transport:
            dashboard: localhost:8080
            # 指定应用与sentinel控制台交互的端口,应用本地会起一个该端口占用的httpserver
            # 默认8719,假如被占用了会自动从8719开始依次+1扫描,直至找到未被占用的端口
            port: 8719
          datasource:
            d1:
              nacos:
                server-addr: localhost:8848
                dataId: cloudalibaba-sentinel-service
                groupId: DEFAULT_GROUP
                data-type: json
                rule-type: flow
    # 暴露监控端点,供配置中心调用,nacos自带类似webhook+bus功能
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    # 激活sentinel对feign的支持,可以像hystrix一样使用fallback进行降级
    feign:
      sentinel:
        enabled: true
    
  3. 一切妥当以后,重启客户端cloudalibaba-consumer-nacos-order83,发现流控规则里已经有了我们在nacos配置中心中进行的配置

    http://img.cana.space/picStore/20201116010011.png

  4. 编辑配置中心,将阈值设置成5 然后发布,刷新sentinel dashboard,可以看到阈值已经变成5了

    http://img.cana.space/picStore/20201116010147.png

至此,nacos+openFeign+sentinel+sentinel持久化整合完毕。