SpringCloud使用OpenFeign进行远程调用
1、OpenFeign介绍
我们利用Nacos实现了服务的治理,利用RestTemplate实现了服务的远程调用。但是远程调用的代码太复杂了:
获取url
List<ServiceInstance> instances = discoveryClient.getInstances("hm-item-service");
ServiceInstance serviceInstance = instances.get(RandomUtil.randomInt(instances.size()));
ResponseEntity<List<ItemDTO>> responseEntity = restTemplate.exchange(
serviceInstance.getUri() + "/items?ids={ids}",
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<ItemDTO>>() {
},
StrUtil.join(",", itemIds)
);
而且这种调用方式,与原本的本地方法调用差异太大,编程时的体验也不统一,一会儿远程调用,一会儿本地调用。
因此,我们必须想办法改变远程调用的开发模式,让远程调用像本地方法调用一样简单。而这就要用到OpenFeign组件了。
其实远程调用的关键点就在于四个:
- 请求方式
- 请求路径
- 请求参数
- 返回值类型
所以,OpenFeign就利用SpringMVC的相关注解来声明上述4个参数,然后基于动态代理帮我们生成远程调用的代码,而无需我们手动再编写,非常方便。
2、快速入门
我们以cart-service中的查询我的购物车为例。因此下面的操作都是在cart-service中进行
引入依赖
在cart-service
服务的pom.xml中引入OpenFeign
的依赖和loadBalancer
依赖:
<!--openFeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--负载均衡器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
启用OpenFeign
在cart-service
的CartApplication
启动类上添加注解,启动OpenFeign功能:
@MapperScan("com.hmall.cart.mapper")
@SpringBootApplication
@EnableFeignClients()
public class cartApplication {
public static void main(String[] args) {
SpringApplication.run(cartApplication.class, args);
}
}
编写OpenFeign客户端
在cart-service
中,定义一个新的接口,编写Feign客户端:
其中代码如下:
@FeignClient("item-service")
public interface ItemClient {
@GetMapping("/items")
List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);
}
这里只需要声明接口,无需实现方法。接口中的几个关键信息:
@FeignClient("item-service")
:声明服务名称@GetMapping
:声明请求方式@GetMapping("/items")
:声明请求路径@RequestParam("ids") Collection<Long> ids
:声明请求参数List<ItemDTO>
:返回值类型
有了上述信息,OpenFeign就可以利用动态代理帮我们实现这个方法,并且向http://item-service/items
发送一个GET
请求,携带ids为请求参数,并自动将返回值处理为List<ItemDTO>
。
我们只需要直接调用这个方法,即可实现远程调用了。
3、连接池
Feign底层发起http请求,依赖于其它的框架。其底层支持的http客户端实现包括:
- HttpURLConnection:默认实现,不支持连接池
- Apache HttpClient :支持连接池
- OKHttp:支持连接池
因此我们通常会使用带有连接池的客户端来代替默认的HttpURLConnection。比如,我们使用OK Http.
引入依赖
<!--OK http 的依赖 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
开启连接池
application.yml
配置文件中开启Feign的连接池功能:
feign:
okhttp:
enabled: true # 开启OKHttp功能
重启服务,连接池就生效了。
4、日志配置
OpenFeign只会在FeignClient所在包的日志级别为DEBUG时,才会输出日志。而且其日志级别有4级:
- NONE:不记录任何日志信息,这是默认值。
- BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
- HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
- FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。
Feign默认的日志级别就是NONE,所以默认我们看不到请求日志。
定义日志级别
public class DefaultFeignConfig {
@Bean
public Logger.Level feignLogLevel(){
return Logger.Level.FULL;
}
}
配置
接下来,要让日志级别生效,还需要配置这个类。有两种方式:
-
局部生效:在某个
FeignClient
中配置,只对当前FeignClient
生效@FeignClient(value = "item-service", configuration = DefaultFeignConfig.class)
-
全局生效:在
@EnableFeignClients
中配置,针对所有FeignClient
生效。@EnableFeignClients(defaultConfiguration = DefaultFeignConfig.class)