微服务:一篇博客带你学会Feign(远程调用、自定义配置、性能优化、常用方式)

Feign

基于Feign的远程调用

声明式http客户端,其实就是一个简化http发送的客户端。

orderservice中引入

  1. 引入依赖:
        <!--openFeign依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
  1. 配置类上开启Feign自动装配 @EnableFeignClients

  2. 编写Feign接口

@FeignClient("userservice") // 指定服务名称
public interface UserClient {

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

以看到其实和写一个接口类似,这样的好处是,不仅方便程序员编写,而且让程序员使用时认为像是在本地调用一样方便。

传统的利用restTemplate方式发送:

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

大家可以类比去记忆。

  1. 使用
    直接像使用本地bean一样去注入和调用即可,不影响代码可读性还。
@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Resource
    private RestTemplate restTemplate;

    @Autowired
    private UserClient userClient;

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
/*        // 2.查询用户,远程调用
        String url = "http://userservice/user/" + order.getUserId();
        User user = restTemplate.getForObject(url, User.class);*/

        User user = userClient.findById(order.getUserId());

        // 3. 封装
        order.setUser(user);
        // 4.返回
        return order;
    }
}

调用成功:
在这里插入图片描述

Feign本身就自带的Ribbon负载均衡。

自定义配置

正常情况下,默认自动装配的配置就足够了。

在这里插入图片描述

一般最多就是改改日志,其他的一般不修改。

下面介绍两种修改方式:

  1. 基于配置文件
    针对某个服务:
feign:  
  client:
    config: 
      userservice: # 针对某个微服务的配置
        loggerLevel: FULL #  日志级别 

针对全部服务:

feign:  
  client:
    config: 
      default: # 用default就是针对全部服务,如果写服务名称,则是针对某个微服务的配置
        loggerLevel: FULL #  日志级别 

四种日志级别:

  • NONE:不记录任何日志信息,这是默认值。
  • BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
  • HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
  • FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。
  1. 基于java代码修改
@Configuration
public class DefaultFeignConfiguration {

    @Bean
    public Logger.Level feignLogLevel() {
        return Logger.Level.BASIC;
    }
}

全局生效,将其放到启动类的@EnableFeignClients这个注解中:

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class) 

局部生效,将其放到对应服务的@FeignClient这个注解中:

@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration.class) 

FULL级别的日志信息:

05-30 10:30:12:184 DEBUG 6836 --- [nio-8080-exec-3] cn.itcast.order.web.UserClient           : [UserClient#findById] ---> GET http://userservice/user/1 HTTP/1.1
05-30 10:30:12:184 DEBUG 6836 --- [nio-8080-exec-3] cn.itcast.order.web.UserClient           : [UserClient#findById] ---> END HTTP (0-byte body)
05-30 10:30:12:190 DEBUG 6836 --- [nio-8080-exec-3] cn.itcast.order.web.UserClient           : [UserClient#findById] <--- HTTP/1.1 200 (5ms)
05-30 10:30:12:190 DEBUG 6836 --- [nio-8080-exec-3] cn.itcast.order.web.UserClient           : [UserClient#findById] connection: keep-alive
05-30 10:30:12:190 DEBUG 6836 --- [nio-8080-exec-3] cn.itcast.order.web.UserClient           : [UserClient#findById] content-type: application/json
05-30 10:30:12:190 DEBUG 6836 --- [nio-8080-exec-3] cn.itcast.order.web.UserClient           : [UserClient#findById] date: Thu, 30 May 2024 02:30:12 GMT
05-30 10:30:12:190 DEBUG 6836 --- [nio-8080-exec-3] cn.itcast.order.web.UserClient           : [UserClient#findById] keep-alive: timeout=60
05-30 10:30:12:190 DEBUG 6836 --- [nio-8080-exec-3] cn.itcast.order.web.UserClient           : [UserClient#findById] transfer-encoding: chunked
05-30 10:30:12:190 DEBUG 6836 --- [nio-8080-exec-3] cn.itcast.order.web.UserClient           : [UserClient#findById] 
05-30 10:30:12:190 DEBUG 6836 --- [nio-8080-exec-3] cn.itcast.order.web.UserClient           : [UserClient#findById] {"id":1,"username":"柳岩","address":"湖南省衡阳市"}
05-30 10:30:12:190 DEBUG 6836 --- [nio-8080-exec-3] cn.itcast.order.web.UserClient           : [UserClient#findById] <--- END HTTP (59-byte body)

性能优化

Feign底层发起http请求,依赖于其它的框架。

其底层客户端实现包括:

  • URLConnection:默认,不支持连接池

  • Apache HttpClient:支持连接池

  • OKHttp:支持连接池

优化方法:

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

引入依赖:

        <!--httpClient的依赖 -->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>

配置连接池:

feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志级别
  httpclient:
    enabled: true # 开启feign使用HttpClient
    max-connections: 100 # 最大的连接数
    max-connections-per-route: 20 # 每个路径的最大连接数

Feign 常用使用方式

  1. 继承

在这里插入图片描述

本身就是微服务为了解耦,这样反而让服务端和客户端耦合了。

而且springMVC对应方法参数,比如@PathVariable继承不下来的,因此Controller中必须再次声明方法、参数列表、注解。

  1. 抽取

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

如果不抽取,那么每个服务调用相同的接口都需要重写写相同的代码。

抽取之后,只要引入依赖,即可像在本地一样去使用即可。

在这里插入图片描述

现在来实践一下吧。

创建feign-api子模块,并导入依赖:

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

将order-service中的UserClient、实体类User、DefaultFeignConfigurationy移动到feign-api项目中。

order-service中引入api模块:

        <!--feign-api模块-->
        <dependency>
            <groupId>cn.itcast.demo</groupId>
            <artifactId>feign-api</artifactId>
            <version>1.0</version>
        </dependency>

orderservice上启动类的EnableFeignClients注解上加上此服务需要使用的Client接口,可以引入多个。

@EnableFeignClients(clients = {UserClient.class})

也可以

@EnableFeignClients(basePackage = "feignClient位置")  

将爆红的地方导包(因为位置变了,现在我们用的feign模块中的)。

重启,调用一下:

在这里插入图片描述

  • 27
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cosmoshhhyyy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值