前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >微服务通信密码,OpenFeign如何实现透明、高效的接口调用与协同

微服务通信密码,OpenFeign如何实现透明、高效的接口调用与协同

原创
作者头像
星辰大海的精灵
修改2024-04-11 14:01:45
3360
修改2024-04-11 14:01:45
举报
文章被收录于专栏:开发工具开发工具

引言

在微服务架构的世界里,服务间的顺畅通信至关重要。OpenFeign,作为Spring Cloud生态系统中的一颗璀璨明珠,以其声明式的HTTP客户端特性,极大地简化了微服务间的交互。本文将带您深入探索OpenFeign的核心原理,并结合实际案例,剖析其在日常开发中的应用场景,助力您在微服务通信中更加得心应手。

OpenFeign简介

OpenFeign 的中心思想在于通过提供一种声明式、注解驱动的接口化服务调用方式,极大地简化了微服务架构中的RESTful API调用以及服务间通信的复杂性。它使得开发者可以聚焦于业务逻辑本身,如同调用本地方法一样便捷地调用远程服务,而不必深陷于HTTP请求细节的实现。OpenFeign 动态生成代理类来处理请求和响应转换,有效地降低了耦合度,并且它集成了Spring Cloud生态系统,支持服务发现、负载均衡、容错处理等高级功能,从而增强了微服务间的通信效率与稳定性,对微服务架构的整体优化起到了重要作用。

工作流程

核心特性

在看了解每一个核心特性之前,有两个固定的前置条件,后面不在单独赘述。

  1. 引入依赖
代码语言:javascript
复制
xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. 在启动类上添加@EnableFeignClients注解,开启openFeign功能
代码语言:javascript
复制
java
@SpringBootApplication
@EnableFeignClients
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

声明式客户端:

OpenFeign允许开发者通过定义接口并添加注解的方式来创建HTTP客户端。这种方式使得编写的客户端代码更加简洁、直观,并且易于维护。 Java 代码示例

定义一个Feign客户端接口,并使用@FeignClient注解标记

代码语言:javascript
复制
java
@FeignClient(value = "user-center", path = "/admin/feign/serviceProvider")
public interface ServiceProviderClient {

    @GetMapping("/service/path")
    String getServiceData();

    @PostMapping("/service/path")
    String createServiceData(@RequestBody SomeRequestObject data);

    @PutMapping("/service/path/{id}")
    String updateServiceData(@PathVariable("id") Long id, @RequestBody SomeRequestObject data);

    @DeleteMapping("/service/path/{id}")
    String deleteServiceData(@PathVariable("id") Long id);
}

Spring Cloud集成:

OpenFeign与Spring Cloud紧密集成,支持Spring MVC的注解,如@RequestMapping,并利用Spring的HttpMessageConverters来处理请求和响应的编解码。

  1. 编写OpenFeign客户端
代码语言:javascript
复制
java

@Api(tags = "用户中心Feign-Api")
@FeignClient(value = "user-center", path = "/userInfo")
public interface UserFeignApi {

    @ApiOperation("根据用户ID查询用户信息")
    @GetMapping("/getUserInfoById")
    List<UserInfoDTO> getUserInfoById(@RequestParam("userId") Long userId);
}
  1. 微服务调用者发起调用,像调用本地方式一样调用远程微服务提供者
代码语言:javascript
复制
java
@Api(tags = {"用户Feign-Api"})
@RestController
@RequestMapping("/admin/feign/userInfo")
public class BackendUserFeignController {

    @Autowired
    private UserFeignApi userApi;

    @ApiOperation("根据用户ID查询用户详情")
    @GetMapping("/getUserInfoById")
    public BaseResult<List<UserInfoDTO>> getUserInfoById(@RequestParam("userId") Long userId) {
        return userApi.getUserInfoById(userId);
    }
}

负载均衡:

OpenFeign集成了Ribbon,一个客户端负载均衡器,使得通过OpenFeign发起的HTTP请求可以自动地在多个服务实例间进行负载均衡。如果想要自定义负载均衡策略,还需要做点事情。

  1. 引入ribbon依赖
代码语言:javascript
复制
xml

   <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    </dependency>
  1. LoadBalancer默认采用了轮询的负载均衡策略,如果你想自定义负载均衡策略,可以在application.yml或application.properties配置文件中增加如下的配置
