找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

983

积分

0

好友

139

主题
发表于 4 天前 | 查看: 15| 回复: 0

要理解Feign首次调用慢的原因,首先需要梳理清楚远程调用的完整流程,这涉及到注册中心、负载均衡组件与Feign客户端之间的协作关系。在微服务架构中,服务实例会注册到Eureka或Nacos等注册中心。Feign本身并不直接处理服务发现与负载,这部分功能由Ribbon承担。Ribbon会从注册中心获取服务提供者的列表,并将其缓存在本地。随后,FeignClient在进行调用时,实际上是通过Ribbon选择一个可用的服务实例发起HTTP请求。

Ribbon的负载均衡机制

核心在于理解Ribbon如何获取并维护服务列表。下图展示了其核心工作原理:

Ribbon负载均衡原理图

RibbonClientConfiguration 配置类中,核心是 ILoadBalancer 接口的实现。该接口定义了对服务实例进行操作的关键方法,包括:添加服务器、选择服务器、标记服务下线、获取所有服务列表、获取健康服务列表等。

ILoadBalancer接口方法

默认使用的负载均衡器是 ZoneAwareLoadBalancer。在其初始化过程中,会调用父类 DynamicServerListLoadBalancerrestOfInit 方法。其中有两个非常关键的方法:enableAndInitLearnNewServersFeatureupdateListOfServers

restOfInit方法

enableAndInitLearnNewServersFeature 方法内部,会启动一个服务列表更新器(ServerListUpdater):

LOGGER.info(“Using serverListUpdater {}”, serverListUpdater.getClass().getSimpleName());
serverListUpdater.start(updateAction);

ServerListUpdater.start 方法的实现,本质上是通过一个后台线程定时去拉取最新的服务列表。这就是Ribbon维护本地服务缓存的方式。

ServerListUpdater.start方法

Ribbon负载均衡策略简介

除了服务列表获取,负载均衡策略也是影响调用的因素。Ribbon内置了多种策略:

  • RoundRobinRule:轮询策略。
  • WeightedResponseTimeRule:权重响应时间策略,响应时间越短的服务实例权重越高。
  • RandomRule:随机策略。
  • BestAvailableRule:最小并发数策略。
  • RetryRule:重试策略。
  • AvailabilityFilteringRule:可用性敏感策略,过滤掉不健康的实例。
  • ZoneAvoidanceRule:区域感知策略(默认)。

关于如何自定义负载均衡策略,本文不做展开。

Ribbon的延迟加载与“饥饿加载”模式

问题的根源在于,Ribbon对于Feign客户端的负载均衡器是在服务启动后,第一次发生实际调用时才进行创建的。 因此,第一次调用不仅包含HTTP请求的网络耗时,还需要加上LoadBalancerFeign Client等组件的初始化时间,从而导致明显延迟。

以下是一个简单的服务间调用示例(System服务调用System2服务):

@GetMapping(“/requestSystem2Api”)
public String requestSystem2Api(){
    long startTime = System.currentTimeMillis();
    R<String> stringR = iTestServiceClient.testRequestMethod();
    if (null !=stringR){
        log.info(“接口返回:”+stringR.getMsg());
    }
    long needTime = System.currentTimeMillis() - startTime;
    log.info(“接口调用需要的时间:”+needTime);
    return “”;
}

从调用日志可以清晰看到,第一次调用时,DynamicServerListLoadBalancer 会进行Feign客户端的负载均衡初始化,耗时较长;第二次调用则直接使用已初始化的组件,速度很快。

首次调用与后续调用耗时对比

开启Ribbon饥饿加载

为了解决首次调用慢的问题,Spring Cloud Ribbon 提供了 ribbon.eager-load 配置(俗称“饥饿加载”模式)。该模式会在应用启动时,预先初始化指定服务的Ribbon客户端,从而避免首次调用的初始化开销。

application.yml 中的配置示例如下:

ribbon:
  nacos:
    enabled: true
  eager-load:
    enabled: true # 开启饥饿加载模式
    clients: Lxlxxx-system2 # 指定需要预加载的服务名(可配置多个)
  ReadTimeout: 10000
  ConnectTimeout: 10000

开启此配置后,在项目启动日志中可以看到,指定的服务(如Lxlxxx-system2)的Ribbon客户端已被加载,从而有效避免了首次请求的超时问题。

开启饥饿加载后的启动日志

总结

Ribbon的饥饿加载模式,本质上是一种 “客户端负载预热” 操作。它在应用启动阶段提前完成负载均衡客户端的初始化,将初始化时间从首次调用的关键路径中移出。如果你的微服务之间存在调用逻辑复杂、处理数据量大或依赖组件多的情况,导致接口本身处理时间较长,再叠加上首次调用的初始化延迟,很容易触发超时。启用饥饿加载是解决此类问题的一个有效实践。




上一篇:iPad 12配置曝光:A19处理器与8GB内存性能大幅提升
下一篇:BurpSuite插件CloudX实战:自动解密AES加密流量助力渗透测试与漏洞挖掘
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-17 20:12 , Processed in 0.119535 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表