Feign配合Ribbon和Eureka来提供负载均衡的HTTP客户端(四)

更多内容参见个人技术博客,无广告欢迎关注

1.1         Feigh

1.1.1      概念

Feign is a declarative web service client. It makes writing web service clients easier. To use Feign create an interface and annotate it. It has pluggable annotation support including Feign annotations and JAX-RS annotations. Feign also supports pluggable encoders and decoders. Spring Cloud adds support for Spring MVC annotations and for using the same HttpMessageConverters used by default in Spring Web. Spring Cloud integrates Ribbon and Eureka to provide a load balanced http client when using Feign.

Feigh是一个声明式web服务客户端。它能让开发web服务变得容易。使用Feign需要创建一个接口并注解它。它拥有包括Feign注解和JAX-RS注解的可插拔支持。它还支持可插拔的编码器和解码器。Spring Cloud拥有Spring MVC支持,并使用Spring Web中默认同样的HttpMessageConverters。在使用Feign时,Spring Cloud集成了RibbonEureka来提供负载均衡的HTTP客户端。

总结:Feign简化HttpClient开发,封装了JAX-RSspringmvc的注解,学习成本很低。

1.1.2      Feign的坑

不能直接支持接收对象参数,只能一个一个属性接收。如果必须要接收对象参数,可以变相通过@RequestBody,通过json的表单提交来实现。

对于日期类型支持和json转换间冲突多,还滞后8小时。转为字符串类型,在提供者时,再强制转换为日期,更加方便些。

1.2         消费者实现Feign

1.2.1      创建Maven工程

1.2.2      pom.xml

<?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>
<parent>
<groupId>com.wood</groupId>
<artifactId>spring-cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wood</groupId>
<artifactId>feign-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>feign-client</name>
<description>Demo project for Spring Boot</description>

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- Feign依赖,声明式开发 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!-- Hystrix,Feign是基于Hystrix的,Hystrix下一章节会讲到 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
</dependencies>
</project>

1.2.3      application.properties

server.port=8093
spring.application.name=feign-client
eureka.client.serviceUrl.defaultZone=http://localhost:6001/eureka
# 定义根目录下日志级别
logging.level.root=INFO

1.2.4      EurekaServiceFeign.java

以接口对外暴露,从而封装底层操作。

package com.wood.feignclient.remote;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
* 这个接口相当于把原来的服务提供者项目当成一个Service类
**/
@FeignClient(value="provider-user")
public interface EurekaServiceFeign {
/**
* Feign中没有原生的@GetMapping/@PostMapping/@DeleteMapping/@PutMapping
* 要指定需要用method进行
* */
@RequestMapping(value="/hello/{name}",method=RequestMethod.GET)
String hello(@PathVariable("name") String name);

}

1.2.5      HelloController.java

package com.wood.feignclient.controller;

import com.wood.feignclient.remote.EurekaServiceFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

@Autowired
private EurekaServiceFeign eurekaServiceFeign
;

@GetMapping("/hello/{name}")
@ResponseBody
public String hello(@PathVariable String name){
return eurekaServiceFeign.hello(name);
}
}

1.2.6      FeignClientApplication.java

package com.wood.feignclient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients //开启Feign
public class FeignClientApplication {

public static void main(String[] args) {
SpringApplication.run(FeignClientApplication.class, args);
}

}

1.2.7      常见的坑

只支持旧的@RequestMapping不支持新的@GetMapping()

method=RequestMethod.GET 只支持POST方法,GET方法也会自动转到POST方法

@PathVariable("name") String name 必须写名称“name”,springmvc可以不写

启动超过1s会报超时,再刷新就可以正常访问,原因在于hystrix断路器的影响,稍差的机器就会发生。

 

1.2.8      测试

执行顺序:

先启动服务端     6001    eureka-server        EurekaServerApplicaiton

在启动提供者1   8081    provider-a        ProviderAAppcation

最后启动消费者  8093    feign-client  FeignClientApplication

访问Eureka控制台:      http://localhost:6001/

 

访问请求:               http://localhost:8093/hello/wood

出现服务提供者A:wood ,页面出现,设置断点,发现提供者也进入了,Feign消费者也进入了。

1.3         拓展:Feign实现降级

1.3.1      UserFeignFallback

直接实现消费者的Feign接口,给每个方法设置异常时的处理

package com.wood.feignclient.remote;

import org.springframework.stereotype.Component;

/**
* Feign实现降级
* 直接实现消费者的UserFeign接口,给每个方法设置异常时的处理
*/
@Component // 微服务访问异常则启用降级
public class UserFeignFallback implements EurekaServiceFeign {
@Override
public String hello(String name) {
return "微服务访问异常则启用降级 hello";
}
}

1.3.2      修改接口EurekaServiceFeign

@FeignClient(value="provider-user", fallback = UserFeignFallback.class)

1.3.3      application.properties

server.port=8093
spring.application.name=feign-client
eureka.client.serviceUrl.defaultZone=http://localhost:6001/eureka
# 定义根目录下日志级别
logging.level.root=INFO

#feign集成hystrix必须开启

feign:

  hystrix:

    enabled: true

1.4         Feign小结

1.4.1      调用过程

 

首先,提供者provider-user和消费者custorm-feign都注册到Eureka中。用户请求feign中的controllerfeign中的controller调用feign定义的接口方法。接口的方法根据注解去找到eureka注册中心中的provider-user地址,然后请求远程provider-user所在服务器的地址,然后调用远程的provider-user提供者的具体服务。提供者响应返回jsonjsonfeign封装传输给“接口”的返回值,“接口”在返回给feigncontroller,最终响应给用户。

1.4.2      自动创建实现类

Feign是典型的基于接口,基于动态代理技术自动生成代理对象。

设置断点,可以清晰的看到这个过程。先访问feign-clientcontroller;观察EurekaServiceFeign接口,如下图其实一个jdk动态代理类。

 

动态代理类根据配置的注解信息去Eureka中找到对应调用的提供者的链接信息,进行访问,断点就进入到provider-usercontroller中具体执行,执行完成层层返回。

附上demo spring-clioud-feign.zip 

原文地址:https://www.cnblogs.com/wood-life/p/10332919.html