代码语言:javascript
复制
yaml

spring:
  cloud:
    loadbalancer:
      ribbon:
        enabled: true
        nfloadbalancer:
          rule:
            # 随机 
            name: com.netflix.loadbalancer.RandomRule
            # 加权响应时间
            name: com.netflix.loadbalancer.WeightedResponseTimeRule
            # 区域避免
            name: com.netflix.loadbalancer.AvailabilityFilteringRule
            # 自定义策略 若要实现自定义策略,需要创建一个类实现com.netflix.loadbalancer.IRule接口,并在配置中指定这个自定义类的全限定名

容错和熔断:

OpenFeign可以与Hystrix结合使用,提供容错和熔断机制。这有助于防止服务故障的蔓延,提高系统的稳定性和可靠性。

日志增强:

OpenFeign提供了日志增强功能,允许开发者通过配置不同的日志级别来监控HTTP请求和响应的详细信息。日志级别包括NONE(无日志)、BASIC(基本信息)、HEADERS(请求和响应头信息)和FULL(完整的请求和响应信息)。

  1. Java Bean配置方式 利用@Configuration实现全局生效,对所有的微服务调用者都生效 定义一个配置类,指定日志级别
代码语言:javascript
复制
java

// 注意: 此处配置@Configuration注解就会全局生效,如果想指定对应微服务生效,就不能配置
@Configuration
@Configuration
public class FeignConfig {
    
    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

通过源码可以看到日志等级有4种,分别是:

  • NONE【性能最佳,默认值】:不记录任何日志。
  • BASIC【适用于生产环境追踪问题】: 仅记录请求方法、URL、响应状态代码以 及执行时间。
  • HEADERS:记录BASIC级别的基础上, 记录请求和响应的header。
  • FULL【比较适用于开发及测试环境定位问题】:记录请求和响应的header、body和元数据。
  1. 在application.yml配置文件中配置 Client 的日志级别才能正常输出日志,格式 是"logging.level.feign接口包路径=debug"
代码语言:javascript
复制
yaml

logging: 
  level: 
  com.tuling.mall.feigndemo.feign: debug
  1. 全局生效,对所有的微服务调用者都生效
代码语言:javascript
复制
yaml

spring:
  cloud:
    openfeign:
      client:
        config:
          default:
            loggerLevel: FULL
  1. 局部生效,yml中对调用的微服务提供者进行配置 对应属性配置类:org.springframework.cloud.openfeign.FeignClientProperties.FeignClientConfiguration
代码语言:javascript
复制
yaml

spring:
  cloud:
    openfeign:
      client:
        config:
          mall-order: #对应微服务
            loggerLevel: FULL

支持多种HTTP客户端:

除了内置的HTTP客户端,OpenFeign还允许开发者通过添加相应的依赖和配置来使用Apache HttpClient或OkHttp等第三方HTTP客户端。 Feign发起调用真正执行逻辑:feign.Client#execute (扩展点)

代码语言:javascript
复制
java

@Override
public Response execute(Request request, Options options) throws IOException{
  HttpURLConnection connection = convertAndSet(request, options);
  return convertResponse(connection, request);
}
  1. 配置Apache HttpClient5
  • 引入依赖
代码语言:javascript
复制
xml

<dependency>
  <groupId>io.github.openfeign</groupId>
  <artifactId>feign-hc5</artifactId>
</dependency>
  • 修改yaml配置,启用Apache HttpClient5
代码语言:javascript
复制
yaml

spring:
  cloud:
    openfeign:
      #feign client使用 Apache HttpClient5
      httpclient: 
        hc5:
          enabled: true

关于配置可参考源码: org.springframework.cloud.openfeign.FeignAutoConfiguration

测试:调用会进入feign.httpclient.ApacheHttpClient#execute

