SpringCloud - Feign

Feign 入门

先看 RestTemplate 发起远程调用的代码:

        String url = "http://userservice/user/" + order.getUserId();
        User user = restTemplate.getForObject(url, User.class);

存在以下问题:

  • 代码可读性差,编程体验不统一
  • 参数复杂URL难以维护

Feign 是一个声明式的http 客户端,官方地址:https://github.com/OpenFeign/feign
其作用就是帮助我们优雅的实现http请求的发送,解决上面提到的问题

使用入门:
1.引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2.启动类开启注解

3.编写客户端

package cn.itcast.order.client;


import cn.itcast.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 {
  
    /*
    主要是使用SpringMVC的注解来声明远程调用:
      1.服务名称:userservice
      2.请求方式:Get
      3.请求路径:/user/{id}
      4.请求参数: Long id
      5.返回值类型:User
    */
    @GetMapping("/user/{id}")
    User fingById(@PathVariable("id") Long id);
}

4.修改order-service

@Autowired
private UserClient userClient;

public Order queryOrderById(Long orderId) {
    // 1.查询订单
    Order order = orderMapper.findById(orderId);
    //2.查询用户信息
    User user = userClient.fingById(order.getUserId());
    order.setUser(user);
    // 3.返回
    return order;
}

feign 中已经引入ribbon,因此默认也是已经支持负载均衡的:

Feign 支持自定义配置

Feign 运行自定义配置来覆盖默认配置,可以修改的配置如下:

一般我们需求配置的就是日志级别。默认为NONE

e.g: 更改日志方式一:

feign:
  client:
    config:
      default: # 对所请求的全部微服务生效,也可指定具体微服务 比如uservice
        logger-level: FULL

控制台日志:

