在前面的文章中可以发现当我们通过RestTemplate调用其它服务的API时,所需要的参数须在请求的URL中进行拼接,如果参数少的话或许我们还可以忍受,一旦有多个参数的话,这时拼接请求字符串就会效率低下,并且显得好傻。
那么有没有更好的解决方案呢?答案是确定的有,Netflix已经为我们提供了一个框架:Feign
Feign是什么?
Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单。Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息。
而Feign则会完全代理HTTP请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。Feign整合了Ribbon和Hystrix(关于Hystrix我们后面再讲),可以让我们不再需要显式地使用这两个组件。
总起来说,Feign具有如下特性:
- 可插拔的注解支持,包括Feign注解和JAX-RS注解;
- 支持可插拔的HTTP编码器和解码器;
- 支持Hystrix和它的Fallback;
- 支持Ribbon的负载均衡;
- 支持HTTP请求和响应的压缩。
服务提供者
在microservice-provider模块中,新增getFeignBalancer和getFeignTimeout接口。依然启动8764和8765两个端口。
idea不会启动多端口可以看【服务消费者RestTemplate+Ribbon(Greenwich.SR2)】
/**
* @describe Feign负载均衡测试
* @author: hero良
* @param
* @return:
*/
@GetMapping("/getFeignBalancer")
public String getFeignBalancer(String name){
log.debug("************接受到请求*************");
return "hello " + name+" , this is 8764";
}
/**
* @describe Feign超时测试
* @author: hero良
* @param
* @return:
*/
@GetMapping("/getFeignTimeout")
public String getFeignTimeout(){
log.debug("************接受到请求*************");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello ";
}
服务消费者
新建microservice-feign,添加依赖
<dependencies>
<!--支持web应该用开发,包括spring-mvc、jackson、tomcat、spring-webmvc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
</dependencies>
yml配置
spring:
application:
name: feign-service
server:
port: 8767
eureka:
client:
service-url:
defaultZone: http://eureka1:8761/eureka/
# defaultZone: http://eureka1:8761/eureka/,http://eureka2:8761/eureka/,http://eureka3:8762/eureka/
启动类
//开启Eureka
@EnableEurekaClient
//开启Feign客户端注解
@EnableFeignClients
@SpringBootApplication
public class FeignApplication {
public static void main(String[] args) {
SpringApplication.run(FeignApplication.class, args);
}
}
@FeignClient
FeignClient注解被@Target(ElementType.TYPE)修饰,表示FeignClient注解的作用目标在接口上
声明接口之后,在代码中通过@Autowired注入之后即可使用。@FeignClient标签的常用属性如下:
- name:指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现
- url: url一般用于调试,可以手动指定@FeignClient调用的地址
- decode404:当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException
- configuration: Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract
- fallback: 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口
- fallbackFactory: 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码
- path: 定义当前FeignClient的统一前缀
@FeignClient(value = "provider-service")
public interface FeignClientService {
@GetMapping("/appController/getFeignBalancer")
String getFeignBalancer(@RequestParam(value = "name") String name);
@GetMapping("/appController/getFeignTimeout")
String getFeignTimeout();
controller
@Autowired
private FeignClientService feignClientService;
/**
* @description feign的负载均衡
* @author hero良
* @param name
* @return java.lang.String
* @exception
* @version 1.0
*/
@GetMapping("/getFeignBalancer")
public String getFeignBalancer(String name){
return feignClientService.getFeignBalancer(name);
}
/**
* @description feign的超时与重试
* @author hero良
* @return java.lang.String
* @exception
* @version 1.0
*/
@GetMapping("/getFeignTimeout")
public String getFeignTimeout(){
return feignClientService.getFeignTimeout();
}
yml配置负载策略和超时重试
因为feign也是采用了Ribbon的负载均衡和重试,所以和 【 服务消费者RestTemplate+Ribbon(Greenwich.SR2) 】的配置是相同的,只是把连接超时和相应时间放在了配置文件中。
#负载均衡策略配置 ribbon(默认轮询)
provider-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #配置规则 随机
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #配置规则 轮询
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule #配置规则 重试
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule #配置规则 响应时间权重
# NFLoadBalancerRuleClassName: com.netflix.loadbalancer.BestAvailableRule #配置规则 最空闲连接策略
#请求连接超时时间 单位ms
ConnectTimeout: 500
#请求处理的超时时间 单位ms
ReadTimeout: 2000
# 同一实例最大重试次数,不包括首次调用
MaxAutoRetries: 0
# 重试其他实例的最大重试次数,不包括首次所选的server
MaxAutoRetriesNextServer: 2
# 是否所有操作都进行重试
#当OkToRetryOnAllOperations设置为false时,只会对get请求进行重试。
#如果设置为true,便会对所有的请求进行重试,如果是put或post等写操作,
#如果服务器接口没做幂等性,会产生不好的结果,所以OkToRetryOnAllOperations慎用。
OkToRetryOnAllOperations: false
具体测试方式和【 服务消费者RestTemplate+Ribbon(Greenwich.SR2) 】相同,这里也不再累述。