RPC实现原理之核心技术-路由与负载均衡

  1. 为什么要采用路由?

    真实的环境中一般是以集群的方式提供服务,但对于服务调用方来说,一个接口会有多个服务提供方同时提供服务,所以 RPC 在每次发起请求的时候,都需要从多个服务节点里面选取一个用于处理请求的服务节点

    每次上线应用的时候都不止运行一台服务器实例,上线就会涉及到变更,只要变更就可能导致原本正常运行的节点出现异常,尤其是发生重大变动或升级的时候,导致应用服务的不稳定因素就很多。

    为减少这种风险,一般会选择灰度方式发布应用实例,比如可以先发布部分实例观察是否存在异常,后续再根据使用的情况,选择发布更多实例或是回滚已经上线的实例。

    但这种方式也会存在缺陷,线上一旦出现问题,还是会有一定影响。对于我们的服务提供方来说,服务会同时提供给很多的调用方来调用,尤其像一些基础性的服务,调用会更加频繁复杂,比如商品、价格等等,一旦线上实例有问题,将会导致所有的调用方业务受到影响。

    如何减少上线变更导致的风险?这就需要在RPC应用中增加路由功能。

  2. 如何实现路由?

    基于上面所讲述的问题,是不是可以在上线完成之后,先让一小部分的调用请求进行逻辑验证,待没问题后再接入其他的服务节点,从而实现流量隔离的效果。那么在 RPC 框架里面该具体如何实现呢?

    1)服务注册发现方式:

    如果通过服务发现的方式来隔离调用方的请求,从逻辑上看是可行,但注册中心在 RPC 里面的作用是用来存储数据并保证数据的一致性。如果把这种复杂的计算逻辑放到注册中心内,当集群节点变多之后,就会导致注册中心压力很大,而且大部分情况下我们是采用开源软件来搭建注册中心,还需要进行二次开发。所以从实际的角度出发,通过服务发现方式来实现请求隔离并不理想。

    2)RPC路由策略:

    在 RPC 发起请求的时候,有一个步骤就是从服务提供方节点集合里面选择一个合适的节点(负载均衡),那么就可以在选择节点前再加上一个“筛选逻辑”,把符合我们要求的节点筛选出来。这个就是路由策略:

    接收请求–>请求校验–>路由策略–>负载均衡–>

    常见的有IP 路由策略,用于限制哪些可以调用服务方的客户端 IP。使用了 IP 路由策略后,整个集群的调用拓扑如下图所示:

    file

    有了 IP 路由之后,上线过程中就可以只让部分请求调用到新上线的实例,相对传统的灰度发布方式来讲,这样做我们可以把试错成本降到最低。

    但有些场景下,可能还需要更细粒度的路由方式,比如说根据SESSIONID要落到相同的服务节点上以保持会话的有效性,某个商品的请求都采用同一个服务节点处理,那么IP路由的方式就不能满足我们的要求, 这个时候就可以采用参数化路由

    file

    相比 IP 策略路由,参数路由支持的灰度粒度更小,这也是一个服务治理的手段。灰度发布功能是 RPC 路由功能的一个典型应用场景,通过 RPC 路由策略的组合使用可以让服务提供更加灵活地管理、合理分配流量,进一步降低上线可能导致的风险。

  3. RPC框架中的负载均衡

    RPC 的负载均衡是由 RPC 框架自身提供实现,RPC 的服务调用方会与“注册中心”下发的所有服务节点建立长连接,在每次发起 RPC 调用时,服务调用方都会通过配置的负载均衡插件,自主选择一个最佳的服务节点,发起 RPC 调用请求。

    file

    RPC 负载均衡策略一般包括轮询、随机、权重、最少连接等。其中随机,轮询策略应该属最常用的策略,Dubbo默认就是使用随机负载均衡策略,这些策略基本可以保证每个节点接收到的请求流量是平均的;同时我们还可以通过控制节点权重的方式,来进行流量控制。比如默认每个节点的权重都设为 100,但我们把其中的一个节点的权重更改为50 时,它接收到的流量就是其他节点的 一半。

  4. 自适应的负载均衡策略

    RPC 的负载均衡完全由 RPC 框架自身实现,服务调用方发起请求时,会通过所配置的负载均衡组件,自主地选择合适服务节点。调用方如果能知道每个服务节点处理请求的能力,再根据服务节点处理请求的能力来判断分配相应的流量,集群资源就能够得到充分的利用, 当一个服务节点负载过高或响应过慢时,就少给它发送请求,反之则多给它发送请求。这个就是自适应的负载均衡策略。

    具体如何实现?

    这就需要判定服务节点的处理能力, 服务调用方收集与之建立长连接的每个服务节点的指标数据,比如服务节点的负载指标、CPU 核数、内存大小、请求处理的耗时指标、服务节点的状态指标(CPU/内存占用率)。通过这些指标,计算出一个分数,比如总分 100 分,如果 CPU 负载达到 80%,就减它 10分,内存负载达到80%,再减10分,以此类比,需要减多少分是需要一个合理依据的计算策略。

    file

    主要步骤:

    (1)添加计分器和指标采集器,将其作为自适应负载均衡算法的组件,用于采集记录服务节点的状态, 并且评定相应的分数。

    (2)指标采集器收集服务节点 CPU 核数、CPU 负载以及内存占用率等指标,还包括请求耗时等数据,通过服务调用方与服务提供方的心跳数据来获取。

    (3)可以配置开启哪些指标采集器,并设置这些参考指标的具体权重,再根据指标的实际数据和权重来综合打分。

    (4)通过对服务节点的综合打分,最终计算出服务节点的实际权重,之后服务调用方会根据相应的路由策略,来选择合适的服务节点。

  5. Dubbo路由负载源码剖析:

    调用路径:

    AbstractClusterInvoker.invoke() -> AbstractClusterInvokerd.doInvoke() ->AbstractInvoker.invoke()

    源码剖析:

    1. AbstractClusterInvoker.invoke方法:
    	@Override
        public Result invoke(final Invocation invocation) throws RpcException {
            checkWhetherDestroyed();
    
            // 给调用方绑定传递的附加信息	
            Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
            if (contextAttachments != null && contextAttachments.size() != 0) {
                ((RpcInvocation) invocation).addAttachments(contextAttachments);
            }
    
            List<Invoker<T>> invokers = list(invocation);
            // 初始化负载均衡策略
            LoadBalance loadbalance = initLoadBalance(invokers, invocation);
            RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
            return doInvoke(invocation, invokers, loadbalance);
        }
    

    最后调用的doInvoke是一个抽象方法,该方法主要是负责Dubbo集群调用容错不同策略的具体实现:

    protected abstract Result doInvoke(Invocation invocation, List<Invoker<T>> invokers,
                                           LoadBalance loadbalance) throws RpcException;
    

    Dubbo默认采用的是FailoverClusterInvoker策略。

    1. FailoverClusterInvoker.doInvoke方法:
    public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
    ...
        // 选择具体的负载策略,Dubbo支持轮询、随机、权重、最少连接策略,默认采用的是随机策略
        Invoker<T> invoker = select(loadbalance, invocation, copyInvokers, invoked);
        ...
        // 根据负载策略获取具体的执行节点, 处理调用请求    
        Result result = invoker.invoke(invocation);
    ...    
    }
    

    通过上述源码剖析, 我们就可以在Dubbo中实现AbstractLoadBalance的doSelect接口,自定义扩展实现自适应权重负载均衡策略,充分发挥RPC服务集群的资源,提升整体性能。


本文由mirson创作分享,如需进一步交流,请加QQ群:19310171或访问www.softart.cn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

麦神-mirson

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

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

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

打赏作者

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

抵扣说明:

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

余额充值