侧边栏壁纸
博主头像
樯哥的技术分享网博主等级

学无止境,学以致用,志存高远。

  • 累计撰写 17 篇文章
  • 累计创建 10 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

使用Sentinel实现服务熔断与降级

随心
2023-06-14 / 0 评论 / 0 点赞 / 42 阅读 / 7255 字

服务之间互相调用时,如果A服务连续N次都无法访问到B服务,当N的值超过阈值时,将会熔断,之后会直接禁止对B服务的访问。举个例子来说就是当你请求A服务提供的某个接口,此时A服务通过调用B服务进行处理,但是由于网络故障,A服务一连多次都调用B服务失败,之后你再次请求A服务时,A服务将不再向B服务发送请求,A服务会直接告诉你请求失败,有效降低了故障对系统的影响。此时A服务不再请求B服务,但是又不能让他告诉我一个莫名其妙的错误,因此我们可以在熔断之后让他返回固定默认值,这就是降级。

在这里,这里我只演示使用Feign远程调用时的熔断降级功能。

具体步骤

  1. 接着前面文章中的项目,创建一个支持熔断降级的服务消费者模块,模块名为service-sentinel-feign-consumer。

  2. pom.xml文件内容如下:

    <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>top.jiangqiang</groupId>
            <artifactId>spring-cloud-demo</artifactId>
            <version>${revision}</version>
        </parent>
        <artifactId>service-sentinel-feign-consumer</artifactId>
        <name>${project.artifactId}</name>
        <description>service-sentinel-feign-consumer</description>
        <properties>
            <java.version>17</java.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
                <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>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-loadbalancer</artifactId>
            </dependency>
            <!--使用feign调用接口时必须依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
            <!--流量控制,熔断降级-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            </dependency>
        </dependencies>
    
    </project>
  3. application.yaml文件配置如下:

    server:
      port: 8005
    spring:
      application:
        name: service-sentinel-feign-consumer
      cloud:
        sentinel:
          transport: #使用sentinel控制台时需要配置
            port: 8719
            dashboard: localhost:8080
        nacos:
          username: @nacos.username@ #@***@这种写法表示从pom.xml文件读取配置
          password: @nacos.password@
          config:
            file-extension: yaml
            server-addr: @nacos.server-addr@ #用于管理配置的nacos服务地址
            namespace: @nacos.namespace@ #命名空间
          discovery:
            server-addr: @nacos.server-addr@ #服务发现,服务注册中心地址,因为和配置中心使用同一个nacos,所以地址是同一个。
            namespace: @nacos.namespace@
        loadbalancer: #使用 Spring Cloud Alibaba 社区针对 Spring Cloud Loadbalancer 负载均衡依赖提供的负载均衡策略,以便使用 Spring Cloud Alibaba 提供的所有的能力
          ribbon:
            enabled: false
          nacos: #使用nacos提供的负载均衡,不使用此配置时,默认的负载均衡是轮询
            enabled: true
      config:
        import: #springboot3必须配置此选项,至少配置一个,可以任意配置,配置后会使用nacos配置中心对应的配置
          - optional:nacos:${spring.application.name}.yaml #前面加optional表示可选,允许配置服务器连接不成功时启动服务
          - nacos:datasource.yaml?refresh=true #?refresh=true表示配置更新不需要重启即可生效,可以省略
          - nacos:common.yaml
    feign:
      sentinel:
        enabled: true #feign结合sentinel使用
        
    management:
      endpoints:
        web:
          exposure:
            include: '*' #允许所有的endpoints访问

    注意这几行配置:启用sentinel针对Feign的自动配置,sentinel是一个专门用于限流和熔断降级控制的框架,底层已经完美兼容了feign的写法。

    feign:
      sentinel:
        enabled: true #feign结合sentinel使用
  4. 启动类如下:

    //该注解可以省略
    @EnableDiscoveryClient
    @SpringBootApplication
    //使用feign客户端时必须
    @EnableFeignClients
    public class ServiceSentinelFeignConsumerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ServiceSentinelFeignConsumerApplication.class, args);
        }
    
    }
  5. 服务降级后的处理逻辑代码:

    public class FeignServiceFallback implements FeignService {
        @Override
        public String getPort() {
            return "获取端口号失败,熔断降级生效";
        }
    }
  6. 将降级后的处理逻辑注入为一个Bean,但是这里还没有真的注入,因为类上并没有加@Configuration 注解。这里其实通过该注解也可以实现功能。

    public class FeignConfiguration {
        @Bean
        public FeignServiceFallback echoServiceFallback() {
            return new FeignServiceFallback();
        }
    }
  7. 编写FetchService代码:

    /**
     * configuration后面配置的类中可以使用@Bean注入对象,也可以直接在对应的类上使用@Configuration注解
     */
    @FeignClient(name = "service-provider", fallback = FeignServiceFallback.class, configuration = FeignConfiguration.class)
    public interface FeignService {
        @GetMapping(value = "/getPort")
        String getPort();
    }
  8. 编写一个Controller类

    @RestController
    @RequestMapping("/")
    @RequiredArgsConstructor
    public class TestController {
    
        private final FeignService feignService;
    
        /**
         * 支持熔断降级
         * @return
         */
        @RequestMapping(value = "/getPort1")
        public String getPort1() {
            return "Feign:" + feignService.getPort();
        }
    }
  9. 先启动两个服务提供者,然后访问localhost:8005/getPort1看看能否正常访问,此时通过nacos将两个服务提供者均下线,再访问该地址看看会发生什么。我们可以发现,服务发生了降级,执行了我们编写的降级后的逻辑。

0

评论区