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
我们关闭生产者,再次访问触发熔断
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 属性是形同的,但是启动之后却会出现如下异常:
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();
}