In the Spring Cloud Netflix stack, each microservice exposes its own services in the form of an HTTP interface, so an HTTP client must be used when calling a remote service. We can use JDK native URLConnection, Apache's Http Client, Netty's asynchronous HTTP Client, and Spring's RestTemplate. However, the most convenient and elegant thing to use is Feign.
Introduction to Feign
Feign is a declarative, templated HTTP client. Using Feign in Spring Cloud, we can achieve the same encoding experience as calling local methods when requesting remote services using HTTP. The developer cannot completely realize that this is a remote method, nor can it be seen that this is an HTTP request. for example:
@Autowiredprivate AdvertGropRemoteService service; // Remote service public AdvertGroupVO foo(Integer groupId) { return service.findByGroupId(groupId); // Call remote service via HTTP} Developers can complete the process of sending HTTP requests, decoding HTTP returns and encapsulating them into objects through service.findByGroupId() .
Definition of Feign
In order for Feign to know which address to send a request to when calling a method and which parameters to take for the request, we need to define an interface:
@FeignClient(name = "ea") // [A]public interface AdvertGroupRemoteService { @RequestMapping(value = "/group/{groupId}", method = RequestMethod.GET) // [B] AdvertGroupVO findByGroupId(@PathVariable("groupId") Integer adGroupId) // [C] @RequestMapping(value = "/group/{groupId}", method = RequestMethod.PUT) void update(@PathVariable("groupId") Integer groupId, @RequestParam("groupName") String groupName)A: @FeignClient is used to notify Feign components to proxy the interface (no need to write an interface implementation), and the user can directly inject it through @Autowired.
B: @RequestMapping means that when calling this method, you need to send a GET request to /group/{groupId} .
C: @PathVariable has the same meaning as the corresponding annotation in SpringMVC.
When the Spring Cloud application is started, Feign will scan the interface marked with the @FeignClient annotation, generate a proxy, and register it into the Spring container. When generating a proxy, Feign will create a RequetTemplate object for each interface method. This object encapsulates all the information required for HTTP requests. The request parameter name, request method and other information are determined in this process. The templateization of Feign is reflected here.
In this example, we use Feign in combination with Eureka and Ribbon ,@FeignClient(name = "ea") means to notify Feign to query Eureka for a service named ea when calling this interface method, so as to get the service URL.
Feign's Encoder, Decoder and ErrorDecoder
Feign's process of serializing the method parameter object in the method signature into request parameters and putting it into an HTTP request is completed by the encoder (Encoder). Similarly, deserializing HTTP response data into java objects is done by a decoder (Decoder).
By default, Feign will convert parameters marked with @RequestParam annotation into strings and add them to the URL, and convert parameters without annotations into json through Jackson to put them into the request body. Note that if the method in @RequetMapping specifies the request method as POST, then all unnoted parameters will be ignored, for example:
@RequestMapping(value = "/group/{groupId}", method = RequestMethod.GET)void update(@PathVariable("groupId") Integer groupId, @RequestParam("groupName") String groupName, DataObject obj);At this time, because the GET request has no request body, the obj parameter will be ignored.
In Spring Cloud environment, Feign's Encoder* will only be used to encode parameters that have not been added to the annotation. If you customize the Encoder, your Encoder will only be called when encoding the obj parameter. For Decoder, the default delegates to the MappingJackson2HttpMessageConverter class in SpringMVC for decoding. ErrorDecoder will only be called when the status code is not between 200 and 300. The function of ErrorDecoder is to return an exception based on HTTP response information, which can be caught where Feign interface is called. We are currently using ErrorDecoder to cause the Feign interface to throw a business exception for the caller to handle.
Feign's HTTP Client
By default, Feign uses JDK native URLConnection to send HTTP requests. There is no connection pool, but a long connection will be maintained for each address, that is, the persistence connection of HTTP is used. We can replace Feign's original http client with Apache's HTTP Client, thereby obtaining the control capabilities closely related to performance such as connection pools, timeouts, etc. Spring Cloud supports this replacement since the Brixtion.SR5 version, first declares the Apache HTTP Client and feign-httpclient dependencies in the project:
<!-- Replace Feign native httpclient with Apache HttpClient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> <dependency> <groupId>com.netflix.feign</groupId> <artifactId>feign-httpclient</artifactId> <version>${feign-httpclient}</version> </dependency>Then add in application.properties:
feign.httpclient.enabled=true
Summarize
Through Feign, we can make HTTP remote calls completely transparent to developers and get a coding experience consistent with calling local methods. This is similar to the way remote services are exposed in Alibaba Dubbo. The difference is that Dubbo is based on a private binary protocol, while Feign is essentially an HTTP client. If you are using Spring Cloud Netflix to build microservices, then Feign is undoubtedly the best choice.
The above is the method (recommended) for using Spring Cloud Feign as an HTTP client to call remote HTTP services (recommended). I hope it will be helpful to everyone. If you have any questions, please leave me a message and the editor will reply to everyone in time. Thank you very much for your support to Wulin.com website!