Feign 简介
pring Cloud的Feign支持的一个中心概念就是命名客户端.Feign客户端使用@FeignClient注册组合成组件,按需调用远程服务器.
Spring Cloud使用FeignClientsConfiguration创建一个新的集合作为每个命名客户端的ApplicationContext(应用上下文), 包含feign.Decoder,feign.Encoder和feign.Contract。Feign 通过注解注入一个模板化请求进行工作。只需在发送之前关闭它,参数就可以被直接的运用到模板中。然而这也限制了 Feign,只支持文本形式的API,它在响应请求等方面极大的简化了系统
feign模板化体现
Spring Cloud应用在启动时,Feign会扫描标有@FeignClient注解的接口,生成代理,并注册到Spring容器中。生成代理时Feign会为每个接口方法创建一个RequetTemplate对象,该对象封装了HTTP请求需要的全部信息,请求参数名、请求方法等信息都是在这个过程中确定的,Feign的模板化就体现在这里。
功能实现
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
客户端接口
@FeignClient(name = "cdkClient",contextId = "cdk-client",path = "/act/test",
url ="${setting.bigScreen.host}",
fallback = CilentErr.class)
public interface CilentApi {
@PostMapping("/feignTest")
public void cilentTest(@RequestBody String code);
name 的值为:调用客户端的名称。
url :单独的一个http接口,接口提供方没有注册到注册中心,通过http请求路径进行远程调用
path:调用的接口路径
fallback:异常处理,当服务调用失败时执行
Feign将方法签名中方法参数对象序列化为请求参数放到HTTP请求中的过程,是由编码器(Encoder)完成的。同理,将HTTP响应数据反序列化为java对象是由解码器(Decoder)完成的。默认情况下,Feign会将标有@RequestParam注解的参数转换成字符串添加到URL中,将没有注解的参数通过Jackson转换成json放到请求体中。注意,如果在@RequetMapping中的method将请求方式指定为POST,那么所有未标注解的参数将会被忽略
服务端接口
@RestController
@RequestMapping("/act/test")
@Slf4j
public class CdServcieController {
@PostMapping("/feignTest")
public void cilentTest(@RequestBody String code){
log.info("服务端口接收到请求"+code);
};
}
feign使用Hystrix
引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
在客户端fallback中注定类
@Component
public class CilentErr implements CilentApi {
@Override
public void Test1(String code) {
System.out.println("服务失败时调用");
}
}
然后在启动类添加上@EnableFeignClients,
@EnableCircuitBreaker注解
最后配置properties文件
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
#是否在控制台打印JPA执行过程生成的SQL
spring.jpa.show-sql=true
#表示JPA对应的数据库是MySQL
spring.jpa.database=mysql
#表示在项目启动时根据实体类更新数据库中的表
spring.jpa.hibernate.ddl-auto=update
#表示使用的数据库方言是MySQL57Dialect
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
server.port=8071
setting.bigScreen.host=http://localhost:8091
#开启hystrix
feign.hystrix.enabled=true
在Spring Cloud中,Feign和Ribbon在整合了Hystrix后,可能会出现首次调用失败的问题,要如何解决该问题呢?
Hystrix默认的超时时间是1秒,如果超过这个时间尚未响应,将会进入fallback代码。
而首次请求往往会比较慢(因为Spring的懒加载机制,要实例化一些类),这个响应时间可能就大于1秒了。
解决方案 :
方法一
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
该配置是让Hystrix的超时时间改为5秒
方法二
hystrix.command.default.execution.timeout.enabled: false
该配置,用于禁用Hystrix的超时时间
feign的扩展配置
#Hystrix支持,如果为true,hystrix库必须在classpath中
feign.hystrix.enabled=false
#请求和响应GZIP压缩支持
feign.compression.request.enabled=true
feign.compression.response.enabled=true
#支持压缩的mime types
feign.compression.request.enabled=true
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048
# 日志支持
logging.level.project.user.UserClient: DEBUG
feign原理简述
1 Spring Cloud应用在启动时,程序会进行包扫描,扫描所有包下所有标有@FeignClient注解的接口,生成代理对象,并将这些接口注入到spring的IOC容器中
2 当定义的Feign中的接口被调用时,通过JDK的动态代理来生成RequestTemplate代理对象。
该对象封装了HTTP请求需要的全部信息,请求参数名、请求方法等信息都是在这个过程中确定的,Feign的模板化就体现在这里
3 RequestTemplate再生成Request。
4 然后将Request交给client处理,这个client默认是JDK的HttpUrlConnection(也可以是HttpClient或Okhttp,需要配置)
5 最后Client被封装到LoadBalanceClient类,这个类结合类Ribbon做到了负载均衡