Introduction to Spring Cloud Feign instances and feign instances

Source: Internet
Author: User

Introduction to Spring Cloud Feign instances and feign instances

The previous blog built a Eureka + Ribbon + Hystrix framework. Although it can basically meet the call requirements between services, the code looks ugly. Every time the client writes a restTemplate, to make the call more beautiful and more readable, we are now learning to use Feign.

Feign contains Ribbon and Hystrix. In practice, it is realized slowly. The so-called jar package containing Feign does not contain the physical package of Ribbon and Hystrix, instead, the Feign function includes the logic of the other two. In short, Feign can do Ribbon and Hystrix, but the corresponding jar package must be used for Ribbon and Hystrix annotations.

Case 1:

Eureka Registration Center: https://github.com/yejingtao/forblog/tree/master/demo-eureka-register

Service provider: https://github.com/yejingtao/forblog/tree/master/demo-feign-freeservice

Service Caller: https://github.com/yejingtao/forblog/tree/master/demo-feign-freeconsumer

The service provider is a simple EurekaClient + web application. The following methods are provided:

@RestController @RequestMapping("/feign-service") public class HelloServiceContorller {   private Logger logger = LoggerFactory.getLogger(this.getClass());      private void sleep(String methodName) {     int sleepMinTime = new Random().nextInt(3000);     logger.info("helloService "+methodName+" sleepMinTime: "+sleepMinTime);     try {       Thread.sleep(sleepMinTime);     } catch (InterruptedException e) {       e.printStackTrace();     }   }      @RequestMapping(value="/serviceGet",method=RequestMethod.GET)   public String helloService(@RequestParam String name) {     sleep("get");     return "HelloServiceImpl name :"+name;   }      @RequestMapping(value="/serviceHead", method=RequestMethod.HEAD)   public String helloService(@RequestHeader String name,       @RequestHeader String password) {     sleep("header");     return "helloServiceHead name :"+name +" password:"+password;   }      @RequestMapping(value="/servicePost", method=RequestMethod.POST)   public String helloService(@RequestBody UserDemo userDemo) {     sleep("post");     return userDemo.toString();   } } 

Note that the following annotations cannot be omitted.

@ RequestParam: Annotation which indicates that amethod parameter shocould be bound to a web request parameter

@ RequestBody: Annotation indicating a methodparameter shocould be bound to the body of the web request.

@ RequestHeader: Annotation which indicates that amethod parameter shocould be bound to a web request header.

If the preceding annotation is missing, no error is reported after the service runs, but the input parameter cannot be obtained.

Service caller project:

<dependency>       <groupId>org.springframework.cloud</groupId>       <artifactId>spring-cloud-starter-feign</artifactId>     </dependency> 

Here, we only rely on Feign, not Ribbon and Hystrix.

Application. yml:

Server: port: 9051 spring: application: name: demo-feign-freeconsumer eureka: client: serviceUrl: defaultZone: http: // peer1: 1111/eureka/, http: // peer2: 1112/eureka/feign: hystrix: enabled: true # Ribbon timeout setting # ribbon: # ConnectTimeout: 500 # ReadTimeout: 3000

Hystrix is a configuration pitfall for a long time. The Spring Cloud I use is Dalston SR1, Which is newer than other materials on the Internet, because Feign's support for Hystrix is disabled by default in the new version, therefore, manually enable feign through configuration. hystrix. enabled = true, so that service downgrade and other functions will be effective.

Application Startup Program

@SpringBootApplication @EnableEurekaClient @EnableFeignClients public class DemoFeignApplication {      public static void main(String[] args) {     SpringApplication.run(DemoFeignApplication.class, args);   } }

Note that there is still a pitfall. Here I use @ SpringBootApplication + @ EnableEurekaClient instead of @ SpringCloudApplication, because the latter includes @ EnableCircuitBreaker, @ EnableCircuitBreaker is included in the Hystrix package, and Hystrix is not introduced in my pom. Therefore, Spring Cloud still has some shortcomings in this regard. If you use @ SpringCloudApplication for compilation, no error will be reported, but it cannot be started. Of course, the main character here is the annotation @ EnableFeignClients.

Core client code

@FeignClient(name="demo-feign-freeservice",fallback=DemoFeignFallback.class) public interface DemoFeignService{       @RequestMapping(value="/feign-service/serviceGet",method=RequestMethod.GET)   String helloService(@RequestParam("name") String name);      @RequestMapping(value="/feign-service/serviceHead", method=RequestMethod.HEAD)   String helloService(@RequestHeader("name") String name,       @RequestHeader("password") String password);      @RequestMapping(value="/feign-service/servicePost", method=RequestMethod.POST)   String helloService(@RequestBody UserDemo userDemo);  } 

