• openfeign + hystrix 实现远程调用,配置熔断、超时、多 name


    1,前提条件

    生产者和消费者两个项目必须都注册到同一个注册中心

    2,生产者

    生产者无需特殊配置,只需要是一个正常的web项目并且提供可访问的接口即可,接口示例如下

    package com.hwq.data.base.client;
    
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class HomeClient {
        @GetMapping("/client/home/index")
        public String index() {
            return "Open Feign";
        }
    }
    

    3,消费者

    1,pom.xml
    <!-- 远程调用 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-archaius</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-netflix-archaius</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <!-- Hystrix 熔断器 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-archaius</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-netflix-archaius</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
    2,配置开启熔断功能
    feign:
      hystrix:
        # 开启熔断器
        enabled: true
    
    3,启动类
    package com.hwq.admin.back;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    
    @SpringBootApplication  // 启动 SpringBoot 项目
    @EnableDiscoveryClient  // 启动 服务发现客户端 功能
    @EnableFeignClients     // 启动 远程调用
    public class AdminBackApp {
    
        public static void main(String[] args) {
            SpringApplication.run(AdminBackApp.class);
        }
    
    }
    
    4,FeignClient 接口
    package com.hwq.admin.back.feign;
    
    import com.hwq.admin.back.feign.impl.HomeFeignImpl;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    
    // 声明为 feign 远程调用,name:生产者项目名,fallback:发生错误或超时时的熔断类
    @FeignClient(name = "sc-web-data-base", fallback = HomeFeignImpl.class)
    public interface HomeFeign {
    
        // 这里的方法签名要和生产者保持一致
        @GetMapping("/client/home/index")
        String index();
    
    }
    
    5,熔断类

    该类需要实现 FeignClient 接口,并且配置在 fallback 参数中

    package com.hwq.admin.back.feign.impl;
    
    import com.hwq.admin.back.feign.HomeFeign;
    import org.springframework.stereotype.Component;
    
    @Component
    public class HomeFeignImpl implements HomeFeign {
    
        @Override
        public String index() {
            return "触发熔断";
        }
    
    }
    
    5,调用的控制层
    package com.hwq.admin.back.controller;
    
    import com.hwq.admin.back.feign.HomeFeign;
    import com.hwq.admin.back.vo.ResultVO;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class HomeController {
    
        // FeignClient 接口 可以直接注入使用
        @Autowired
        private HomeFeign homeFeign;
    
        @GetMapping("/home/feign")
        public ResultVO<String> fegin() {
            String index = homeFeign.index();
            return ResultVO.success("OK", index);
        }
        
    }
    

    4,测试

    启动项目后,访问:http://localhost:2011/home/feign

    image-20201224113016474

    我们关闭生产者,再次访问触发熔断

    image-20201224113238752

    5,超时配置

    配置超时可有效防止因为程序性能问题导致的长时间无响应,并且造成线程池忙碌堵塞

    feign:
      hystrix:
        # 开启熔断器,如果要采用
        enabled: true
    
    ribbon:
      # 远程请求调用的超时时间 5 秒
      ConnectTimeout: 5000
      # 连接后的等待处理的超时时间 30 分钟
      ReadTimeout: 1800000
      # 最大重试次数,当注册中心中可以找到服务,但是服务连不上时将会重试
      MaxAutoRetries: 0
      # 切换实例的重试次数
      MaxAutoRetriesNextServer: 0
    
    hystrix:
      command:
        default:
          execution:
            isolation:
              thread:
                # 触发熔断的超时时间
                timeoutInMilliseconds: 1801000
    
    • openfeign 是依赖于 ribbon 的,所以超时配置配置 ribbon
    • ribbon 配置下的项必须使用驼峰,使用中横线会失效,虽然这看起来怪怪的
    • 重生次数建议设置为 0,否则会出现幂等性的问题,当然查询的无所谓
    • 熔断触发的超时时间应该大于 (ConnectTimeout + ReadTimeout)* (总重试次数 + 1)
    • 总重试次数 = MaxAutoRetries * MaxAutoRetriesNextServer + 1

    6,相同 name 配置

    1,场景

    我们在开发中常常会配置多个 feignclient 指向同一个服务,这必然导致这些接口的 name 属性是形同的,但是启动之后却会出现如下异常:

    image-20201224132952126

    2,原因

    如果我们要创建多个具有相同名称或URL的伪客户端,以便它们指向同一台服务器,但每个客户端具有不同的自定义配置,则必须使用的contextId属性

    3,解决办法
    package com.hwq.admin.back.feign;
    
    import com.hwq.admin.back.feign.impl.HomeFeignImpl;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    
    // 声明为 feign 远程调用,name:生产者项目名,contextId: 唯一标识,fallback:发生错误或超时时的熔断类
    @FeignClient(name = "sc-web-data-base", contextId = "home", fallback = HomeFeignImpl.class)
    public interface HomeFeign {
    
        // 这里的签名要和生产者保持一致
        @GetMapping("/client/home/index")
        String index();
    
    }
    
  • 相关阅读:
    C programming course
    关于时间管理的培训心得
    吴老师,一路好走!
    自己实现Int32Collection(.Net 1.1),以及效率问题的体会
    《C陷阱与缺陷》和《C专家编程》两本书又翻印了
    暂时闲一会,写一点点面试体会吧
    人类没有一件事是值得烦恼的
    EP0N系统中简便可行的光纤保护方法
    越来越不想写代码了
    [转]PON关键技术-通用成帧协议研究
  • 原文地址:https://www.cnblogs.com/lovling/p/14183659.html
Copyright © 2020-2023  润新知