SpringCloud Alibaba(上)

SpringCloud Alibaba(上)

moran
2021-01-31 / 0 评论 / 12 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2021年04月14日,已超过71天没有更新,若内容或图片失效,请留言反馈。

SpringCloud Alibaba

概述

因为springcloud netflix项目进入了维护,因此出现alibaba版本。
维护信息

SpringCloud Alibaba github官网

学习资料


官网
github
教程
中文教程

Nacos服务注册和配置中心

前四个字符分别为Naming和Configuration的前两个字母,最后的s为service。

Nacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
其实就是注册中心+配置中心的组合。Nacos=Eureka+config+bus

github
官网
springcloud对Nacos的教程

启动

将下载好的nacos解压,进入bin目录运行startup.cmd,访问http://localhost:8848/nacos显示web界面就代表搭建成功。默认用户名和密码都是nacos。

服务注册中心简单例子

SpringCloud alibaba

基于Nacos的服务提供者

  • pom
 <dependencies>
        <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-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>
    </dependencies>
  • application.yml
    server:
      port: 9001

    spring:
      application:
        name: nacos-payment-provider
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848 #配置Nacos地址

    management:
      endpoints:
        web:
          exposure:
            include: '*'
  • 主启动类
    package com.atguigu.springcloud;

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

    @EnableDiscoveryClient
    @SpringBootApplication
    public class PaymentMain9001 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain9001.class,args);
        }
    }
  • 控制器
    @RestController
    public class PaymentController
    {
        @Value("${server.port}")
        private String serverPort;

        @GetMapping(value = "/payment/nacos/{id}")
        public String getPayment(@PathVariable("id") Integer id)
        {
            return "nacos registry, serverPort: "+ serverPort+"\t id"+id;
        }
    }

当服务提供者启动成功后就可以在Nacos的web界面中的服务列表看到微服务名称。

虚拟映射

在测试中,如果想要以一个启动类启动两个微服务,可以使用虚拟映射的方法。

基于Nacos的服务消费者

  • pom
<dependencies>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
  • application.yml
    server:
      port: 83

    spring:
      application:
        name: nacos-order-consumer
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848

    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;

    @EnableDiscoveryClient
    @SpringBootApplication
    public class OrderNacosMain83
    {
        public static void main(String[] args)
        {
            SpringApplication.run(OrderNacosMain83.class,args);
        }
    }

使用@EnableDiscoveryClient注解开启服务注册发现功能

  • config类
    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();
        }
    }

注意必须要使用负载均衡@LoadBalanced注解,不然启动会报错。

  • 控制器类
    @RestController
    @Slf4j
    public class OrderNacosController
    {
        @Resource
        private RestTemplate restTemplate;

        @Value("${service-url.nacos-user-service}")
        private String serverURL;

        @GetMapping(value = "/consumer/payment/nacos/{id}")
        public String paymentInfo(@PathVariable("id") Long id)
        {
            return restTemplate.getForObject(serverURL+"/payment/nacos/"+id,String.class);
        }

    }

启动后就可以在Nacos服务注册中心的服务列表看到微服务名

Nacos自带负载均衡,可以从Nacos的依赖中看出。

各种注册中心比较




服务配置中心简单例子

  • pom.xml
    <dependencies>
        <!--nacos-config-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!--nacos-discovery-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--web + actuator-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--一般基础配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
  • bootstrap.yml
    server:
      port: 3377

    spring:
      application:
        name: nacos-config-client
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848 #服务注册中心地址
          config:
            server-addr: localhost:8848 #配置中心地址
            file-extension: yaml #指定yaml格式的配置
  • application.yml
    spring:
      profiles:
        active: dev


两个配置连在一起就会从配置中心获取对应环境配置。


简单来说就是:微服务名-环境.后缀


  • 主启动类
    package com.atguigu.springcloud.alibaba;

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

    @EnableDiscoveryClient
    @SpringBootApplication
    public class NacosConfigClientMain3377
    {
        public static void main(String[] args) {
            SpringApplication.run(NacosConfigClientMain3377.class, args);
        }
    }
  • 控制器类
    @RestController
    @RefreshScope // 支持Nacos的动态刷新功能
    public class ConfigClientController
    {
        @Value("${config.info}")
        private String configInfo;

        @GetMapping("/config/info")
        public String getConfigInfo() {
            return configInfo;
        }
    }

将该微服务启动后,访问http://localhost:3377/config/info就可以显示nacos上的配置信息,同时支持动态刷新。

分类配置




DataId



再次访问http://localhost:3377/config/info

Group



再次访问就可以加载指定组的指定配置文件。

