Feign代替RestTemplate发起远程调用的代码
RestTemplate发起远程调存在下面的问题:
•代码可读性差,编程体验不统一
•参数复杂URL难以维护
Feign是一个声明式的http客户端,官方地址:https://github.com/OpenFeign/feign
其作用就是帮助我们优雅的实现http请求的发送,解决上面提到的问题。
Feign可以把HTTP 的请求进行隐藏,伪装成类似 SpringMVC 的 Controller一样。你不用再自己拼接 url,拼接参数等等操作,一切都交给 Feign 去做。
创建好了用户,订单,商品微服务,这三个微服务是互相隔离的,那么微服务和微服务之间如何互相调用呢,显然三个微服务都可以采用http通信,也就是 restTemplate 进行互相访问,但是这种方式对参数传递和使用都不是很方便,所以弃用此方式,采用 feign 进行服务之间的调用,可以简化调用流程,真正感觉到是在同一个项目中调用另一个类的方法
当我们通过RestTemplate调用其它服务的API时,所需要的参数须在请求的URL中进行拼接,如果参数少的话或许我们还可以忍受,一旦有多个参数的话,这时拼接请求字符串就会效率低下,并且显得好傻。
在开发 Spring Cloud 微服务的时候,我们知道,服务之间都是以 HTTP 接口的形式对外提供服务的,因此消费者在进行调用的时候,底层就是通过 HTTP Client 的这种方式进行访问。Spring 的 RestTemplate 去实现服务间的调用。但是最方便、最优雅的方式是通过 Spring Cloud Feign 进行服务间的调用。使用 Feign 只需要创建一个接口加上对应的注解,比如:@FeignClient 注解。
总结:
Feign 是一种声明式、模板化的 HTTP 客户端。在 Spring Cloud 中使用 Feign,可以做到使用 HTTP 请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问 HTTP 请求。
Feign替代RestTemplate步骤
引入依赖
我们在order-service服务的pom文件中引入feign的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
添加注解
在order-service的启动类添加注解开启Feign的功能
编写Feign的客户端
在order-service中新建一个接口,内容如下
package com.atguigu.order.client;
import com.atguigu.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient("userservice")
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
这个客户端主要是基于SpringMVC的注解来声明远程调用的信息,比如:
服务名称:userservice
请求方式:GET
请求路径:/user/{id}
请求参数:Long id
返回值类型:User
这样,Feign就可以帮助我们发送http请求,无需自己使用RestTemplate来发送了。
注释 orderservice 的配置文件
总结
使用Feign的步骤:
① 引入依赖
② 添加@EnableFeignClients注解
③ 编写FeignClient接口
④ 使用FeignClient中定义的方法代替RestTemplate
熔断器支持
feign整合Hystrix熔断器
Feign默认也有对Hystrix的集成!
开启Hystrix
在 order-service 配置文件 application.yml 中开启 feign 熔断器支持:默认关闭
feign:
hystrix:
enabled: true # 开启Feign的熔断功能
熔断降级类创建
修改order-service,创建一个类com.atguigu.feign.fallback.UserClientFallback,实现刚才编写的UserClient,作为FallBack的处理类,代码如下:
package com.atguigu.feign.fallback;
import com.atguigu.domain.User;
import com.atguigu.feign.UserClient;
import org.springframework.stereotype.Component;
@Component
public class UserClientFallback implements UserClient {
@Override
public User findById(Integer id) {
User user = new User();
user.setUsername("服务熔断");
return user;
}
}
指定Fallback处理类
在@FeignClient注解中,指定FallBack处理类
package com.atguigu.order.client;
import com.atguigu.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//userservice是application的名字
@FeignClient(value = "userservice",fallback = UserClientFallback.class)
public interface UserClient {
/**该方法是要调用的方法
*/
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
请求压缩
SpringCloudFeign支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。
order-service
通过配置开启请求与响应的压缩功能:(简单压缩)
feign:
compression:
request:
enabled: true # 开启请求压缩
response:
enabled: true # 开启响应压缩
也可以对请求的数据类型,以及触发压缩的大小下限进行设置(完整压缩)
# Feign配置
feign:
compression:
request:
enabled: true # 开启请求压缩
mime-types: text/html,application/xml,application/json # 设置压缩的数据类型
min-request-size: 2048 # 设置触发压缩的大小下限
#以上数据类型,压缩大小下限均为默认值
response:
enabled: true # 开启响应压缩
日志配置
配置文件方式
基于配置文件修改feign的日志级别可以针对单个服务:
feign:
client:
config:
userservice: # 针对某个微服务的配置
loggerLevel: FULL # 日志级别
也可以针对所有服务
feign:
client:
config:
default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
loggerLevel: FULL # 日志级别
而日志的级别分为四种:
NONE:不记录任何日志信息,这是默认值。
BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据
ava代码方式
也可以基于Java代码来修改日志级别,先声明一个类,然后声明一个Logger.Level的对象(因为这是Feign对象的日志,用Feign导入该配置类):
package com.atguigu.order.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
public class DefaultFeignConfiguration {
@Bean
public Logger.Level feignLogLevel(){
return Logger.Level.BASIC; // 日志级别为BASIC
}
}
如果要全局生效,将其放到启动类的@EnableFeignClients这个注解中,局部生效,放到@FeignClient注解中:
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class)
@FeignClient(value = "userserver",fallback = DefaultFeignConfiguration .classFeignHystrixFallback.class,configuration = )//告诉我远程的接口,以及进行熔断处理调用
Feign底层发起http请求,依赖于其它的框架。其底层客户端实现包括:
•URLConnection:默认实现,不支持连接池
•Apache HttpClient :支持连接池
•OKHttp:支持连接池
因此提高Feign的性能主要手段就是使用连接池代替默认的URLConnection。
这里我们用Apache的HttpClient来演示。
引入依赖
在order-service的pom文件中引入Apache的HttpClient依赖:
<!--httpClient的依赖 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
配置连接池
在order-service的application.yml中添加配置:
feign:
client:
config:
default: # default全局的配置
loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
httpclient:
enabled: true # 开启feign对HttpClient的支持
max-connections: 200 # 最大的连接数
max-connections-per-route: 50 # 每个路径的最大连接数
总结,Feign的优化:
1.日志级别尽量用basic
2.使用HttpClient或OKHttp代替URLConnection
① 引入feign-httpClient依赖
② 配置文件开启httpClient功能,设置连接池参数