JavaJava 程序员

SpringCloud:Feign远程调用

2022-05-27  本文已影响0人  程序花生

1、Feign替代RestTemplate

1.1 Feign的介绍

我们之前使用的RestTemplate远程调用存在着代码可读性差,编程体验不统一,参数复杂URL难以维护。如果再工作中遇见了类似百度搜索的URL将难以维护

当我们面对这么长的URL的时候,当然是希望能够少些甚至不写,最低的要求就是不要再service层看到这种东西。所以我们就使用了Feign

Feign是一个声明式的http客户端,官方地址:github.com/OpenFeign/f…

其作用就是帮助我们优雅的实现http请求的发送,解决上面提到的问题。 Feign我理解是常用于微服务相互调用的。

1.2 SpringCloud使用Feign

1. 添加依赖

```
<!-- Feign客户端依赖 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
```

2. 引导类开启功能

在引导类上添加`@EnableFeignClients`注解

```
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

    ...
}
```

3. 编写Feign客户端

为同一个提供者的服务创建一个接口,里面就替代了所有需要用RestTemplate远程调用的url

    @FeignClient("userservice")
    public interface UserClient {
        @GetMapping("/user/{id}")
        User queryOrderByUserId(@PathVariable Long id);
    }

这个客户端主要是基于SpringMVC的注解来声明远程调用的信息,比如:

这样,Feign就可以帮助我们发送http请求,无需自己使用RestTemplate来发送了。

4. 在对应service层中使用

首先将Feign客户端自动装配,再调用其中的方法。

    @Service
    public class OrderService {

        @Autowired
        private OrderMapper orderMapper;

        @Autowired
        private UserClient userClient;

        public Order queryOrderById(Long orderId) {
            // 1.查询订单
            Order order = orderMapper.findById(orderId);
            // 2\. 利用 Feign 发送 http 请求到对应的 微服务中
            User user = userClient.queryOrderById(orderId);
            // 3\. 封装 User 到 Order 中。
            order.setUser(user);
            // 4.返回
            return order;
        }
    }

2、自定义配置

2.1 Feign自定义配置

Feign可以支持很多的自定义配置,如下表所示:

类型 作用 说明
feign.Logger.Level 修改日志级别 包含四种不同的级别:NONE、BASIC、HEADERS、FULL
feign.codec.Decoder 响应结果的解析器 http远程调用的结果做解析,例如解析json字符串为java对象
feign.codec.Encoder 请求参数编码 将请求参数编码,便于通过http请求发送
feign. Contract 支持的注解格式 默认是SpringMVC的注解
feign. Retryer 失败重试机制 请求失败的重试机制,默认是没有,不过会使用Ribbon的重试

一般情况下,默认值就能满足我们使用,如果要自定义时,只需要创建自定义的@Bean覆盖默认Bean即可。

2.2 配置文件方式

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

而日志的级别分为四种:

2.3 Java代码方式

先创建Feign日志级别配置类

public class DefaultFeignConfiguration {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.HEADERS;
    }

    ...
}

在引导类开启Feign并传入日志级别配置类@EnableFeignClients(defaultConfiguration = 日志级别配置类.class)

    @SpringBootApplication
    @EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class)
    public class OrderApplication {

        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class, args);
        }

        ...
    }

将配置文件放到对应的Feign客户端的@FeignClient(value = "服务名称", configuration = 日志级别配置类.class)

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

2.4 配置优先级

3、Feign使用优化

Feign作为一个网关,连接使用TCP/IP协议发起http请求,依赖于其它的框架。如果频繁发送请求就会有多次的“三次握手四次挥手”。其底层客户端实现包括:

为了减少频繁请求的情况下资源的消耗,所以在优化方面可以着力于客户端底层使用连接池代替默认的URLConnection。下面我们就用Apache HttpClient来演示。

3.1 Apache HttpClient使用

1. 引入依赖

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

2. 配置

    feign:
      httpclient:
        # 开启 httpClient
        enabled: true
        # 连接池最大连接数
        max-connections: 200
        # 单个服务最大占用连接数
        max-connections-per-route: 50

4、最佳实践

4.1 统一父接口标准

我们可以发现,Feign的客户端和提供者的controller层是非常相似的

所以为了让代码简化,我们可以将Feign客户端和提供者controller层提作为接口放在一个微服务中,通过引入微服务将对应的接口导入。

4.2 抽取Feign独立模块

FeiginClient抽取成独立的模块,并且将接口有关的pojo、默认的Feign配置都放到这个模块中,提供给所有消费者使用。

1. 创建Feign-api模块

2. 引入依赖

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

3. 将对应的FeignClient和接口相关的pojo以及默认的配置都放在项目中

[图片上传失败...(image-c3dcce-1653662031811)]

4. 在使用Feign的项目引导类上,开启扫描Feign-api模块对应的位置

  1. 我们可以将Feign-api模块内某个包下的所有FeignClient都扫描进去。通过@EnableFeignClients(clients = basePackages = "包路径")完成。
  2. 我们可以将Feign-api模块下指定的FeignClient字节码扫描。通过@EnableFeignClients(clients = {clients.class, clients.class})

5. 启动服务,就成功了。

作者:何鸭子
链接:https://juejin.cn/post/7101677917725753375
来源:稀土掘金

上一篇 下一篇

猜你喜欢

热点阅读