微服务通信背后的秘密:Ribbon 如何选择最佳服务实例?

在上一篇文章揭秘 Feign 调用机制:微服务通信的无缝集成中,我们了解到Feign调用机制的实现深度依赖Ribbon,本文将在此基础上深入探讨Ribbon是如何获取服务实例列表并执行负载均衡相关策略选择具体服务实例的。

一、Ribbon的重要性

在微服务架构中,通常会有多个服务实例同时运行以提供相同的服务。这就需要一种机制来确保客户端能够有效地选择合适的服务实例进行调用,同时还要保证负载能够均衡地分布在各个实例上,以提高系统的整体性能和可靠性。Ribbon 正是为了解决这个问题而诞生的

二、获取服务实例列表

前文中,探究 Eureka 在 Spring Boot 中的配置注入与统一管理机制(下)——第四节提到,Eureka的源码中集成了Ribbon,那么本文继续以Eureka为例。其实,Ribbon 可以与多种服务注册中心集成。

Ribbon 会通过 EurekaClient 接口与 Eureka 服务器进行通信以获取服务实例。以下是核心方法:

  1. updateListOfServers方法
    • 位置:DynamicServerListLoadBalancer类中。
    • 作用:更新可用的服务实例列表
    • 实现:调用 obtainServersViaDiscovery方法来获取可用的服务实例列表
  2. obtainServersViaDiscovery方法
    • 位置:DiscoveryEnabledNIWSServerList类中。
    • 作用:获取可用的服务实例
    • 实现:调用getInstancesByVipAddress(vipAddress, this.isSecure, this.targetRegion)的方法获取可用的服务实例列表。
  3. getInstancesByVipAddress(String vipAddress, boolean secure,@Nullable String region)方法
    它是最核心的方法
    • 位置: DiscoveryClient类中。
    • 作用:负责根据虚拟主机名获取实例列表
    • 实现
public List<InstanceInfo> getInstancesByVipAddress(String vipAddress, boolean secure,
                                                       @Nullable String region) {
   
        ……
        Applications applications;
        // 获取applications
        if (instanceRegionChecker.isLocalRegion(region)) {
   
            applications = this.localRegionApps.get();
        } else {
   
            applications = remoteRegionVsApps.get(region);
            if (null == applications) {
   
                logger.debug("No applications are defined for region {}, so returning an empty instance list for vip "
                        + "address {}.", regio……n, vipAddress);
                return Collections.emptyList();
            }
        }
        // 根据虚拟主机名获取与之关联的实例列表。
        if (!secure) {
   
            return applications.getInstancesByVirtualHostName(vipAddress);
        } else {
   
            return applications.getInstancesBySecureVirtualHostName(vipAddress);

        }
    }

通过1-3步,我们知晓了Ribbon是如何获取可用的服务实例列表的。
那么,最新的服务实例列表是如何更新的呢。答案是可调度线程

通常情况下,DynamicServerListLoadBalancer 使用一个后台任务(通过 PollingServerListUpdater)定期调用 updateListOfServers 方法,以保持服务实例列表的最新状态。

public PollingServerListUpdater(long initialDelayMs, long refreshIntervalMs) {
   
        this.isActive = new AtomicBoolean(false);
        this.lastUpdated = System.currentTimeMillis();
        this.initialDelayMs = initialDelayMs;
        this.refreshIntervalMs = refreshIntervalMs;
	}

这个过程通常是由 PollingServerListUpdater 类中的 start() 方法启动的,该方法会定期触发更新操作。

this.scheduledFuture = getRefreshExecutor()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

coding侠客

一起充电,一起成长。

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

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

打赏作者

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

抵扣说明:

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

余额充值