Feign受Retrofix、JAXRS-2.0和WebSocket影響,採用了聲明式API接口的風格,將Java Http客戶端綁定到他的內部。Feign的首要目標是將Java Http客戶端調用過程變得簡單。html
源碼地址:https://github.com/OpenFeign/feignjava
本章案例基於上一章,可參考:git
spring boot 2.0.3+spring cloud (Finchley)一、搭建Eureka 以及構建高可用Eureka Server集羣 github
spring boot 2.0.3+spring cloud (Finchley)二、搭建負載均衡Ribbon (Eureka+Ribbon+RestTemplate)web
新建module工程eureka-feign-client。pom文件引入相關依賴,包括主maven工程的pom文件,eureka client起步依賴,feign的起步依賴,web的起步依賴(已在主maven工程pom中配置)spring
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.cralor</groupId> <artifactId>eureka-feign-client</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>eureka-feign-client</name> <description>Demo project for Spring Boot</description> <parent> <groupId>com.cralor</groupId> <artifactId>chap7-feign</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
配置文件作相關配置apache
server: port: 8765 spring: application: name: eureka-feign-client eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/
在程序的啓動類加上註解@EnableFeignClients開啓Feign Client功能瀏覽器
@EnableFeignClients @SpringBootApplication public class EurekaFeignClientApplication { public static void main(String[] args) { SpringApplication.run(EurekaFeignClientApplication.class, args); } }
經過以上步驟,該程序已經具有了Feign的功能,如今來實現一個簡單的feign client。新建一個EurekaClientFeign的接口,在接口上加@FeignClient註解來聲明一個Feign Client。value爲遠程調用其餘服務的服務名,FeignConfig.class爲配置類,在EurekaClientFeign內部有一個sayHiFromClientEureka()的方法,該方法經過Feign來調用eureka-client服務的「/hi」的aipi接口。網絡
@Component @FeignClient(value = "eureka-client",configuration = FeignConfig.class) public interface EurekaClientFeign { @GetMapping(value = "/hi") String sayHiFromClientEureka(@RequestParam(value = "name")String name); }
在FeignConfig類上加上@Configuration註解,代表這是一個配置類,並注入一個BeanName爲feignRetryer的Retryer的Bean。可以使feign在遠程調用失敗後會進行重試。app
@Configuration public class FeignConfig { @Bean public Retryer feignRetryer(){ return new Retryer.Default(100,TimeUnit.SECONDS.toMillis(1),5); } }
service層HiService類注入EurekaClient的Bean
@Service public class HiService { @Autowired EurekaClientFeign eurekaClientFeign; public String sayHi(String name){ return eurekaClientFeign.sayHiFromClientEureka(name); } }
新建HiController類,調用HiService的sayHi()方法,HiService經過EurekaClientFeign遠程調用eureka-client服務的API接口「/hi」。
@RestController public class HiController { @Autowired HiService hiService; @GetMapping("/hi") public String sayHi(@RequestParam(defaultValue = "cralor",required = false)String name){ return hiService.sayHi(name); } }
啓動eureka-server工程,端口號8761,啓動兩個eureka-client工程的實例,端口號876二、8763,啓動eureka-feign-client工程,端口號8765。在瀏覽器屢次訪問http://localhost:8765/hi,瀏覽器會輪流顯示
可見Feign Client遠程調用了eureka-client的服務(存在端口號爲8762和8763的兩個實例)的「/hi」API接口,feign client有負載均衡的能力。
總結:feign源碼實現過程以下
1.首先經過@EnableFeignClients註解開啓FeignClient功能。只有這個註解的存在,程序啓動時纔會開啓對@FeignConfig註解的包的掃描,
2.根據Feig的規則實現接口,並在接口上面加上@FeignClient註解。
3.程序啓動後會進行包掃描,掃描全部@FeignClient註解的類,並將這些信息注入IOC容器中。
4.當接口的方法被調用時,經過JDK的代理來生成具體的RequestTemplate模板對象。
5.根據RequestTemplate再生成Http請求的Request對象。
6.Request對象交給Client去處理,其中Client的網絡請求框架能夠是HttpURLConnection、HttpClient和OkHttp。
7.最後Client被封裝到LoadBalanceClient類,這個類結合類Ribbon作到了負載均衡。
參考:https://windmt.com/2018/04/15/spring-cloud-3-service-producer-and-consumer/#Spring-Cloud-Feign
案例代碼地址:https://github.com/cralor7/springcloud