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

}
posted on 2020-12-24 13:53  被遗忘的优雅  阅读(2704)  评论(0编辑  收藏  举报