09-09 11:13:10:320 DEBUG 15732 --- [nio-8080-exec-7] c.i.order.mapper.OrderMapper.findById    : ==> Parameters: 101(Long)
09-09 11:13:10:331 DEBUG 15732 --- [nio-8080-exec-7] c.i.order.mapper.OrderMapper.findById    : <==      Total: 1
09-09 11:13:10:335 DEBUG 15732 --- [nio-8080-exec-7] cn.itcast.order.client.UserClient        : [UserClient#fingById] ---> GET http://userservice/user/1 HTTP/1.1
09-09 11:13:10:335 DEBUG 15732 --- [nio-8080-exec-7] cn.itcast.order.client.UserClient        : [UserClient#fingById] ---> END HTTP (0-byte body)
09-09 11:13:10:373 DEBUG 15732 --- [nio-8080-exec-7] cn.itcast.order.client.UserClient        : [UserClient#fingById] <--- HTTP/1.1 200 (36ms)
09-09 11:13:10:373 DEBUG 15732 --- [nio-8080-exec-7] cn.itcast.order.client.UserClient        : [UserClient#fingById] connection: keep-alive
09-09 11:13:10:373 DEBUG 15732 --- [nio-8080-exec-7] cn.itcast.order.client.UserClient        : [UserClient#fingById] content-type: application/json
09-09 11:13:10:373 DEBUG 15732 --- [nio-8080-exec-7] cn.itcast.order.client.UserClient        : [UserClient#fingById] date: Sat, 09 Sep 2023 03:13:10 GMT
09-09 11:13:10:373 DEBUG 15732 --- [nio-8080-exec-7] cn.itcast.order.client.UserClient        : [UserClient#fingById] keep-alive: timeout=60
09-09 11:13:10:373 DEBUG 15732 --- [nio-8080-exec-7] cn.itcast.order.client.UserClient        : [UserClient#fingById] transfer-encoding: chunked
09-09 11:13:10:373 DEBUG 15732 --- [nio-8080-exec-7] cn.itcast.order.client.UserClient        : [UserClient#fingById] 
09-09 11:13:10:374 DEBUG 15732 --- [nio-8080-exec-7] cn.itcast.order.client.UserClient        : [UserClient#fingById] {"id":1,"username":"柳岩","address":"湖南省衡阳市"}
09-09 11:13:10:374 DEBUG 15732 --- [nio-8080-exec-7] cn.itcast.order.client.UserClient        : [UserClient#fingById] <--- END HTTP (59-byte body)

log.level 配置为BASIC 的效果:

09-09 11:20:57:735 DEBUG 4416 --- [nio-8080-exec-4] cn.itcast.order.client.UserClient        : [UserClient#fingById] ---> GET http://userservice/user/1 HTTP/1.1
09-09 11:20:57:766 DEBUG 4416 --- [nio-8080-exec-4] cn.itcast.order.client.UserClient        : [UserClient#fingById] <--- HTTP/1.1 200 (29ms)

更改配置方式二:

针对所有微服务调用生效:

针对具体微服务调用生效:

package cn.itcast.order.client;





import cn.itcast.order.config.DefaultFeignLClientConfig;
import cn.itcast.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(value= "userservice", configuration = DefaultFeignLClientConfig.class)
public interface UserClient {


    @GetMapping("/user/{id}")
    User fingById(@PathVariable("id") Long id);
}

logger.level 配置为 HEADERS 的效果:

09-09 11:27:17:292 DEBUG 9304 --- [nio-8080-exec-2] cn.itcast.order.client.UserClient        : [UserClient#fingById] <--- HTTP/1.1 200 (29ms)
09-09 11:27:17:292 DEBUG 9304 --- [nio-8080-exec-2] cn.itcast.order.client.UserClient        : [UserClient#fingById] connection: keep-alive
09-09 11:27:17:292 DEBUG 9304 --- [nio-8080-exec-2] cn.itcast.order.client.UserClient        : [UserClient#fingById] content-type: application/json
09-09 11:27:17:292 DEBUG 9304 --- [nio-8080-exec-2] cn.itcast.order.client.UserClient        : [UserClient#fingById] date: Sat, 09 Sep 2023 03:27:17 GMT
09-09 11:27:17:293 DEBUG 9304 --- [nio-8080-exec-2] cn.itcast.order.client.UserClient        : [UserClient#fingById] keep-alive: timeout=60
09-09 11:27:17:293 DEBUG 9304 --- [nio-8080-exec-2] cn.itcast.order.client.UserClient        : [UserClient#fingById] transfer-encoding: chunked
09-09 11:27:17:293 DEBUG 9304 --- [nio-8080-exec-2] cn.itcast.order.client.UserClient        : [UserClient#fingById] <--- END HTTP (59-byte body)

Feign 性能优化

Feign 底层的客户端实现:

  • URLConnection:默认实现,不支持连接池
  • Apache HttpClient:支持连接池
  • OKHttp: 支持连接池

因此优化Feign 的性能主要包括:

  • 使用连接池代替默认的URLConnection
  • 日志级别最好使用basic 或 none

修改Feign 底层客户端的实现步骤:
1.引入依赖:

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

2.修改配置:

feign:
  client:
    config:
      default: # 全部生效,也可指定具体uservice
        logger-level: BASIC
  httpclient:
    enabled: true
    max-connections: 200 # 最大连接数
    max-connections-per-route: 50 # 每个路径的最大连接数

Feign - 最佳实践

方式一:继承

方式二:抽取,将FeignClient 抽取为独立的模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用

方式二案例:

1.新建feign-api发模块:

2.order-service 引入 feign-api 依赖:

3.order-service 启动类指定具体的FeignClient类或者 FeignClient所在的包(全部的FeiginClient)

//引入具体的FeignClient类
@EnableFeignClients(clients = UserClient.class)

/引入所有的FeignClient类
@EnableFeignClients(basePackages = "com.chuangzhou.client")
posted @ 2023-09-09 10:40  chuangzhou  阅读(6)  评论(0编辑  收藏  举报