文章目录
1. 是什么
feign是声明式的web service客户端,它让微服务之间的调用变得更简单了,只需要创建一个接口,接口上面加注解@FeignClient即可,类似controller调用service。Feign与Ribbon和Eureka可以支持负载均衡
2. 能做什么
使编写Java Http客户端变得容易,它定义和实现依赖服务接口的定义,在在为服务接口上面添加Feign注解即可完成对服务提供方的接口绑定。Feign通过接口的方法调用Rest服务(相当于Ribbon + RestTemplate),该请求发送给Eureka服务器,通过Feign直接找到服务接口,由于在进行服务调用的时候融合了Ribbon技术,所以也支持负载均衡。(Feing面试接口,Ribbon面向RestTemplate)
3. 为什么选择Feign
简单并且可以自定义编码器及错误处理(其它技术有Apache HttpClient,使用 Jersey 和 CXF 这些来写一个 Rest 或 SOAP 服务的java客服端)
4. Feign原理
- 启动时,程序会进行包扫描,扫描所有包下所有@FeignClient注解的类,并将这些类注入到spring的IOC容器中。当定义的Feign中的接口被调用时,通过JDK的动态代理来生成RequestTemplate。
- RequestTemplate中包含请求的所有信息,如请求参数,请求URL等。
- RequestTemplate声明Request,然后将Request交给client处理,这个client默认是JDK的HTTPUrlConnection,也可以是OKhttp、Apache的HTTPClient等
- 最后client封装成LoadBaLanceClient,结合ribbon负载均衡地发起调用
更多内容,参见:https://xli1224.github.io/2017/09/22/configure-feign/
5.项目应用
5.1 服务提供方
5.1.1引依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
5.1.2 配置文件
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: basic
5.1.3 启动项加注解
@EnableEurekaClient
@SpringBootApplication
@EnableDiscoveryClient
public class GameWebApplication {
public static void main(String[] args){
SpringApplication.run(GameWebApplication.class,args);
}
}
5.1.4 对外暴漏的服务接口添加注解
package com.dmsdbj.integral.game.api.facade;
@FeignClient(value = "INTEGRAL-GAME-PROVIDER", path = "/game-web")
public interface LotteryClientService {
@PostMapping(value = "/api/lottery/addLottery")
IntegralResult<LotteryModel> addLottery(@RequestBody LotteryModel model);
}
这样再调用eureka注册的其它服务,在代码中就像调用自己的service一样了
@FeignClient注解的一些属性:
属性名 | 默认值 | 作用 | 备注 |
value | 空字符床 | 调用服务名称,和name属性相同 | |
path | 空字符床 | 自动给所有方法的requestMapping前加上前缀,类似与controller类上的requestMapping | |
serviceId | 空字符床 | 服务id,作用和name属性相同 | |
name | 空字符床 | 调用服务名称,和value属性相同 | |
url | 空字符床 | 全路径地址或hostname,http或https可选 | |
decode404 | false | 配置响应状态码为404时是否应该抛出FeignExceptions | |
configuration | {} | 自定义当前feign client的一些配置 | |
fallback | void.class | 熔断机制,调用失败时,走的一些回退方法,可以用来抛出异常或给出默认返回数据 | 底层依赖hystrix,启动类要加上@EnableHystrix |
primary | true |
5.2 服务消费方
5.2.1 引依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
5.2.2 配置文件
eureka:
instance:
prefer-ip-address: true
client:
service-url:
defaultZone: http://192.168.22.126:7001/eureka
5.2.3 启动项加注解
@EnableEurekaClient
// 服务发现
@EnableDiscoveryClient
// 对外暴漏接口所在的包路径
@EnableFeignClients(basePackages = " com.dmsdbj.integral.game.api.facade")
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class InternApplication {
public static void main(String[] args) {
SpringApplication.run(InternApplication.class, args);
}
}
5.2.4 消费者引用外部服务
//这里直接注入Feign client
@Autowired
private LotteryClientService lotteryClientService;
@PostMapping("/toCart/{productId}")
public ResponseEntity addCart(@RequestBody LotteryModel model){
// 调用注入服务的方法即可
lotteryClientService.addLottery(model);
}
Feign底层默认是使用jdk中的HttpURLConnection发送HTTP请求,feign底层是使用了ribbon作为负载均衡的客户端,而ribbon的负载均衡也是依赖于eureka 获得各个服务的地址
6.遇到的问题
在bebug模式下调试,出现连接超时,在配置文件中做如下配置即可:
ribbon:
ConnectTimeout: 60000 # 连接超时时间
ReadTimeout: 60000 # 超时时间
## 上面就可以解决此问题,下面配置作为扩展
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # Ribbon使用的负载均衡策略
MaxAutoRetries=1 #同一台实例最大重试次数,不包括首次调用
MaxAutoRetriesNextServer=1 #重试负载均衡其他的实例最大重试次数,不包括首次调用
OkToRetryOnAllOperations=false #是否所有操作都重试
ServerListRefreshInterval=20000 #调整刷新server list的时间间隔
api.mplus.distspace.com.ribbon.listOfServers=localhost:8080,localhost:8081 #服务器列表,可以通过静态的配置确定负载的服务器,也可以动态指定服务器列表,如果动态指定服务器列表,则会有后台线程来刷新该列表
默认的ReadTimeout时间为5s,ConnectTimeout时间为2s。用Fegin进行服务间调用,底层用的还是Ribbon
参考文章:
https://blog.csdn.net/u010862794/article/details/73649616