官方地址:https://cloud.spring.io/spring-cloud-static/Edgware.SR3/single/spring-cloud.html#spring-cloud-feignhtml
1、概述
Feign是一個聲明式Web服務客戶端。它使編寫Web服務客戶端變得更容易。使用Feign建立一個接口並對其進行註釋。它具備可插入的註釋支持,包括Feign註釋和JAX-RS註釋。Feign還支持可插拔編碼器和解碼器。 Spring Cloud添加了對Spring MVC註釋的支持,而且使用了Spring Web中默認使用的相同HttpMessageConverters。Spring Cloud將Ribbon和Eureka集成在一塊兒,在使用Feign時提供負載均衡的http客戶端。git
源碼地址:https://github.com/OpenFeign/feignspring
1.一、基礎使用
1》添加pom
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
2》啓動類上添加註解
@SpringBootApplication @EnableFeignClients public class ComsumerMovieFeignApplication { public static void main(String[] args) { SpringApplication.run(ComsumerMovieFeignApplication.class, args); } }
3》添加一個接口併爲接口添加註解,調用用戶服務
@FeignClient("microservice-provider-user") public interface UserFeignClient { // @GetMapping("/sample/{id}") @RequestMapping(method = RequestMethod.GET, value = "/movie/{id}") public User findById(@PathVariable("id") Long id); }
注意點:一、spring註解不能使用getMapping,需使用RequestMapping;二、@PathVariable必須添加參數;三、當服務接受參數是一個對象時候,此時默認會轉化爲post請求,及時接口寫的是get請求【?待解決】json
//請求不會成功,只要參數是複雜對象,即便指定了GET方法,feign依然會以post方法進行發送 @RequestMapping(method = RequestMethod.GET, value = "/get-user") public User getUser(User user);
4》程序調用
@Autowired private UserFeignClient userFeignClient; @GetMapping("/movie/{id}") public User findById(@PathVariable Long id) { return userFeignClient.findById(id); }
執行post相似服務器
參考代碼:https://github.com/bjlhx15/spring-cloud/tree/master/microservice-comsumer-movie-feign網絡
1.二、覆寫Feign的默認配置
1.2.一、概述
Spring Cloud的Feign支持中的一箇中心概念是指定的客戶端。app
每一個feign客戶端都是總體的一部分,這些組件是一塊兒工做以根據須要聯繫遠程服務器,而且該組件具備一個名稱,開發人員可使用@FeignClient批註命名。負載均衡
Spring Cloud使用FeignClientsConfiguration建立一個新的集合,做爲每一個指定客戶端的ApplicationContext。這包含(除其餘外)feign.Decoder,feign.Encoder和feign.Contract。框架
經過使用@FeignClient聲明額外配置(在FeignClientsConfiguration之上),Spring Cloud可以讓您徹底控制客戶端
示例
@FeignClient(name = "stores", configuration = FooConfiguration.class) public interface StoreClient { //.. }
注意事項:FooConfiguration
同RibbonConfiguration一致放包問題,參看:http://www.cnblogs.com/bjlhx/p/8859088.html
注意事項2:之前使用url能夠不用,如今必須使用name
1.2.二、默認配置
Spring Cloud Netflix默認提供如下bean for feign(BeanType beanName:ClassName):
Decoder
feignDecoder:ResponseEntityDecoder
(which wraps aSpringDecoder
) 默認解碼Encoder
feignEncoder:SpringEncoder 默認編碼
Logger
feignLogger:Slf4jLogger 默認日誌
Contract
feignContract:SpringMvcContract 默認契約
Feign.Builder
feignBuilder:HystrixFeign.Builder 默認構建builder
Client
feignClient: if Ribbon is enabled it is aLoadBalancerFeignClient
, otherwise the default feign client is used. 默認client
經過將feign.okhttp.enabled或feign.httpclient.enabled分別設置爲true並將它們放在類路徑中,可使用OkHttpClient和ApacheHttpClient feign客戶端。當使用Apache或OkHttpClient使用OK HTTP時,能夠經過提供ClosableHttpClient的bean來定製HTTP客戶端。
1.2.三、非默認配置
Spring Cloud Netflix默認狀況下不提供如下bean,但仍從應用程序上下文中查找這些類型的bean以建立假客戶端:
Logger.Level
Retryer
ErrorDecoder
Request.Options
Collection<RequestInterceptor>
SetterFactory
1.2.四、開發
編寫一個默認註解
@Configuration public class Configuration1 { @Bean public Contract feignContract() { return new feign.Contract.Default(); } }
由於原默認註解使用spring的如今這裏改用feign契約,故如下調用須要使用feign的註解RequestLine等
編寫客戶端調用
@FeignClient(name = "microservice-provider-user", configuration = Configuration1.class) public interface UserFeignClient { @RequestLine("GET /sample/{id}") public User findById(@Param("id") Long id); }
程序使用便可。
參看代碼:https://github.com/bjlhx15/spring-cloud/tree/master/microservice-comsumer-movie-feign-customizing
1.2.五、若是請求eureka的接口如
@FeignClient(name = "xxxx", url = "http://localhost:8761/", configuration = Configuration2.class) public interface FeignClient2 { @RequestMapping(value = "/eureka/apps/{serviceName}") public String findServiceInfoFromEurekaByServiceName(@PathVariable("serviceName") String serviceName); }
由於eureka設置了權限此時訪問失敗
需增長配置類,Configuration2增長權限校驗
@Configuration public class Configuration2 { @Bean public BasicAuthRequestInterceptor basicAuthRequestInterceptor() { return new BasicAuthRequestInterceptor("user", "a123"); } }
1.2.六、Feign請求/響應壓縮
feign.compression.request.enabled=true feign.compression.response.enabled=true
Feign請求壓縮爲您提供了相似於您爲Web服務器設置的設置:
feign.compression.request.enabled=true feign.compression.request.mime-types=text/xml,application/xml,application/json feign.compression.request.min-request-size=2048
這些屬性使您能夠選擇壓縮媒體類型和最小請求閾值長度。
1.三、feign日誌
爲每一個建立的Feign客戶端建立一個記錄器。默認狀況下,記錄器的名稱是用於建立Feign客戶端的接口的完整類名稱。 Feign日誌記錄僅響應DEBUG級別。
application.yml.
logging.level.project.user.UserClient: DEBUG
注level是具體類路徑。可能不生效,須要配置一下配置
您能夠爲每一個客戶端配置的Logger.Level對象告訴Feign要記錄多少。選擇是:
NONE
, No logging (DEFAULT).BASIC
, 只記錄請求方法和URL以及響應狀態碼和執行時間。HEADERS
, 記錄基本信息以及請求和響應標頭。FULL
, 爲請求和響應記錄標題,正文和元數據。
例如,如下操做將Logger.Level設置爲FULL:
@Configuration public class FooConfiguration { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } }
參看代碼:https://github.com/bjlhx15/spring-cloud/tree/master/microservice-comsumer-movie-feign-customizing
1.四、Feign第一次啓動timeout問題
hystrix默認1秒超時
方法1、可配置超時時間增長:
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
方法2、關閉熔斷超時
hystrix.command.default.execution.timeout.enabled: false
方法3、關閉熔斷機制
feign.hystrix.enabled: false
能夠參看:https://github.com/Netflix/Hystrix/wiki/Configuration
1.五、手動建立Feign客戶端


@Import(FeignClientsConfiguration.class) class FooController { private FooClient fooClient; private FooClient adminClient; @Autowired public FooController(Decoder decoder, Encoder encoder, Client client, Contract contract) { this.fooClient = Feign.builder().client(client) .encoder(encoder) .decoder(decoder) .contract(contract) .requestInterceptor(new BasicAuthRequestInterceptor("user", "user")) .target(FooClient.class, "http://PROD-SVC"); this.adminClient = Feign.builder().client(client) .encoder(encoder) .decoder(decoder) .contract(contract) .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin")) .target(FooClient.class, "http://PROD-SVC"); } }
1.六、feign源碼實現過程
一、首先經過@EnabledFeignClients註解開啓FeignClient的功能。主要是啓動程序時開啓對@FeignClient註解的包掃描
二、根據feign的規則實現接口,並在接口上面加上@FeignClient註解
三、程序啓動後,進行包掃描,掃描全部的@FeignClient的註解的類,並將這些類放入Ioc容器。
四、當接口的方法被調用時,經過JDK的代理來生成具體的RequestTemplate模板對象
五、根據RequestTemplate再生成Http請求的Request對象。
六、Request對象交給Client去處理,其中Client的網絡請求框架能夠是HttpURLConnetion,HTTPClient和OkHttp等
七、最後Client被封裝到LoadBlanceClient類,這個類結合類Ribbon作負載均衡。