  1. 配置OkHttp
  • 引入依赖
代码语言:javascript
复制
xml

<dependency>
  <groupId>io.github.openfeign</groupId>
  <artifactId>feign-okhttp</artifactId>
</dependency>
  • 修改yaml配置,启用Apache HttpClient5
代码语言:javascript
复制
yaml

spring:
  cloud:
    openfeign:
      #feign client使用 Apache okhttp
      httpclient: 
        okhttp:
          enabled: true

关于配置可参考源码: org.springframework.cloud.openfeign.FeignAutoConfiguration

测试:调用会进入feign.okhttp.OkHttpClient#execute

请求和响应压缩:

OpenFeign支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。

代码语言:javascript
复制
yaml

spring:
  cloud:
    openfeign:
      compression: # 配置 GZIP 来压缩数据
        request:
          enabled: true 
          mime-types: text/xml,application/xml,application/json 
          min-request-size: 1024 # 最小请求压缩阈值
        response:
        enabled: true

注意:当 Feign 的 HttpClient不是 okHttp的时候,压缩配置不会生效,配置源码在 FeignAcceptGzipEncodingAutoConfiguration

核心代码就是 @ConditionalOnMissingBean(type="okhttp3.OkHttpClient"),表示 Spring容器 中不包含指定的 bean 时条件匹配,也就是没有启用 okhttp3 时才会进行压缩配置。

拦截器配置

通常我们调用的接口都是有权限控制的,很多时候可能认证的值是通过参数去传递的,还有就是通过 请求头去传递认证信息,比如 Basic 认证方式。 Feign 中我们可以直接配置 Basic 认证

代码语言:javascript
复制
java

@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor(){
    retuen new BasicAuthRequestInterceptor("admin","123456");
}
  • 使用场景 统一添加 header 信息; 对 body 中的信息做修改或替换;
  • 扩展点: feign.RequestInterceptor 每次feign发起http调用之前会去执行拦截器中的逻辑。所以,如果想要在发送请求时增加一些额外请求参数的话,可以继承这个接口,原因是因为openFeign在远程调用之前会遍历容器中的RequestInterceptor,调用RequestInterceptor的apply方法,创建一个新的Request进行远程服务调用。通过过实现RequestInterceptor给容器中添加自定义的RequestInterceptor实现类,在这个类里面设置需要发送请求时的参数。

代码语言:javascript
复制
java

public interface RequestInterceptor {

  /**
   * Called for every request. Add data using methods on the supplied {@linkRequestTemplate}.
   */
  void apply(RequestTemplate template);
}

自定义的RequestInterceptor实现类

代码语言:javascript
复制
java

@Slf4j
public class FeignAuthRequestInterceptor implements RequestInterceptor {
  @Override
  public void apply(RequestTemplate template) {
  // 业务逻辑 模拟认证逻辑测试也可以在yml中配置
  ServletRequestAttributes attributes = (ServletRequestAttributes)
RequestContextHolder.getRequestAttributes();
  if(null != attributes){
      HttpServletRequest request = attributes.getRequest();
      String access_token = request.getHeader("Authorization");
      log.info("从Request中解析请求头:{}",access_token);
      //设置token
      template.header("Authorization",access_token);
     }
    }
  }

  @Configuration // 全局生效
  public class FeignConfig {
    @Bean
    public Logger.Level feignLoggerLevel() {
      return Logger.Level.FULL;
    }
    
  /**
    * 自定义拦截器
    * @return
  */
    @Bean
    public FeignAuthRequestInterceptor feignAuthRequestInterceptor(){
    return new FeignAuthRequestInterceptor();
  }
}

也可以在yaml中配置

代码语言:javascript
复制
yaml

spring:
  cloud:
    openfeign:
      client:
        config:
          user-center: #对应微服务
            requestInterceptors: #配置拦截器
              -
                com.user.feigndemo.interceptor.AuthRequestInterceptor

user-center端可以通过 @RequestHeader获取请求参数进行校验,可以在filter或者mvc interceptor 中进行处理

#结语

OpenFeign通过简化服务间通信的复杂性,实现了微服务之间的透明和高效协同。通过注解和自动配置,开发者能够轻松定义服务接口,而Feign在后台处理请求的发送和响应的接收。集成服务发现和负载均衡机制,Feign不仅提高了调用的灵活性,也增强了系统的健壮性。这使得微服务架构下的接口调用更加简洁、高效,为构建现代化的分布式应用提供了有力支撑。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • OpenFeign简介
  • 工作流程
  • 核心特性
    • 声明式客户端:
      • Spring Cloud集成:
        • 负载均衡:
          • 容错和熔断:
            • 日志增强:
              • 支持多种HTTP客户端:
                • 请求和响应压缩:
                  • 拦截器配置
                  相关产品与服务
                  负载均衡
                  负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档