资讯专栏INFORMATION COLUMN

babel: yet another rpc, but far beyond rpc(中)

gityuan / 1122人阅读

摘要:前两种的方式毕竟会多几跳中转,但在路由的灵活性和通讯语义的提供更丰富的选择,而且在大数据量的处理上,吞吐量和平均延时并不会比直连差很多。跨机房的通信和本机房的通信有所不同本地机房的通信讲究高吞吐量,类访问会要求低延时。

(图片源自网络)

2 架构描述 简单架构

从之前的描述,已经可以看出我们会采用RPC over MQ的方式做底层实现,类似方法调用的通信语义会在client和server两端的库中作封装。

从后端实现来说,我们用三套后端来满足不同的场景:

1、对大中型分布式系统环境,rabbitmq是非常非常好的支撑。本来以为需要自己做很多工作,但深入了解rabbitmq,尤其是其支持的amqp协议,发现其实前人在很多思路方面已经栽好树了,比如一致性hash和跨机房等功能,都有相应的插件支撑。
所以,rabbitmq成为babel的第一选择,可以实现我们规划功能的全集,我们的SAAS平台都是使用的rabbitmq。

2、对少量机器而言,redis提供了非常轻量级的队列支持,可以提供有限但必要的功能。
redis没有类似amqp这样的协议,需要手动作些封装。我们在单机环境使用redis,尽可能减少部署和运维的开销。

3、对性能有苛刻要求的可以用zeromq后端去做tcp直连。前两种mq的方式毕竟会多几跳中转,但在路由的灵活性和通讯语义的提供更丰富的选择,而且在大数据量的处理上,吞吐量和平均延时并不会比直连差很多。
但为了满足特殊环境的需要,我们预留了zeromq的实现选择,最近由于新的需求,正在准备完成这块拼图。zeromq的缺点在于需要中央配置系统来帮忙完成路由功能。

每种后台实现对使用者透明,可以通过配置进行透明切换,但是有些高级通信语义redis和zeromq不支持。

如果对应到web service 三要素:

UDDI:传统的rpc或者SOA都是去注册中心发现远端对象,然后客户端主动推送数据到服务端。mq的方式帮我们省却了自注册(订阅实现)和服务发现(mq自己路由)的问题。

WSDL:目前我们通过json的方式来描述rpc的service端,包括机房所在地,持久化,超时等等。

SOAP:目前使用json的方式,我们定义了一个统一的Event对象来封装一些固定属性,其他都在一个map中。由业务代码自己去打包拆包。当然这种方式在大团队中不适合。

通讯语义封装

大量的工作可以利用mq来实现,我们的工作主要体现在通讯语义的封装。

❶ client端访问模式语义

queue语义(消息有去无回):传统的数据输送。

简单rpc(消息一去一回):传统的rpc和soa都适用于此场景。

轮询rpc(消息一去多回):一个request出去,多个response回来,适合于轮询下游节点的场景。

分布式存储rpc(一个request消息,只要有最小条件的response消息就返回):适合于分布式场景下的读写。例如三个拷贝,需要至少两份读成功或者至少两份写成功,等等。目前此方式我们还没有用到。

❷ 消息分发语义(实际上这里的行为参考了storm的部分功能)

Shuffle:一个消息,会有多个接收者,这些接收者根据自己的资源情况去抢占同一来源的消息,达到load balance的目的。实际上我们通过shuffle来做集群功能,省掉了LB的引入。而且性能强的拉多点,性能弱的拉少点,变相的实现了根据消费者的性能来做分发。

Sharding:与shuffle类似,也是多个consumer来分享消息,不过根据消息的key,保证在拓扑环境不发生改变的情况下,同一个key始终指向同一个消费者,为后续分布式系统的搭建打下基础

topic语义:所有消费者都会得到消息的一个拷贝。常见的mq语义

topic+shffule:一组消费者作为一个整体来订阅topic,得到所有的消息,每个订阅团体内部通过shuffle的形式去分摊。这种非常适合用大数据环境下,有不同类型的数据消费者,每一个类型的消费者有各自的实例数。

topic+sharding:一组消费者作为一个整体来订阅topic,得到所有的消息,每个订阅团体内部通过sharding的形式去分摊。类似于topic shuffle,只是换用了sharding这种更严格的语义。

❸ 数据的封装语义。用于指定babel上承载数据的特征,例如:

batch operation:用于指定是否进行批处理传递。

Security:暂无使用。

Compressing:指定payload压缩方法,目前只做了gzip。

机房:指定了机房所在地,框架会根据生产者和消费者的不同自动做跨机房的处理。

持久化:指定在无消费者的情况下,是否需要持久化存储,以及最大大小。

超时:指定消息的最大有效时间,超过的消息将会被丢弃。

其他。

对于以上的通讯语义,首先需要去底层的mq基础里面找到相对应的设施来做封装,比如对于queue语义作个简单举例:

而对于像rpc,轮询,以及其他功能,则需要相应的代码来支撑,比如:

response的返回可以通过client监听queue来实现

response和request的串联可以通过自定义的requestid来实现

轮询可以通过client 端等待多个消息返回,可以用condition来做同步

……

这里有不少细节,暂不在本文中进行展开了。

跨语言

由于几种mq都有python和java的客户端,所以我们工作会轻松很多,只是同样的逻辑需要写两份,好处还是很明显的,使得我们的系统语言无关,方便根据当前人员的技能情况来分配开发任务。
不过这里不得不吐槽python的并发,虽然有心理准备,没想到是如此之差。当使用多线程的时候,性能下降的厉害,比java要差两个数量级,所以我们python版做了同步(多线程),异步(协程)两个版本。异步版本的性能尚可接受;我们已经准备在build自己的异步python框架,来覆盖我们的应用程序。

跨机房通信

Babel的一大特色是跨机房通信,来帮助我们解决不同数据中心的通信问题,使得业务开发人员只用关心其所负责的业务即可。跨机房的通信和本机房的通信有所不同:

本地机房的通信讲究高吞吐量,rpc类访问会要求低延时。

跨机房通信必须应对复杂的网络情况,要求数据不丢,rpc类通信可以接受相对较高的延时。

实现上,我们利用了federation插件,当rpc框架发现存在跨机房访问时,会自动启用相应的路由,下图是同事画的两种情况下的路由,绿线是本地调用,红线是跨机房调用。

对于业务应用而言,使用上是基本透明的,借助于mq的中转,在多机房环境下它也可以玩转除数据推送外的RPC类访问语义。

3 实战举例 实例

1 分布式数据计算平台

首先是我们的私有化大数据平台warden。warden集数据采集、转换、分发、实时分析和展示等功能于一体,希望从客户的原始网络流量中找出异常点和风险事件。

此图是一个warden分布式版本的草图:

采集的数据通过topic sharding类分配给不同类型的消费者,比如ES writer,Mysql writer,实时分析引擎;每种消费者可以有不同的实例数。

实时计算引擎通过sharding来分摊流量,达到scale out的效果。

rule引擎需要数据的时候同样通过简单的sharding的rpc就可以获得相应的数据了。

规则引擎的结果可以通过topic来进行再分发。

目前只有实时引擎是java的,因为性能要求苛刻,其他模块采用python开发。

上图只是个例子,来简要说明babel是如何支撑一个分布式数据计算系统的。实际的系统使用了更多的语义,也更加的复杂。不过借助于Babel的协助,整个系统在实现和运维上已经很大程度上减轻了复杂程度。

2 水平扩展的web系统

第二个例子是我们曾经做过的SAAS平台私有化案例,是我们早期SAAS平台的极简版本。

图画的略凌乱了些:

系统主架构是用haproxy做负载均衡,发到我们的两台主机上。

两台主机内部完全相同,右边主机内部组件没有画全。

每台主机有内部的nginx,load balance到本机器内部的诸多python web server 上。

python web server直接读取本地的nosql数据库。

写数据时,由于写请求sharding到两台机器上,所以我们有个topic的service来处理nosql数据写入,保证每个写入操作都写到两台机器上,每台机器的nosql始终存有全量的最新数据。

由于客户要求落地关系型数据库,所以通过shuffle再将写请求分散开,统一写入mysql中。

在这个系统中,我们成功的利用babel建立了自己的一致性框架,从而避免了去使用db做数据一致性;同时由于对等的服务器架构,在部署维护上省掉了很多事情。

框架运维

整个框架,我们都准备了统一的metrics体系去做监控和报警(实际上metrics系统本身的跨机房属性反而是通过babel来实现),详尽的监视了RPC的某个环节,之前有过我们监控的文章,这里就不重复了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/45549.html

相关文章

  • babel: yet another rpc, but far beyond rpc(下)

    摘要:研发通讯框架,以及其支撑的其他框架,比如监控报警等。这个是最重要的角色。目前的配置与分发还不能做到自动化,有手工工作量。完成自动化发布部署,将整个系统做一个统一的整体。研究弹性伸缩方面的非功能性扩展。考虑增加熔断等自我保护机制。 showImg(https://segmentfault.com/img/bVQ2BQ?w=400&h=277); (图片源自网络) 4框架生态 实际上,在做...

    chenatu 评论0 收藏0
  • 简易RPC框架:基于 netty 的协议编解码

    摘要:概述在简易框架需求与设计这篇文章中已经给出了协议的具体细节,协议类型为二进制协议,如下协议的解码我们称为,编码我们成为,下文我们将直接使用和术语。直接贴代码,参考前文提到的协议格式阅读以下代码协议编码器 概述 在《简易RPC框架:需求与设计》这篇文章中已经给出了协议的具体细节,协议类型为二进制协议,如下: ---------------------------------------...

    Loong_T 评论0 收藏0

发表评论

0条评论

gityuan

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<