命名空间

新建命名空间


在dev命名空间下新建yaml配置

再次访问

Nacos集群和持久化配置

官网说明



初始化文件也在nacos目录下的config文件夹下。

使用

  • 下载linux版本的nacos

github
下载linux版本的nacosnacos并解压

  • 配置数据库
    配置Nacos文件夹下的config/application.properties将数据库配置好。


注意:前提是数据库导入nacos的sql完成并启动。

  • 配置nacos集群


ip需要是自己服务器的ip。如果是虚拟机可以通过hostname -i查看ip。

  • 修改启动脚本
    官网给的startup.sh是不能打开不同端口的Nacos的,需要手动更改脚本。


修改内容:


注意:nohup是不挂断运行,比如连接xshell启动java,断开后,java也会随之关闭,如果使用nohup为前缀启动就不会关闭。
&是后台运行。
执行脚本:

  • Nginx配置,作为负载均衡器
    修改nginx:


修改内容:

按照指定文件启动nginx:

启动nginx,通过1111端口访问访问nginx,nginx会代理到nacos。
然后就可以通过1111访问配置文件

Sentinel

SpringCloud Alibaba Sentel实现熔断与限流
github官网
github中文官网

作用

下载

链接
下载jar包。

服务端使用


通过java -jar sentinel-dashboard-1.8.0.jar命名启动sentinel管理界面
访问:http://localhost:8080/进入管理界面,用户密码默认为sentinel

客户端简单例子

  • pom.xml
<dependencies>
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.6.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>
  • application.yml
    server:
      port: 8401

    spring:
      application:
        name: cloudalibaba-sentinel-service
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
        sentinel:
          transport:
            dashboard: localhost:8080
            port: 8719  #默认8719,假如被占用了会自动从8719开始依次+1扫描。直至找到未被占用的端口

    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;

    @EnableDiscoveryClient
    @SpringBootApplication
    public class MainApp8401
    {
        public static void main(String[] args) {
            SpringApplication.run(MainApp8401.class, args);
        }
    }
  • 控制器类
    @RestController
    public class FlowLimitController
    {
        @GetMapping("/testA")
        public String testA() {
            return "------testA";
        }

        @GetMapping("/testB")
        public String testB() {

            return "------testB";
        }
    }

启动该微服务,然后会发现sentinel管理界面还是什么都没有,这是因为sentinel是采用懒加载模式,需要用户去访问才会出现。

流控规则

访问http://localhost:8401/testA则会出现

流控模式


  • 直接(默认)
    /testA新增流控规则


单机阈值就是每秒访问次数。当访问次数大于时,会默认出现

但是,默认视图不是我们想要的。因此需要修改

线程数:

线程数是指同时处理请求的数量,为1则表示1次只能处理一个请求。

  • 关联
    当关联的资源达到阈值,就限流自己。

比如:当A关于B,B的资源达到阈值,那么A就也被限流。

  • 链路
    多个请求调用一个微服务。

流控效果

  • 直接失败
    直接抛出错误
  • 预热
    公式:阈值除以coldFactor(默认值为3),经过预热时长后才会达到阈值



  • 排队等待


sentinel的熔断降级




Sentinel的断路器是没有半开状态的

  • RT

秒级平均响应时间
测试:

  • 异常比例

  • 异常数

当一分钟异常数超过阈值就会熔断。
测试代码:

    @GetMapping("/testE")
    public String testE()
    {
        log.info("testE 测试异常数");
        int age = 10/0;
        return "------testE 测试异常数";
    }

当一分钟内异常数超出阈值,就会熔断指定时长。

热点Key限流


github介绍

  • 控制器方法
       @GetMapping("/testHotKey")
        @SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
        public String testHotKey(@RequestParam(value="p1",required = false) String p1,
                                 @RequestParam(value = "p2",required = false) String p2){
            return "-------testHotKey";
        }

        public String deal_testHotKey(String p1, String p2, BlockException exception){
            return "----------deal_testHotKey,o(╥﹏╥)o";
        }

注解@SentinelResource用于配置热点规则,value为热点规则名称,在sentinel web界面控制热点规则也是使用这个名称,blockHandler是兜底的方法。兜底方法的方法参数要一致(h可以引入异常类)。

如上图的配置后,如果加入第一个参数(参数位置为0),那么1秒内只能请求1次。否则降级处理。其他参数没有限制。
注意:如果没有指定blockHandler方法,那么降级将会爆出错误页面。

参数例外项

当新增特点规则为第一个参数1s内只能请求1次时,某些特定情况下,比如当第一个参数的值为特定值不希望和平常限流值一致,那么这种情况可以使用参数例外项。(比如之前的案例,当p1为5时,阈值可以为200)