@ FeignClient annotation defines that this interface is a Feign client. name specifies the service name registered to Eureka, and fallback is the interface implementation class after the service is downgraded.

@ RequestMapping specifies the relative url and http Request Method of the request, which are one-to-one correspondence with the server. @ RequestParam,

@ RequestBody and @ RequestHeader annotations have more value attributes than the server end. They must be explicitly notified about how the Feign client parameters correspond.

Downgrade service code:

@Component public class DemoFeignFallback implements DemoFeignService{   @Override   public String helloService(String name) {     return "get error";   }    @Override   public String helloService(String name,String password) {     return "head error";   }      @Override   public String helloService(UserDemo userDemo) {     return "post error";   } } 

I found that I intentionally removed the @ RequestParam, @ RequestBody, and @ RequestHeader annotations from the input parameters, the essence of these annotations is that Feign uses http transmission parameters when calling microservices. However, service downgrade does not provide http requests, so this can be omitted.

Controller code:

@RestController public class DemoFeignController {      @Autowired   private DemoFeignService demoFeignService;      @RequestMapping(value="/test", method=RequestMethod.GET)   public String demoServiceTest() {     StringBuffer sb = new StringBuffer();     sb.append(demoFeignService.helloService("yuanyuan"));     sb.append("\n");     sb.append(demoFeignService.helloService("yjt","xixihaha"));     sb.append("\n");     sb.append(demoFeignService.helloService(new UserDemo("yejingtao","123456")));     return sb.toString();        } } 

Let's look at the effect:

Our service has not timed out. All three methods are normal, but the head request does not get the returned value. This is determined by the characteristics of the head http request. The head does not return the body of the response, it is generally used for Connectivity testing.

Let's look at another group:

If you are not lucky, the head and post request methods have been processed for more than 2000 ms. The service is downgraded and the implementation is replaced by the fallback processing class.

In Case 1, we always feel that the service provider and the service caller have repeated code. Can we optimize it? See Case 2.

Case 2:

Eureka Registration Center: https://github.com/yejingtao/forblog/tree/master/demo-eureka-register

Interface API: https://github.com/yejingtao/forblog/tree/master/demo-feign-serviceapi

Service provider: https://github.com/yejingtao/forblog/tree/master/demo-feign-serviceimpl

Service Caller: https://github.com/yejingtao/forblog/tree/master/demo-feign-apiconsumer

Case 2: The biggest change is to write the service capability to an API project separately. Both the caller and the provider pom depend on this API.

API:

public interface HelloService {      @RequestMapping(value="/feign-service/serviceGet",method=RequestMethod.GET)   String helloService(@RequestParam("name") String name);      @RequestMapping(value="/feign-service/serviceHead", method=RequestMethod.HEAD)   String helloService(@RequestHeader("name") String name,       @RequestHeader("password") String password);      @RequestMapping(value="/feign-service/servicePost", method=RequestMethod.POST)   String helloService(@RequestBody UserDemo userDemo);    } 

Service provider:

@RestController public class HelloServiceContorller implements HelloService{      private Logger logger = LoggerFactory.getLogger(this.getClass());      private void sleep(String methodName) {     int sleepMinTime = new Random().nextInt(3000);     logger.info("helloService "+methodName+" sleepMinTime: "+sleepMinTime);     try {       Thread.sleep(sleepMinTime);     } catch (InterruptedException e) {       e.printStackTrace();     }   }      @Override   public String helloService(@RequestParam("name") String name) {     sleep("get");     return "HelloServiceImpl name :"+name;   }      @Override   public String helloService(@RequestHeader("name") String name,       @RequestHeader("password") String password) {     sleep("header");     return "helloServiceHead name :"+name +" password:"+password;   }      @Override   public String helloService(@RequestBody UserDemo userDemo) {     sleep("post");     return userDemo.toString();   }       } 

Service Caller:

@FeignClient(name="demo-feign-serviceimpl", fallback=FeignServiceFallback.class) public interface FeignService extends HelloService{  } 

Other code remains unchanged, and the effect is the same.

The two styles have their own advantages and disadvantages: freestyle is more free, and the new method on the server does not affect the client code. The disadvantage is that changes to the service capability are caused by exceptions when the service capability is not synchronized; the service capability of the server side is synchronized in the API format, but the code on both sides of the interface needs to be modified, so you need to consider it clearly when building the interface.

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.