●Feign是一 个声明式的REST客户端,它用了基于接口的注解方式,很方便实现客户端配置。
●Feign最初由Netlix公司提供,但不支持SpringMVC注解,后由SpringCloud对其封装,支持了SpringMVC注解,让使用者更易于接受。
demo 目录结构
consumer的pom添加依赖
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
/**
* 1.定义接口!
* 2.接口上添加注解@FeignClient,设置value属性为服务提供者的应用名称
* 3.编写调用接口,接口的声明规则和提供方接口保持一致。
* 4.注入该接口对象,调用接口方法完成远程调用
* backend-show-provider 是provider的名称
*/
@FeignClient(value = "backend-show-provider")
public interface ConsumerApp {
/**
* provider Controller名称;sayhello 请求的方法名
*
* @param message
* @return
*/
@GetMapping("/provider/sayhello2")
String providerSayHello2(@RequestParam("message")String message);
}
consumer的application.java中添加
@SpringBootApplication
@EnableFeignClients //开启Feign的功能
public class BackendShowConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(BackendShowConsumerApplication.class,args);
}
}
consumer服务中
@Resource
private ConsumerApp consumerApp;
@GetMapping(value = "/sayhello2")
public String sayhello2(String message){
String result = null;
try {
result = consumerApp.providerSayHello2(message);
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
provider服务代码
@GetMapping("/sayhello2")
public String providerSayHello2(String message,String username) {
System.out.println("username:"+username);
// int a=1/0;//错误
try {
Thread.sleep(2000);//超时设置
} catch (InterruptedException e) {
e.printStackTrace();
}
log.error("provder sayhello port:{}, message:{}", port, message);
return "Provider sayhello port:" + port + " , message:" + message;
}
编写Feign调用接口时候,注意方法的参数必须 @RequestParam (例如:@RequestParam("message")String message) 否则 【status 405 reading】
不推荐使用这种,在实际发布情况中,可能存在端口被暂用。需要改端口的情况
/**
* name 名称,可以自己随意取;url 对应的服务请求地址
*/
@FeignClient(name="providerTest",url = "http://localhost:7010")
public interface ConsumerApp {
/**
* provider Controller名称;sayhello 请求的方法名
*
* @param message
* @return
*/
@GetMapping("/provider/sayhello2")
String providerSayHello2(@RequestParam("message")String message);
}
ribbon:
ConnectTimeout: 2000 # Ribbon的连接超时时间
ReadTimeout: 3000 # Ribbon的数据读取超时时间
OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
MaxAutoRetries: 1 # 对当前实例的重试次数
3Feign日志打印
logging:
level:
com.item.backed: debug #com.item.backed为包名,也可具体指定哪个class
package com.item.backed.consumer.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignLogConfig {
/**
* NONE ,不记录
* BASIC,记录基本的请求行,响应状态码数据
* HEADERS,记录基本的请求行,响应状态码数据,记录响应头信息
* FULL ;记录完成的请求响应数据
* @return
*/
@Bean
public Logger.Level level(){
return Logger.Level.FULL;
}
}
,configuration = FeignLogConfig.class
最后查看日志
Feign支持多种http调用形式(这里网上说不支持@GetMapping和@POSTMapping,但是本次的demo都是用的这两个,却可以运行通。) 如果使用以上两种形式请求,报错【Request method 'POST' not supported】。可以尝试更换
前面demo中两种@FeignClient写法都只用到两个参数(configuration、value 或者 name和url);去请求另外一个服务的Controller 路径都写在请求的方法上面。例如:
@GetMapping("/provider/sayhello2")
String providerSayHello2(@RequestParam("message")String message);
现在,在@FeginClinet中添加一个参数 path就行:
import com.item.backed.consumer.config.FeignLogConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(value = "backend-show-provider",path = "/provider",configuration = FeignLogConfig.class)
public interface ConsumerApp {
/**
* provider Controller名称;sayhello 请求的方法名
*
* @param message
* @return
*/
@GetMapping("/sayhello2")
String providerSayHello2(@RequestParam("message")String message);
}
请求如下
配置类型 | 默认配置 |
feignDecoder | ResponseEntityDecoder |
feignEncoder | SpringEncoder |
feignLogger | SIf4jLogger |
feignContract | SpringMvcContract |
feignBuilder | HystrixFeign.Builder |
feignClient | LoadBalancerFeignClient或者feignClient |
Feign继承
◆微服务的目标是大量复用, Feign会导致重复工作量
◆Feign提供了继承特性帮助我们解决这个问题
接口复用最多只能有一层,切忌多继承
◆Feign可以集成Ribbon实现负载均衡
◆Feign可以集成Hystrix实现命令封装
◆Feign可以集成Hystrix实现业务降级
Feign之HTTP性能优化
◆Feign默认使用的JDK自带的HTTP方式
◆Feign最大的优化点是更换HTTP底层实现
◆目前Apache HTTPClient是一个非常好的选择