AVOS Cloud 实时通讯服务架构:微服务和服务发现

「微服务」 (Microservice) 是今年特别热的一个概念,Martin Fowler 的文章 对微服务做了详细的介绍。简而言之,微服务鼓励用户把功能拆分以细粒度的服务接口暴露出来,并经过 REST 服务或轻量级消息队列集成。在微服务架构里,一个业务的实现,可能由不一样的功能单元组合而实现。html

在 AVOS Cloud,咱们提供数据存储、统计、实时通讯等不一样功能的服务,在实现上,这些功能须要共用基础设施,有的服务自己也根据业务性质的不一样拆分功能模块,咱们目前就是以这种「微服务」架构思路来实现拆分。有句话说,if you cannot split, you cannot scale.git

以实时通讯服务为例,根据功能角色的不一样,咱们有这样一些模块:github

  • Push 服务:处理推送的订阅关系,触发推送
  • 长链接服务器:维持设备与服务的长链接
  • Router:应用层的 lookup,负责分配合适的长链接服务器给新设备
  • WatchDog:从多台长链接服务器收集运行和统计数据,对异常状况发起报警
  • 数据存储:群组数据,用户能够经过 API 访问
  • HBase:消息记录存储

模块间的集成,根据业务的特性分别使用 Slacker 远程调用框架和 Kestrel 消息队列。
对于可能耗时较大的任务,咱们经过 Kestrel 队列放到后台执行,避免阻塞前台服务,影响吞吐量。而另外一些须要实时的集成,则使用 Slacker 远程调用实现多个进程间的通讯。apache

Slacker 是一个专门为 Clojure 语言设计的远程调用框架,利用 Slacker 你能够暴露一个 或多个 Clojure 的 namespace 供远程调用。在客户端,Slacker 利用 Clojure 宏 的特性,保持远程调用和本地调用的代码彻底一致,这样本地和远程调用的切换只要更改一个 (require) 便可实现,把框架对业务代码的侵入降到最低。此外,Slacker 使用二进制序列化 nippy,在网络链接层面使用异步复用,同时在超时方面也作了良好的控制。服务器

以上的基础设施帮助咱们良好地拆分模块,为下一步的扩展提供了可能。网络

服务发现

长链接服务器是实时通讯的功能核心,它的瓶颈在内存和 CPU,能够经过增长部署来达到线性扩展。随着业务量的增长和硬件资源的整合,它可能会面临较频繁的部署变化,另外它也须要有能经过新增部署来快速平滑高峰压力的能力。基于 Pub/Sub 抽象 的消息队列对此有良好的支持,但这对咱们以 RPC 为核心的集成方式提出了新的要求,依赖模块也能快速响应服务部署的变化:咱们不可能在新增某个服务部署后修改每一个依赖的配置再逐一重启。架构

在这方面,咱们利用了 Slacker Cluster 框架 。他的核心思想是在部署和服务间增长一层抽象:对于服务的消费者而言,只需声明本身所依赖的服务,而无需静态地了解进程的地址。框架

全部的服务提供者将本身可以提供的服务注册在 Zookeeper 集群里,并将部署地址注册为 Ephemeral 节点。Ephemeral 节点在建立它的链接断后会自动删除,这样当一个部署下线后,它相应的节点也会自动删除。运维

# Zookeeper 目录结构
ls /slacker/example-cluster/namespaces/
[my.serviceA, my.serviceB]

ls /slacker/example-cluster/namespaces/my.serviceA
[192.168.1.100:2104, 192.168.1.101:2014...]

全部服务的客户端会 watch 本身感兴趣的 Zookeeper 节点,而部署变化时,全部的客户端都会获得通知,进而刷新服务列表,将流量引向新的节点。异步

在实时通讯服务中,Router 服务会经过这个 RPC 机制轮询全部在线的长链接服务器,记录他们实时的运行状态。全部的用户设备并不是直接链接到固定的长链接服务器,而是先询问 Router,由后者分配一台压力较轻的实例。当有新的长链接服务器部署后,Router 收到通知,新的链接将优先链接这个新进程。此外,监控和数据收集的服务也会自动地把新实例加入管理范围。

有了这样一套服务发现机制,咱们就能够对整个架构中的任意模块随时增减部署,保证服务能够以健康的状态运行。将来,咱们还会集成云主机的提供商的 API,来实现基础设施的自动化:当系统压力达到阀值时,云主机自动分配新的资源自动开机,jenkins 自动部署,加上现有的服务发现机制,实现 0 手工操做。这将是云服务运维的新篇。

相关文章
相关标签/搜索