SpringCloud第十八章AlibabaSentinel实现熔断与限流(服务熔断功能)

9、服务熔断功能

  • sentinel整合ribbon+openFeign+fallback

  • Ribbon系列

    • 启动nacos和sentinel

    • 提供者9003/9004

    • 新建cloudalibaba-provider-payment9003/9004两个一样的做法

    • POM

      
      <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>mscloud03artifactId>
              <groupId>com.atguigu.springcloudgroupId>
              <version>1.0-SNAPSHOTversion>
          parent>
          <modelVersion>4.0.0modelVersion>
      
          <artifactId>cloudalibaba-provider-payment9003artifactId>
        <dependencies>
            
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
            dependency>
            <dependency>
                <groupId>com.atguigu.springcloudgroupId>
                <artifactId>cloud-api-commonsartifactId>
                <version>${project.version}version>
            dependency>
            
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-actuatorartifactId>
            dependency>
            
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-devtoolsartifactId>
                <scope>runtimescope>
                <optional>trueoptional>
            dependency>
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
                <optional>trueoptional>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
                <scope>testscope>
            dependency>
        dependencies>
      project>
      
    • YML

      server:
        port: 9003
      
      spring:
        application:
          name: nacos-payment-provider
        cloud:
          nacos:
            discovery:
              server-addr: localhost:8848 #配置Nacos地址
      
      management:
        endpoints:
          web:
            exposure:
              include: '*'
      

      记得修改不同的端口号

    • 主启动

      package com.atguigu.springcloud.alibaba;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
      
      
      @SpringBootApplication
      @EnableDiscoveryClient
      public class PaymentMain9003
      {
          public static void main(String[] args) {
                  SpringApplication.run(PaymentMain9003.class, args);
          }
      }
      
    • 业务类

      package com.atguigu.springcloud.alibaba.controller;
      
      import com.atguigu.springcloud.entities.CommonResult;
      import com.atguigu.springcloud.entities.Payment;
      import org.springframework.beans.factory.annotation.Value;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.PathVariable;
      import org.springframework.web.bind.annotation.RestController;
      
      import java.util.HashMap;
      
      /**
       * @auther zzyy
       * @create 2020-02-13 20:54
       */
      @RestController
      public class PaymentController
      {
          @Value("${server.port}")
          private String serverPort;
      
          public static HashMap<Long,Payment> hashMap = new HashMap<>();
          static
          {
              hashMap.put(1L,new Payment(1L,"28a8c1e3bc2742d8848569891fb42181"));
              hashMap.put(2L,new Payment(2L,"bba8c1e3bc2742d8848569891ac32182"));
              hashMap.put(3L,new Payment(3L,"6ua8c1e3bc2742d8848569891xt92183"));
          }
      
          @GetMapping(value = "/paymentSQL/{id}")
          public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id)
          {
              Payment payment = hashMap.get(id);
              CommonResult<Payment> result = new CommonResult(200,"from mysql,serverPort:  "+serverPort,payment);
              return result;
          }
      
      
      
      }
      
      
      
    • 测试地址 http://localhost:9003/paymentSQL/1

    • 消费者84

      • 新建cloudalibaba-consumer-nacos-order84

      • POM

        
        <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>mscloud03artifactId>
                <groupId>com.atguigu.springcloudgroupId>
                <version>1.0-SNAPSHOTversion>
            parent>
            <modelVersion>4.0.0modelVersion>
        
            <artifactId>cloudalibaba-consumer-nacos-order84artifactId>
        
            <dependencies>
                
                <dependency>
                    <groupId>com.alibaba.cloudgroupId>
                    <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
                dependency>
                
                <dependency>
                    <groupId>com.alibaba.cloudgroupId>
                    <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
                dependency>
                
                <dependency>
                    <groupId>com.atguigu.springcloudgroupId>
                    <artifactId>cloud-api-commonsartifactId>
                    <version>${project.version}version>
                dependency>
                
                <dependency>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-starter-webartifactId>
                dependency>
                <dependency>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-starter-actuatorartifactId>
                dependency>
                
                <dependency>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-devtoolsartifactId>
                    <scope>runtimescope>
                    <optional>trueoptional>
                dependency>
                <dependency>
                    <groupId>org.projectlombokgroupId>
                    <artifactId>lombokartifactId>
                    <optional>trueoptional>
                dependency>
                <dependency>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-starter-testartifactId>
                    <scope>testscope>
                dependency>
            dependencies>
        project>
        
        
      • YML

        server:
          port: 84
          
          spring:
            application:
              name: nacos-order-consumer
            cloud:
              nacos:
                discovery:
                  server-addr: localhost:8848
              sentinel:
                transport:
                  #配置Sentinel dashboard地址
                  dashboard: localhost:8080
                  #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
                  port: 8719
        
        
          #消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
          service-url:
            nacos-user-service: http://nacos-payment-provider
        
      • 主启动

        package com.atguigu.springcloud.alibaba;
        
        import org.springframework.boot.SpringApplication;
        import org.springframework.boot.autoconfigure.SpringBootApplication;
        import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
        
        /**
         * @auther zzyy
         * @create 2020-02-13 20:22
         */
        @EnableDiscoveryClient
        @SpringBootApplication
        public class OrderNacosMain84
        {
            public static void main(String[] args) {
                    SpringApplication.run(OrderNacosMain84.class, args);
            }
        }
        
        
      • 业务类

        ApplicationContextConfig

        package com.atguigu.springcloud.alibaba.config;
        
        import org.springframework.cloud.client.loadbalancer.LoadBalanced;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.web.client.RestTemplate;
        
          @Configuration
          public class ApplicationContextConfig
          {
              @Bean
              @LoadBalanced
              public RestTemplate getRestTemplate()
              {
                  return new RestTemplate();
              }
          }
        

        CircleBreakerController

        • 修改后请重启微服务

          • 热部署对java代码级生效及时
          • 对@SentinelResource注解内属性,有时效果不好
        • 目的

          • fallback管运行异常
          • blockHandler管配置违规
        • 测试地址 http://localhost:84/consumer/fallback/1

        • 没有任何配置

          package com.atguigu.springcloud.alibaba.controller;
          
            import com.alibaba.csp.sentinel.annotation.SentinelResource;
            import com.alibaba.csp.sentinel.slots.block.BlockException;
            import com.atguigu.springcloud.entities.CommonResult;
            import com.atguigu.springcloud.entities.Payment;
            import lombok.extern.slf4j.Slf4j;
            import org.springframework.beans.factory.annotation.Autowired;
            import org.springframework.web.bind.annotation.GetMapping;
            import org.springframework.web.bind.annotation.PathVariable;
            import org.springframework.web.bind.annotation.RequestMapping;
            import org.springframework.web.bind.annotation.RestController;
            import org.springframework.web.client.RestTemplate;
          
            import javax.annotation.Resource;
            import java.sql.SQLException;
            import java.util.concurrent.Executors;
          
            @RestController
            @Slf4j
            public class CircleBreakerController
            {
                public static final String SERVICE_URL = "http://nacos-payment-provider";
          
                @Resource
                private RestTemplate restTemplate;
          
                @RequestMapping("/consumer/fallback/{id}")
                @SentinelResource(value = "fallback") 
                 public CommonResult<Payment> fallback(@PathVariable Long id)
                {
                    CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);
          
                    if (id == 4) {
                        throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
                    }else if (result.getData() == null) {
                        throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
                    }
          
                    return result;
                }
            }
          
          
          

          给客户error页面,不友好

        • 只配置fallback

          编码

          package com.atguigu.springcloud.alibaba.controller;
          
          import com.alibaba.csp.sentinel.annotation.SentinelResource;
          import com.atguigu.springcloud.entities.CommonResult;
          import com.atguigu.springcloud.entities.Payment;
          import lombok.extern.slf4j.Slf4j;
          import org.springframework.web.bind.annotation.PathVariable;
          import org.springframework.web.bind.annotation.RequestMapping;
          import org.springframework.web.bind.annotation.RestController;
          import org.springframework.web.client.RestTemplate;
          
          import javax.annotation.Resource;
          
          
          @RestController
          @Slf4j
          public class CircleBreakerController
          {
              public static final String SERVICE_URL = "http://nacos-payment-provider";
          
              @Resource
              private RestTemplate restTemplate;
          
              @RequestMapping("/consumer/fallback/{id}")
              @SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback负责业务异常
              public CommonResult<Payment> fallback(@PathVariable Long id)
              {
                  CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);
          
                  if (id == 4) {
                      throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
                  }else if (result.getData() == null) {
                      throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
                  }
          
                  return result;
              }
              public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
                  Payment payment = new Payment(id,"null");
                  return new CommonResult<>(444,"兜底异常handlerFallback,exception内容  "+e.getMessage(),payment);
              }
          }
          
          

          图说

          SpringCloud第十八章AlibabaSentinel实现熔断与限流(服务熔断功能)_第1张图片

          本例sentinel无配置

          结果

          在这里插入图片描述

          在这里插入图片描述

          在这里插入图片描述

        • 只配置blockHandler

          • 编码

            package com.atguigu.springcloud.alibaba.controller;
            
            import com.alibaba.csp.sentinel.annotation.SentinelResource;
            import com.alibaba.csp.sentinel.slots.block.BlockException;
            import com.atguigu.springcloud.entities.CommonResult;
            import com.atguigu.springcloud.entities.Payment;
            import lombok.extern.slf4j.Slf4j;
            import org.springframework.beans.factory.annotation.Autowired;
            import org.springframework.web.bind.annotation.GetMapping;
            import org.springframework.web.bind.annotation.PathVariable;
            import org.springframework.web.bind.annotation.RequestMapping;
            import org.springframework.web.bind.annotation.RestController;
            import org.springframework.web.client.RestTemplate;
            
            import javax.annotation.Resource;
            import java.sql.SQLException;
            import java.util.concurrent.Executors;
            
            
            @RestController
            @Slf4j
            public class CircleBreakerController
            {
                public static final String SERVICE_URL = "http://nacos-payment-provider";
            
                @Resource
                private RestTemplate restTemplate;
            
                @RequestMapping("/consumer/fallback/{id}")
                 @SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler负责在sentinel里面配置的降级限流
                public CommonResult fallback(@PathVariable Long id)
                {
                    CommonResult result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);
                    if (id == 4) {
                        throw new IllegalArgumentException ("非法参数异常....");
                    }else if (result.getData() == null) {
                        throw new NullPointerException ("NullPointerException,该ID没有对应记录");
                    }
                    return result;
                }
                public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
                    Payment payment = new Payment(id,"null");
                    return new CommonResult<>(444,"fallback,无此流水,exception  "+e.getMessage(),payment);
                }
                public CommonResult blockHandler(@PathVariable  Long id,BlockException blockException) {
                    Payment payment = new Payment(id,"null");
                    return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException  "+blockException.getMessage(),payment);
                }
            
            }
            
            

            图说

            SpringCloud第十八章AlibabaSentinel实现熔断与限流(服务熔断功能)_第2张图片

            本例sentinel需配置

            SpringCloud第十八章AlibabaSentinel实现熔断与限流(服务熔断功能)_第3张图片

            异常超过2次后,断路器打开,断电跳闸,系统被保护

          • 结果

            在这里插入图片描述

        • fallback和blockHandler都配置

          • 编码

            package com.atguigu.springcloud.alibaba.controller;
            
            import com.alibaba.csp.sentinel.annotation.SentinelResource;
            import com.alibaba.csp.sentinel.slots.block.BlockException;
            import com.atguigu.springcloud.entities.CommonResult;
            import com.atguigu.springcloud.entities.Payment;
            import lombok.extern.slf4j.Slf4j;
            import org.springframework.beans.factory.annotation.Autowired;
            import org.springframework.web.bind.annotation.GetMapping;
            import org.springframework.web.bind.annotation.PathVariable;
            import org.springframework.web.bind.annotation.RequestMapping;
            import org.springframework.web.bind.annotation.RestController;
            import org.springframework.web.client.RestTemplate;
            
            import javax.annotation.Resource;
            import java.sql.SQLException;
            import java.util.concurrent.Executors;
            
            
            @RestController
            @Slf4j
            public class CircleBreakerController
            {
                public static final String SERVICE_URL = "http://nacos-payment-provider";
            
                @Resource
                private RestTemplate restTemplate;
            
                @RequestMapping("/consumer/fallback/{id}")
                 @SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler")
                public CommonResult fallback(@PathVariable Long id)
                {
                    CommonResult result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);
                    if (id == 4) {
                        throw new IllegalArgumentException ("非法参数异常....");
                    }else if (result.getData() == null) {
                        throw new NullPointerException ("NullPointerException,该ID没有对应记录");
                    }
                    return result;
                }
                public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
                    Payment payment = new Payment(id,"null");
                    return new CommonResult<>(444,"fallback,无此流水,exception  "+e.getMessage(),payment);
                }
                public CommonResult blockHandler(@PathVariable  Long id,BlockException blockException) {
                    Payment payment = new Payment(id,"null");
                    return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException  "+blockException.getMessage(),payment);
                }
            
            }
            
            

            图说

            SpringCloud第十八章AlibabaSentinel实现熔断与限流(服务熔断功能)_第4张图片

            本例sentinel需配置

            SpringCloud第十八章AlibabaSentinel实现熔断与限流(服务熔断功能)_第5张图片

          • 结果

            在这里插入图片描述

            若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。

        • 忽略属性…

          • 编码

            package com.atguigu.springcloud.alibaba.controller;
            
            import com.alibaba.csp.sentinel.annotation.SentinelResource;
            import com.alibaba.csp.sentinel.slots.block.BlockException;
            import com.atguigu.springcloud.entities.CommonResult;
            import com.atguigu.springcloud.entities.Payment;
            import lombok.extern.slf4j.Slf4j;
            import org.springframework.beans.factory.annotation.Autowired;
            import org.springframework.web.bind.annotation.GetMapping;
            import org.springframework.web.bind.annotation.PathVariable;
            import org.springframework.web.bind.annotation.RequestMapping;
            import org.springframework.web.bind.annotation.RestController;
            import org.springframework.web.client.RestTemplate;
            
            import javax.annotation.Resource;
            import java.sql.SQLException;
            import java.util.concurrent.Executors;
            
            
            @RestController
            @Slf4j
            public class CircleBreakerController
            {
                public static final String SERVICE_URL = "http://nacos-payment-provider";
            
                @Resource
                private RestTemplate restTemplate;
            
                @RequestMapping("/consumer/fallback/{id}")
                @SentinelResource(value = "fallback", fallback = "handlerFallback", blockHandler = "blockHandler",
                        exceptionsToIgnore = {IllegalArgumentException.class})
                public CommonResult<Payment> fallback(@PathVariable Long id)
                {
                    CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);
                    if (id == 4) {
                        throw new IllegalArgumentException ("非法参数异常....");
                    }else if (result.getData() == null) {
                        throw new NullPointerException ("NullPointerException,该ID没有对应记录");
                    }
                    return result;
                }
                public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
                    Payment payment = new Payment(id,"null");
                    return new CommonResult<>(444,"fallback,无此流水,exception  "+e.getMessage(),payment);
                }
                public CommonResult blockHandler(@PathVariable  Long id,BlockException blockException) {
                    Payment payment = new Payment(id,"null");
                    return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException  "+blockException.getMessage(),payment);
                }
            }
            

            图说

            SpringCloud第十八章AlibabaSentinel实现熔断与限流(服务熔断功能)_第6张图片

            本例sentinel无配置

            • 结果

              SpringCloud第十八章AlibabaSentinel实现熔断与限流(服务熔断功能)_第7张图片

              程序异常打到前台了,对用户不友好

  • Feign系列

    • 修改84模块

      • 84消费者调用提供者9003
      • Feign组件一般是消费侧
    • POM

      
              <dependency>
                  <groupId>org.springframework.cloudgroupId>
                  <artifactId>spring-cloud-starter-openfeignartifactId>
              dependency>
      
    • YML

      激活Sentinel对Feign的支持

      # 激活Sentinel对Feign的支持
      feign:
        sentinel:
          enabled: true  
      
    • 主启动类

      添加**@EnableFeignClients**启动Feign的功能

    • 业务类Controller

      带@FeignClient注解的业务接口

      package com.atguigu.springcloud.alibaba.service;
      
      import com.atguigu.springcloud.alibaba.entities.CommonResult;
      import com.atguigu.springcloud.alibaba.entities.Payment;
      import org.springframework.cloud.openfeign.FeignClient;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.PathVariable;
      
      /**
       * 使用 fallback 方式是无法获取异常信息的,
       * 如果想要获取异常信息,可以使用 fallbackFactory参数
       */
      @FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)//调用中关闭9003服务提供者
      public interface PaymentService
      {
          @GetMapping(value = "/paymentSQL/{id}")
          public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
      }
      
      

      fallback = PaymentFallbackService.class

      package com.atguigu.springcloud.alibaba.service;
      
      import com.atguigu.springcloud.alibaba.entities.CommonResult;
      import com.atguigu.springcloud.alibaba.entities.Payment;
      import org.springframework.stereotype.Component;
      
      
      @Component
      public class PaymentFallbackService implements PaymentService
      {
          @Override
          public CommonResult<Payment> paymentSQL(Long id)
          {
              return new CommonResult<>(444,"服务降级返回,没有该流水信息",new Payment(id, "errorSerial......"));
          }
      }
      
      

      Controller

      package com.atguigu.springcloud.alibaba.controller;
      
      import com.alibaba.csp.sentinel.annotation.SentinelResource;
      import com.alibaba.csp.sentinel.slots.block.BlockException;
      import com.atguigu.springcloud.entities.CommonResult;
      import com.atguigu.springcloud.entities.Payment;
      import lombok.extern.slf4j.Slf4j;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.PathVariable;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
      import org.springframework.web.client.RestTemplate;
      
      import javax.annotation.Resource;
      
      
      @RestController
      @Slf4j
      public class CircleBreakerController
      {
          public static final String SERVICE_URL = "http://nacos-payment-provider";
      
          @Resource
          private RestTemplate restTemplate;
      
          @RequestMapping("/consumer/fallback/{id}")
          //@SentinelResource(value = "fallback") //没有配置
          //@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
          //@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
          @SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",
                  exceptionsToIgnore = {IllegalArgumentException.class})
          public CommonResult<Payment> fallback(@PathVariable Long id)
          {
              CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);
      
              if (id == 4) {
                  throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
              }else if (result.getData() == null) {
                  throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
              }
      
              return result;
          }
          //本例是fallback
          public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
              Payment payment = new Payment(id,"null");
              return new CommonResult<>(444,"兜底异常handlerFallback,exception内容  "+e.getMessage(),payment);
          }
          //本例是blockHandler
          public CommonResult blockHandler(@PathVariable  Long id,BlockException blockException) {
              Payment payment = new Payment(id,"null");
              return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException  "+blockException.getMessage(),payment);
          }
      
          //==================OpenFeign
          @Resource
          private PaymentService paymentService;
      
          @GetMapping(value = "/consumer/openfeign/{id}")
          public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id)
          {
              if(id == 4)
              {
                  throw new RuntimeException("没有该id");
              }
              return paymentService.paymentSQL(id);
          }
      
      }
      
      
    • 验证测试

      http://localhost:84/consumer/paymentSQL/1

      测试84调用9003,此时故意关闭9003微服务提供者,看84消费侧自动降级,不会被耗死

  • 熔断框架比较

    SpringCloud第十八章AlibabaSentinel实现熔断与限流(服务熔断功能)_第8张图片

你可能感兴趣的:(spring,cloud,alibaba,微服务)