Feign
我们前面的文章都是使用RestTemplate对依赖服务进行调用,而Feign采用了声明式API接口的风格,将服务调用过程变得更为简单。并且Feign还整合了Ribbon和Hystrix来简化我们的开发。
入门案例
我们的服务注册中心和服务提供者还使用前面的例子,我们先将其启动。
服务注册中心:8001
服务提供者开启两个实例:9998和9999.
(1)先创建一个服务消费者的项目feign-consumer,添加依赖。
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
</dependencies>
(2)创建启动类,添加注解
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class FeignApplication {
public static void main(String[] args) {
SpringApplication.run(FeignApplication.class);
}
}
(3)编写配置文件,指定注册中心
spring:
application:
name: feign-consumer
server:
port: 9008
eureka:
client:
service-url:
defaultZone: http://server1:8001/eureka/
(4)新建一个接口,加@FeignClient注解来声明一个FeignClient,value为远程服务的服务名。接口的请求路径使用SpringMVC的方式和被调用的服务接口保持一致即可实现绑定,指定参数时,@PathVariable、@RequestParam等注解一定要加value指明,否则报错。
@FeignClient("eureka-client01")
public interface HelloService {
@RequestMapping("/hello/{msg}")
public String hello(@PathVariable(value = "msg") String msg);
}
(5)创建Controller,进行远程调用
@RestController
public class FeignController {
@Autowired
private HelloService helloService;
@RequestMapping("/feign/{msg}")
public String test(@PathVariable String msg){
return helloService.hello(msg);
}
}
(6)访问http://localhost:9008/feign/testFeign
发现其已经具有了负载均衡的功能,内部其实依然使用的是Ribbon来实现。


我们其实不难发现,我们在接口中绑定要调用的服务接口时,其实只需要把服务提供者的Controller中被调用方法给复制过来删掉方法体变成抽象方法即可。那么当方法特别多的时候我们能不能来进行复用?现在一个比较通用的解决方案就是定义好一个接口,然后服务提供者实现这个接口并实现这些接口的方法,而服务消费者的FeignClient接口只需要继承这些接口,并添加@FeignClient注解即可。
Feign执行流程
(1)在FeignClientsRegistrar类中,首先会检查是否开启@EnableFeignClients注解,如果有该注解,开启包扫描,扫描被@FeignClient注解的接口,获取接口的信息封装到对象中注入Ioc容器中。
(2)当调用FeignClient接口里的方法时,通过JDK的代理生成RestTemplate对象,然后通过RestTemplate对象生成Request请求对象,然后用Http Client进行请求获取Response响应,这个Http工具可以是HttpURLConnection(默认)、HttpClient、OkHttp等,可以自己进行配置。
(3)client会被注入到LoadBalancerFeignClient类,这个类会结合Ribbon做到负载均衡。
Ribbon和Hystrix配置
由于Feign整合了Ribbon和Hystrix,所以我们可以不需要引入Ribbom和Hystrix的依赖,并且配置和以前几乎是一样的。
Ribbon配置
ribbon:
//这个为建立连接后从服务器读取可用资源的超时时间
ReadTimeout: 5000
//这个为建立连接的超时时间
ConnectionTimeout: 2000
//重试次数
MaxAutoRetries: 1
//对所有操作都执行重试操作
OkToRetryOnAllOperations: true
如果想对具体的实例进行细度的设置,只需要加上服务名称就可以。
例如:
hello-service:
ribbon:
ReadTimeout: 5000
ConnectionTimeout: 2000
Hystrix配置
hystrix:
command:
defualt:
execution:
timeout:
//关闭熔断功能
enable: false
isolation:
thread:
//设置Hystrix命令超时时间
timeoutInMilliseconds: 5000
//关闭Hystrix功能
feign:
hystrix:
enabled: false
配置Hystrix服务降级
(1)在配置文件中开启Hystrix功能
feign:
hystrix:
enabled: true
(2)我们需要实现被@FeignClient修饰的接口,并且以Spring Bean的形式注入Ioc容器中。实现类中实现接口中的每个方法的方法体就是具体的降级逻辑。
@Component
public class HelloServiceFallback implements HelloService {
@Override
public String hello(String msg) {
return "error";
}
}
(3)在服务绑定接口,通过fallback指定服务降级实现类
@FeignClient(name = "eureka-client01",fallback = HelloServiceFallback.class)
public interface HelloService {
@RequestMapping("/hello/{msg}")
public String hello(@PathVariable(value = "msg") String msg);
}
(4)我们开启服务注册中心和消费者,但是关闭服务提供者,进行访问

Feign还支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。
feign:
compression:
request:
enabled: true
response:
enabled: true
本文介绍如何使用Feign简化微服务间的调用,包括配置、执行流程及Ribbon和Hystrix的整合。
167万+

被折叠的 条评论
为什么被折叠?



