Feign的基本使用(http客户端)
1、Feign的基本介绍
Feign 是 Netflix 开发的声明式、模板化的HTTP客户端, Feign可以帮助我们更快捷、优雅地调用HTTP API。
Spring Cloud Feign帮助我们定义和实现依赖服务接口的定义。在Spring Cloud feign的实现下,只需要创建一个接口并用注解方式配置它,即可完成服务提供方的接口绑定,简化了在使用Spring Cloud Ribbon时自行封装服务调用客户端的开发量。
Spring Cloud对Feign进行了增强,使Feign支持了Spring MVC注解,并整合了Ribbon和Eureka,从而让Feign的使用更加方便。
1.1、Feign和RestTemplate的区别
由于我们的服务调用都是基于Http协议进行的,所以代码中不得不使用Http相应的客户端来进行服务间沟通。RestTemplate是Spring Web提供的Http客户端,但是使用 RestTemplate 时代码可读性差,并且参数复杂 url 难维护。Feign是一个声明式的http客户端,其作用就是帮助我们优雅地实现http请求的发送,解决上面提到的问题。
2、Feign的基本使用
在Spring Cloud中,使用 Feign 非常简单,创建一个接口,并在接口上添加一些注解,代码就完成了。Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。
下面假设在 order-service 中引入 feign,向目标服务 user-service 发起请求。(注意,order-service 和 user-service 都必须在注册中心已经注册,否则请求发起无法成功)
首先,在需要使用 feign 发起 http 请求的服务即 order-service 中引入 feign 的依赖,如下:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
在该服务的启动类中添加注解 @EnableFeignClients,以此来开启Feign的功能,如下:
@MapperScan("com.example.orderservice.mapper") @SpringBootApplication @EnableFeignClients //开启Feign的功能 public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }
在 order-service 项目中新建一个接口类,并在接口上添加一些注解,如下:
@FeignClient("userservice") public interface UserClient { @GetMapping("/user/{id}") User findById(@PathVariable("id") Long id); }
feign http 客户端主要就是基于 SpringMVC 的注解来声明远程调用的信息,比如上面的接口类中,通过注解指定了以下信息:
- 通过 @FeifnClient 指定目标服务名称:userservice
- @GetMappding 指定发起的请求方式:GET
- @GetMappding 参数指定请求路径:/user/{id}
- 成员方法指定了发起的 http 请求的参数:Long id
- 成员方法的返回值指定了 http 请求返回值的类型:User
然后就可以在代码中通过调用该接口类的方法来发起 http 请求了,如下:
@Service public class OrderService { @Autowired OrderMapper orderMapper; @Autowired private UserClient userClient; public Order queryOrderById(Long orderId) { // 1.查询订单 Order order = orderMapper.findById(orderId); // 2.利用feign发起http请求 User user = userClient.findById(orderId); // 3.封装user到Order order.setUser(user); // 4.返回 return order; } }
实际上上面的代码相当于 RestTemplate 的以下代码:
String url = "http://userservice/user/" + order.getUserId(); User user = restTemplate.getForObject(url, User.class);
以上就使用了 Feign 客户端代替了 RestTemplate 来发起 http 请求,并且 Feign 无需特定指定负载均衡,默认 feign 就实现了负载均衡,也就是会自动负载均衡到目标服务的多个服务节点中。
2.1、自定义配置
可通过一些自定义配置来覆盖 feign 的默认配置,可以修改的配置如下:
一般我们只需要配置日志级别即可。日志记录会消耗部分性能,在调试代码时,我们可以将日志级别改为 FULL,但是在一般情况下,日志级别都是设置为 NONE 或者 BASIC。
配置Feign日志有两种方式:1.配置文件方式、2.java代码方式
- 通过配置文件自定义配置
通过配置文件来自定义 feign 的日志级别,只需在配置文件添加以下配置即可:
#全局生效 feign: client: config: default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置 loggerLevel: FULL # 日志级别
上面是定义了全局配置,如果想要自定义配置对具体某个目标服务发起请求时的配置的话,可以使用以下配置:
#局部生效 feign: client: config: userservice: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置 loggerLevel: FULL # 日志级别
- 通过Java代码自定义配置
java代码方式,首先需要先声明一个Bean:
public class FeignClientConfiguration { @Bean public Logger.Level feignLogLevel(){ return Logger.Level.BASIC; } }
然后如果是全局配置,则把它放到 @EnableFeignClients 这个注解中。比如可以放在启动类的 @EnableFeignClients 注解中,如下:
@SpringBootApplication @EnableFeignClients(defaultConfiguration = FeignClientConfiguration.class) public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }
如果是局部配置,则把它放到 @FeignClient 这个注解中。比如可以放在上面在使用 feign 时创建的接口类中,如下:
@FeignClient(value = "userservice", configuration = FeignClientConfiguration.class) public interface UserClient { @GetMapping("/user/{id}") User findById(@PathVariable("id") Long id); }
3、feign 性能优化
3.1、使用连接池
Feign 底层的客户端实现实际上是使用了 URLConnection,该 http 客户端不支持连接池,所以我们可以通过使用 Apache HttpClient 或者 OKHttp 来使其支持连接池,达到一定的性能优化效果。
下面以使用 Apache HttpClient 为例,首先引入 HttpClient 依赖,然后再在配置文件中配置连接池即可。
如下:
<!--httpClient的依赖 --> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> </dependency>
在配置文件中配置连接池和相关参数,如下:
feign: httpclient: enabled: true # 开启feign对HttpClient的支持 max-connections: 200 # 最大的连接数 max-connections-per-route: 50 # 每个路径的最大连接数