通过如上的配置后,当参数p1为5时,qps就为200.

注意:注解@SentinelResource控制的是web界面的配置,对这些配置进行降级,如果程序本身出现异常是不会有降级策略的。

系统规则


简单来讲,就是对整个系统进行控制。

当对系统规则中的入口QPS控制后,不管什么请求,其qps都不能超过限定的阈值。

注解@SentinelResource使用

sentinel可以按照资源名称和url地址进行控制

按url地址限流

  • 控制器方法
    @GetMapping("/rateLimit/byUrl")
        @SentinelResource(value = "byUrl")
        public com.atguigu.springcloud.entities.CommonResult byUrl()
        {
            return new com.atguigu.springcloud.entities.CommonResult(200,"按url限流测试OK",new com.atguigu.springcloud.entities.Payment(2020L,"serial002"));
            }

方法并没有兜底方法,因此如果sentinel限流了那么将会抛出sentinel默认错误(Blocked by Sentinel(flow limiting))。

  • sentinel控制台


解决:
创建CustomerBlockHandler类用于自定义限流处理逻辑

  • CustomerBlockHandler.java
    package com.atguigu.springcloud.alibaba.myHandler;

    import com.atguigu.springcloud.entities.Payment;
    import com.alibaba.csp.sentinel.slots.block.BlockException;
    import com.atguigu.springcloud.entities.CommonResult;

    public class CustomerBlockHandler {

        public static CommonResult handlerException(BlockException exception){
            return new CommonResult(200,"按客户自定义,global",new Payment(2020L,"serial003-------1"));
        }

        public static CommonResult handlerException2(BlockException exception){
            return new CommonResult(200,"按客户自定义,global",new Payment(2020L,"serial003--------2"));
        }
    }
  • 控制器方法
    @GetMapping("/rateLimit/customerBlockHandler")
        @SentinelResource(value = "customerBlockHandler",blockHandlerClass = CustomerBlockHandler.class,blockHandler = "handlerException2")
        public CommonResult customerBlockHandler()
        {
            return new CommonResult(200,"按客户自定义", new Payment(2020L,"serial002"));
        }

那么customerBlockHandler的兜底方法将会是CustomerBlockHandler类下的handlerException2方法。

注意:sentinel还可以通过代码的方式配置限流等。

服务熔断功能

整合Ribbon

服务提供者9003/9004
  • pom.xml
     <dependencies>
            <!--SpringCloud ailibaba nacos -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
            <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
                <groupId>com.atguigu.springcloud</groupId>
                <artifactId>cloud-api-commons</artifactId>
                <version>${project.version}</version>
            </dependency>
            <!-- SpringBoot整合Web组件 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <!--日常通用jar包配置-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
  • application.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;

    @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;
        }
    }

测试

同理搭建9004.

服务消费者84
  • pom.xml
    <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            </dependency>
            <dependency>
                <groupId>com.atguigu.springcloud</groupId>
                <artifactId>cloud-api-commons</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
  • application.yml
    server:
      port: 84

    spring:
      application:
        name: nacos-order-consumer
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
        sentinel:
          transport:
            dashboard: localhost:8080
            port: 8719

    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;
    import org.springframework.cloud.openfeign.EnableFeignClients;

    @EnableDiscoveryClient
    @SpringBootApplication
    @EnableFeignClients
    public class OrderNacosMain84
    {
        public static void main(String[] args) {
            SpringApplication.run(OrderNacosMain84.class, args);
        }
    }
  • 配置类
    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();
        }
    }

向ioc容器中注入restTemplate,并开启负载均衡功能。

  • 控制器类
    package com.atguigu.springcloud.alibaba.controller;

    import com.alibaba.csp.sentinel.annotation.SentinelResource;
    import com.alibaba.csp.sentinel.slots.block.BlockException;
    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 com.atguigu.springcloud.entities.CommonResult;
    import com.atguigu.springcloud.entities.Payment;

    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);
        }
    }

按照上面的代码就可以实现负载均衡轮循的效果。当参数id为4或5时会抛出指定异常。但异常界面不友好,因此需要配置。

将注解@SentinelResource的属性fallback配置上

@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常

如上配置后,就不会出现error界免,会进入异常错误兜底方法。
而当配置属性blockHandler而不配置fallback,那么只会对sentinel的控制台配置进行兜底,而不对程序异常进行兜底。
如果两者都配置的话,那么只会进入blockHandler的兜底方法进行处理。

忽略属性:

0

评论 (0)

取消