白杨 2019-03程序员
baiy.cn算法
Copyright (C) 2016 - 2019 Bai Yang, baiy.cn / baiyang.name, baiyang@gmail.com, All Rights Reserved数据库
AIO vs. SOA后端
长久以来,服务器端的高层架构大致被区分为对立的两类:SOA(Service-oriented architecture)以及 AIO(All in one)。SOA 将一个完整的应用分割为相互独立的服务,每一个服务提供一个单一标准功能(如:会话管理、交易评价、用户积分等等)。服务间经过 RPC、WebAPI 等 IPC 机制暴露功能接口,并以此相互通讯,最终组合成一个完整的应用。api
而 AIO 则相反,它将一个应用规约在一个独立的总体中,SOA 中的不一样服务在 AIO 架构下呈现为不一样的功能组件和模块。AIO应用的全部组件一般都运行在一个地址空间(一般是同一进程)内,全部组件的代码也经常放在同一个产品项目中一块儿维护。缓存
AIO 的优点是部署简单,不须要分别部署多个服务,并为每一个服务实现一套高可用集群。与此同时,因为可避免网络传输、内存拷贝等 IPC 通讯所带来的大量开销,所以 AIO 架构的单点效率一般远高于 SOA。服务器
另外一方面,因为 AIO 架构中组件依赖性强,组件间常常知晓并相互依赖对方的实现细节,所以组件的可重用性及可替换性差,维护和扩展也较困难。特别是对于刚加入团队的新人来讲, 面对包含了大量互相深度耦合之组件和模块的"巨型项目",经常须要花费大量努力、经历不少挫折而且犯不少错误才能真正接手。而即便对于老手来讲,因为模块 间各自对对方实现细节错综复杂的依赖关系,也容易发生在修改了一个模块的功能后,莫名奇妙地影响到其它看起来绝不相干功能的状况。微信
与此相反,SOA 模型部署和配置复杂——现实中,一个大型应用经常被拆分为数百个相互独立的服务,《程序员》期刊中的一份公开发表的论文显示,某个国内 "完全拥抱" SOA 的著名(中国排名前5)电商网站将他们的 Web 应用拆分红了一千多个服务。能够想象,在多活数据中心的高可用环境内部署成百上千个服务器集群,而且配置他们彼此间的协做关系是多大的工做量。最近的协程网络瘫痪事件也是由于上千个服务组成的庞大 SOA 架构致使故障恢复缓慢。网络
除了部署复杂之外,SOA 的另外一个主要缺点就是低效——从逻辑流的角度看,几乎每次来自客户端的完整请求都须要依次流经多个服务后,才能产生最终结果并返回用户端。而请求(经过消息中间件)每"流经"一个服务都须要伴随屡次网络 IO 和磁盘访问,多个请求可累计产生较高的网络时延,使用户请求的响应时间变得不可肯定,用户体验变差,并额外消耗大量资源。数据结构
混乱的SOA 依赖关系(图片来自互联网)
此外,不管是每一个 Service 各自链接不一样的 DBMS 仍是它们分别接入同一个后端分布式 DBMS 系统,实现跨服务的分布式事务支持工做都要落到应用层开发者手中。而分布式事务(XA)自己的实现复杂度恐怕就以超过大部分普通应用了,更况且还须要为分布式事务加上高可靠和高可用保证——须要在单个数据切片上使用 Paxos/Raft 或主从+Arbiter之类的高可用、强一致性算法,同时在涉及多个数据切片的事务上使用 2PC/3PC 等算法来保证事务的原子性。所以 SOA 应用中的跨 Service 事务基本都只能退而求其次,作到最终一致性保证,即使如此,也须要增长大量的额外工做——在稍微复杂点的系统里,高可用,并能在指定时间内可靠收敛的最终一致性算法实现起来也不是那么容易。
与此同时,大部分 SOA 系统还常常须要使用消息中间件来实现消息分发服务。若是对消息中间件的可用性(部分节点故障不会影响正常使用)、可靠性(即便在部分节点故障时,也确保消 息不丢失、不重复、并严格有序)、功能性(如:发布/订阅模型、基于轮转的任务分发等)等方面有所要求的话,那么消息中间件自己也容易成为系统的瓶颈。
SOA 架构的优势在于其高内聚、低耦合的自然特性。仅经过事先约定的 IPC 接口对外提供服务,再配合服务间隔离(一般是在独立节点中)运行的特质,SOA 架构划分出了清晰的接口和功能边界,所以能够被很是容易地重用和替换(任何实现了兼容IPC接口的新服务均可替换已有的老服务)。
从软件工程和项目管理的视角来看,因为每一个服务自己一般有足够高的内聚性,而且单个服务实现的功能也较独立,所以相对于 AIO 意大利面式的,相互交织的结构来讲,SOA 的服务很是便于维护——负责某一服务的开发人员只须要看好本身这一亩三分地便可,只要保持服务对外提供的 API 没有发生不兼容的变化,就不须要担忧修改代码、替换组件等工做会影响到其它"消费者"。
同时,由多个独立服务所组成的应用也更容易经过加入新服务和从新组合现有服务来进行功能变动和扩展。
μSOA 架构
在经历了大量实际项目中的权衡、思索和实践后,我逐步定义、实现和完善了可以兼二者之长的 "μSOA"(Micro SOA)架构。在 μSOA 架构中,独立运行的服务被替换成了支持动态插拔的跨平台功能插件(IPlugin);而插件则经过(并仅可经过)API Nexus 来动态地暴露(注册)和隐藏(注销)自身所提供的功能接口,同时也使用 API Nexus 来消费其它插件提供服务。
μSOA 彻底继承了 SOA 架构高内聚、低耦合的优势,每一个插件如独立的服务同样,有清晰的接口和边界,可容易地被替换和重用。在可维护性上,μSOA 也与 SOA 彻底一致,每一个插件均可以被单独地开发和维护,开发人员只须要管好本身维护的功能插件便可。经过加入新插件以及对现有功能插件的从新组合,甚至可比 SOA 模式更容易地对现有功能进行变动和扩展。
而在性能方面,因为全部功能插件都运行在同一个进程内,所以经过 API Nexus 的相互调用不须要任何网络 IO、磁盘访问和内存拷贝,也没有任何形式的其它 IPC 开销,所以其性能和效率都可与 AIO 架构保持在相同量级。
与此同时,μSOA 的部署与 AIO 一样简单——部署在单个节点便可使用,只需部署一个集群便可实现高可用和横向扩展。在配置方面也远比 SOA 简单,仅须要比 AIO 应用多配置一个待加载模块列表而已,而且这些配置也可经过各类配置管理产品来实现批量维护。简单的部署和配置过程不但简化了运营和维护工做,也大大方便了开发和测试环境的构建。
此外,μSOA 也在极大程度上避免了对消息中间件的依赖,取而代之的是经过 API Nexus 的直接API调用;或是在须要削峰填谷的场合中,使用由内存零拷贝和无锁算法高度优化的线程间消息队列。这一方面大大增长了吞吐,避免了延迟,另外一方面也避免了部署和维护一个高可用的消息分发服务集群所带来的巨大工做量——μSOA 集群内的节点间协做和协调通讯需求已被将至最低,对消息分发的可靠性、可用性和功能性都没有过高要求。在多数状况下,使用 Gossip Protocol 等去中心化的 P2P 协议即足以知足须要,有时甚至能够彻底避免这种集群内的节点间通讯。
从 μSOA 的角度看,也能够将 DBC 视做一种几乎全部服务器端应用都须要使用的基础功能插件,因为其经常使用性,所以他们被事先实现并加进了 libapidbc 中。由此,经过提供 IPlugin、API Nexus 以及 DBC 等几个关键组件,libapidbc 为 μSOA 架构奠基了良好的基础设施。
固然,μSOA 与 SOA 和 AIO 三者间并非互斥的选择。在实际应用场景中,能够经过三者间的有机组合来达成最合理的设计。例如:对于视频转码等很是耗时而且不须要同步等待其完成并返回结果的异步操做来讲,因为其绝大部分开销都耗费在了视频编解码计算上,所以将其做为插件加入其它 App Server 就彻底没有必要,将它做为独立的服务,部署在配置了专用加速硬件的服务器集群上应该是更好的选择。
消息端口交换服务
白杨消息端口交换服务(BYPSS)设计用于单点支撑百亿量级端口、十万量级节点规模,每秒处理百万至千万量级消息的高可用、强一致、高性能分布式协调和消息交换服务。其中关键概念包括:
端口交换服务对外提供的 API 原语包括:
端口交换服务的客户端链接分为如下两类:
与传统的分布式协调服务以及消息中间件产品相比,端口转发服务主要有如下特色:
可见,白杨消息端口转发服务自己是一个集成了故障检测、服务选举、服务发现和分布式锁等分布式协调功能的消息路由服务。它经过牺牲极端条件下的可靠性,在保证了 强一致、高可用、可伸缩(横向扩展)的前提下,实现了极高的性能和并发能力。
能够认为消息端口交换服务就是为 μSOA 架构量身定作的集群协调和消息分发服务。μSOA 的主要改进即:将在 SOA 中,每一个用户请求均须要牵扯网络中的多个服务节点参与处理的模型改进为大部分用户请求仅须要同一个进程空间内的不一样 BMOD 参与处理。
这样的改进除了便于部署和维护,以及大大下降请求处理延迟外,还有两个主要的优势:
在此前提下,消息端口交换服务以容许在极端状况下丢失少许将来得及转发的消息为代价,来避免磁盘写入、主从复制等低效模式,以提供极高效率。这对 μSOA 来讲是一种很是合理的选择。
极端条件下的可靠性
传统的分布式协调服务一般使用 Paxos 或 Raft 之类基于多数派的强一致分布式算法实现,主要负责为应用提供一个高可用、强一致的分布式元数据 KV 访问服务。并以此为基础,提供分布式锁、消息分发、配置共享、角色选举、服务发现、故障检测等分布式协调服务。常见的分布式协调服务实现包括 Google Chubby(Paxos)、Apache ZooKeeper(Fast Paxos)、etcd(Raft)、Consul(Raft+Gossip)等。
Paxos、Raft 等分布式一致性算法的最大问题在于其极低的访问性能和极高的网络开销:对这些服务的每次访问,不管读写,都会产生至少三次网络广播——以投票的方式确 定本次访问通过多数派确认(读也须要如此,由于主节点须要确认本次操做发生时,本身仍拥有多数票支持,还是集群的合法主节点)。
在实践中,虽可经过下降系统总体一致性或加入租期机制来优化读操做的效率,但其整体性能仍十分低下,而且对网络 IO 有很高的冲击:Google、Facebook、Twitter 等公司的历次重大事故中,不少都是因为发生网络分区或人为配置错误致使 Paxos、Raft 等算法疯狂广播消息,导致整个网络陷入广播风暴而瘫痪。
此外,因为 Paxos、Raft 等分布式一致性算法对网络 IO 的吞吐和延迟等方面均有较高要求,而链接多座数据中心机房(IDC)的互联网络一般又很难知足这些要求,所以致使依赖分布式协调算法的强一致(抗脑裂)多活 IDC 高可用集群架构难以以合理成本实现。做为实例:2015 年 8 月 20 日 Google GCE 服务中断 12 小时并永久丢失部分数据;2015 年 5 月 27 日和 2016 年 7 月 22 日支付宝两次中断数小时;2013 年 7 月 22 日微信服务中断数小时;以及 2017 年 5 月英国航空瘫痪很多天等重大事故均是因为单个 IDC 因市政施工(挖断光纤)等缘由下线,同时未能成功构建多活 IDC 架构,所以形成 IDC 单点依赖所致使的。
前文也已提到过:因为大部分采用 SOA 架构的产品须要依赖消息中间件来确保系统的最终一致性。所以对其可用性(部分节点故障不会影响正常使用)、可靠性(即便在部分节点故障时,也确保消息不丢 失、不重复、并严格有序)、功能性(如:发布/订阅模型、基于轮转的任务分发等)等方面均有较严格的要求。这就必然要用到高可用集群、节点间同步复制、数 据持久化等低效率、高维护成本的技术手段。所以消息分发服务也经常成为分布式系统中的一大主要瓶颈。
与 Paxos、Raft 等算法相比,BYPSS 一样提供了故障检测、服务选举、服务发现和分布式锁等分布式协调功能,以及相同等级的强一致性、高可用性和抗脑裂(Split Brain)能力。在消除了几乎所有网络广播和磁盘 IO 等高开销操做的同时,提供了数千、甚至上万倍于前者的访问性能和并发处理能力。 可在对网络吞吐和延迟等方面无附加要求的前提下,构建跨多个 IDC 的大规模分布式集群系统。
与各个常见的消息中间件相比,BYPSS提供了一骑绝尘的单点百万至千万条消息每秒的吞吐和路由能力——一样达到千百倍的性能提高,同时保证消息不重复和严格有序。
然而天下没有免费的午饭,特别是在分布式算法已经很是成熟的今天。在性能上拥有绝对优点的同时,BYPSS 必然也有其妥协及取舍——BYPSS 选择放弃极端(平均每一年2次,而且大多由维护引发,控制在低谷时段,基于实际生产环境多年统计数据)情形下的可靠性,对分布式系统的具体影响包括如下两方面:
综上所述,能够认为 BYPSS 服务就是为 μSOA 架构量身定作的集群协调和消息分发服务。BYPSS 和 μSOA 架构之间造成了扬长避短的互补关系:BYPSS 以极端条件下系统总体性能的轻微波动为代价,极大提高了系统的整体性能表现。适合用来实现高效率、高可用、高可靠、强一致的 μSOA 架构分布式系统。
BYPSS特性总结
BYPSS 和基于 Paxos、Raft 等传统分布式一致性算法的分布式协调产品特性对好比下:
特性 | BYPSS | ZooKeeper、Consul、etcd… |
可用性 | 高可用,支持多活 IDC | 高可用,支持多活 IDC |
一致性 | 强一致,主节点经过多数派选举 | 强一致,多副本复制 |
并发性 | 千万量级并发链接,可支持数十万并发节点 | 不超过 5000 节点 |
容量 | 每 10GB 内存可支持约 1 亿消息端口;每 1TB 内存可支持约 100 亿消息端口;两级并发散列表结构确保容量可线性扩展至 PB 级。 | 一般最高支持数万 KV 对。开启了变动通知时则更少。 |
延迟 | 相同 IDC 内每次请求延迟在亚毫秒级(阿里云中实测为 0.5ms);相同区域内的不一样 IDC 间每次请求延迟在毫秒级(阿里云环境实测 2ms)。 | 因为每次请求须要至少三次网络广播和屡次磁盘 IO,所以相同 IDC 中的每操做延迟在十几毫秒左右;不一样 IDC 间的延迟则更长(详见下文)。 |
性能 | 每 1Gbps 网络带宽可支持约 400 万次/秒的端口注册和注销操做。在 2013 年出厂的入门级至强处理器上,每核心可支持约 100 万次/秒的上述端口操做。性能可经过增长带宽和处理器核心数量线性扩展。 | 算法自己的特性决定了没法支持批量操做,不到 100 次每秒的请求性能(因为每一个原子操做都须要至少三次网络广播和屡次磁盘 IO,所以支持批量操做毫无心义,详见下文)。 |
网络利用率 | 高:服务器端和客户端均具有端口注册、端口注销、消息发送的批量打包能力,网络载荷比可接近 100%。 | 低:每请求一个独立包(TCP Segment、IP Packet、Network Frame) ,网络载荷比一般低于 5%。 |
可伸缩性 | 有:可经过级联的方式进行横向扩展。 | 无:集群中的节点越多(由于广播和磁盘IO的范围更大)性能反而越差。 |
分区容忍 | 无多数派分区时系统下线,但不会产生广播风暴。 | 无多数派分区时系统下线,有可能产生广播风暴引起进一步网络故障。 |
消息分发 | 有,高性能,客户端和服务器均包含了消息的批量自动打包支持。 | 无。 |
配置管理 | 无,BYPSS 认为配置类数据应交由 Redis、MySQL、MongoDB 等专门的产品来维护和管理。固然,这些 CMDB 的主从选举等分布式协调工做仍可由 BYPSS 来完成。 | 有,可看成简单的 CMDB 来使用,这种功能和职责上的混淆不清进一步劣化了产品的容量和性能。 |
故障恢复 | 须要从新生成状态机,但能够数千万至数亿端口/秒的性能完成。实际使用中几无波动。 | 不须要从新生成状态机。 |
上述比较中,延迟和性能两项主要针对写操做。这是由于在常见的分布式协调任务中,几乎所有有意义的操做都是写操做。例如:
操做 | 对服务协调来讲 | 对分布式锁来讲 |
端口注册 | 成功:服务选举成功,成为该服务的属主。 失败:成功查询到该服务的当前属主。 |
成功:上锁成功。 失败:上锁失败,同时返回锁的当前属主。 |
端口注销 | 放弃服务全部权。 | 释放锁。 |
注销通知 | 服务已下线,可更新本地查询缓存或参与服务竞选。 | 锁已释放,可从新开始尝试上锁。 |
上表中,BYPSS 的端口注册对应 ZooKeeper 等传统分布式产品中的“写/建立KV对”;端口注销对应“删除KV对”;注销通知则对应“变动通知”服务。
因而可知,为了发挥最高效率,在生产环境中一般不会使用单纯的查询等只读操做。而是将查询操做隐含在端口注册等写请求中,请求成功则当前节点自身成为属主;注册失败天然会返回请求服务的当前属主,所以变相完成了属主查询( 服务发现/名称解析)等读操做。
须要注意的是,就算是端口注册等写操做失败,其实仍是会伴随一个成功的写操做。由于仍然要将发起请求的当前节点加入到指定条目的变动通知列表中,以便在端口注销等变动事件发生时,向各个感兴趣的节点推送通知消息。 所以写操做的性能差别极大地影响了现实产品的实际表现。
从高性能集群(HPC)的视角来看,BYPSS 与前文所述的传统分布式协调产品之间,最大的区别主要体如今如下两个方面:
因为传统分布式协调服务的性能和容量等限制,在经典的分布式集群中,多以服务或节点做为单位来进行分布式协调和调度,同时尽可能要求集群中的节点工做在无状态模式。服务节点无状态的设计虽然对分布式协调服务的要求较低,但同时也带来了集群总体性能低下等问题。
与此相反,BYPSS 可轻松实现每秒千万次请求的处理性能和百亿至千亿量级的消息端口容量。这就给分布式集群的精细化协做构建了良好的基础。与传统的无状态集群相比,基于 BYPSS 的精细化协做集群可以带来巨大的总体性能提高。
咱们首先以最多见的用户和会话管理功能来讲明:在无状态的集群中,在线用户并没有本身的属主服务器,用户的每次请求均被反向代理服务随机地路由至集群中的任意节点。虽然 LVS、Nginx、HAProxy、TS 等主流反向代理服务器均支持基于 Cookie 或 IP 等机制的节点粘滞选项,但因为集群中的节点都是无状态的,所以该机制仅仅是增长了相同客户端请求会被路由到某个肯定后台服务器节点的几率而已,仍没法提供全部权保证,也就没法实现进一步的相关优化措施。
而得益于 BYPSS 突出的性能和容量保证,基于 BYPSS 的集群能够用户为单位来进行协调和调度(即:为每一个活动用户注册一个端口),以提供更优的总体性能。具体的实现方式为:
与传统架构相比,考虑到无状态服务也须要经过 MySQL、Memcached 或 Redis 等技术来实现专门的用户和会话管理机制,所以以上实现并未增长多少复杂度,可是其带来的性能提高却很是巨大,对好比下:
项目 | BYPSS HPC 集群 | 传统无状态集群 |
1 运维 |
省去用户和会话管理集群的部署和维护成本。 | 须要单独实施和维护用户管理集群,并为用户和会话管理服务提供专门的高可用保障,增长故障点、增长系统总体复杂性、增长运维成本。 |
2 网络 |
几乎全部请求的用户匹配和会话验证工做都得以在其属主节点的内存中直接完成。内存访问为纳秒级操做,对比毫秒级的网络查询延迟,性能提高十万倍以上。同时有效下降了服务器集群的内部网络负载。 | 每次须要验证用户身份和会话有效性时,均须要经过网络发送查询请求到用户和会话管理服务,并等待其返回结果,网络负载高、延迟大。 因为在一个典型的网络应用中,大部分用户请求都须要在完成用户识别和会话验证后才能继续处理,所以这对总体性能的影响很大。 |
3 缓存 |
由于拥有了稳定的属主服务器,而用户在某个时间段内老是倾向于重复访问相同或类似的数据(如自身属性,本身刚刚发布或查看的商品信息等)。所以服务器本地缓存的数据局部性强、命中率高。 相较于分布式缓存而言,本地缓存的优点很是明显:
等等,而后尽可能将属于相同分组的用户优先分配给同一个(或同一组)服务器节点。显而易见,选择合适的用户分组策略可极大提高服务器节点的本地缓存命中率。 这使得绝大部分与用户或人群相关的数据都可在本地缓存命中,不但提高了集群总体性能,还消除了集群对分布式缓存的依赖,同时大大下降了后端数据库的读负载。 |
无专属服务器,用户请求随机到达集群中的任意服务器节点;本地缓存命中率低;各节点重复缓存的内容多;须要以更高的成本为代价依赖分布式缓存。 后端数据库服务器的读压力高,要对其进行分库分表、读写分离等额外优化。 |
4 更新 |
因为全部权肯定,能在集群全局确保任意用户在给定时间段内,均由特定的属主节点来提供服务。再加上现代服务器突发宕机故障的几率也较低。 所以能够将用户属性中频繁变化但重要性或时效性较低的部分缓存在内存中,待积累一段时间后再批量更新至数据库。这可大大下降后端数据库服务器的写压力。 例如:商城系统可能随着用户的浏览(好比每次查看商品)进程,随时收集并记录用户的偏好信息。若每次用户查看了新商品后,都须要即时更新数据库,则负载较高。再考虑到由于服务器偶发硬件故障致使丢失最后数小时商品浏览偏好数据彻底能够接受,所以可由属主节点将这些数据临时保存在本地缓存中,每积累数小时再批量更新一次数据库。 再好比:MMORPG 游戏中,用户的当前位置、状态、经验值等数据随时都在变化。属主服务器一样能够将这些数据变化积累在本地缓存中,并以适当的间隔(好比:每 5 分钟一次)批量更新到数据库中。 这不但极大地下降了后端数据库要执行的请求数量,并且将多个用户的数据在一个批量事务中打包更新也大大减小数据库操做时的磁盘刷新动做,进一步提高了效率。 此外,由专门的属主节点发起对用户属性的更新也避免了无状态集群中多个节点同时请求更新同一对象时的争抢问题,进一步提升了数据库性能。 |
因为用户的每次请求均可能被转发到不一样服务器节点来处理,所以没法实现累积写入优化和批量写入优化。后端数据库的写负担很是重。 存在多个节点争抢更新同一条记录的问题,进一步加剧了数据库负担。 为此要对后端数据库进行额外的分库分表等优化,还会引起“须要由应用层来自行处理分布式事务”等反作用。 |
5 推送 |
因为同一用户发起的全部会话均被集中在同一个属主节点内统一管理,所以可很是方便地向用户推送即时通知消息(Comet)。 若发送消息的对象与消息接收消息的用户处于相同节点,则可直接将该消息推送给收件人麾下的全部活动会话。 不然只需将消息定向投递到收件人的属主节点便可。消息投递可以使用 BYPSS 实现(直接向收件人对应端口发消息,应启用消息批量发送机制来优化),亦可经过专用的消息中间件(如:Kafka、RocketMQ、RabbitMQ、ZeroMQ等)来完成。 若按照本表“项目3”中描述的方法,优先将关联更紧密的用户分配到相同属主节点的话,则可大大提高消息推送在相同节点内完成的几率,此举可显著下降服务器间通讯的压力。 所以咱们鼓励针对业务的实际状况来妥善定制用户分组策略,合理的分组策略可实现让绝大部分消息都在当前服务器节点内本地推送的理想效果。 例如:对游戏类应用,可按地图对象分组,将处于相同地图副本内的玩家交由同一属主节点进行管理——传统 MMORPG 网游中的绝大部分消息推送都发生在同一地图副本内的玩家之间(AOI 范围)。 再好比:对于 CRM、HCM、ERP 等 SaaS 应用来讲,可按照公司来分组,将隶属于相同企业的用户集中到同一属主节点上——很显然,此类企业应用中,近 100% 的通讯都来自于企业内部成员之间。 这样便可实现近乎 100% 的本地消息推送,达到几乎免除了服务器间消息投递的效果,极大地下降了服务器集群的内部网络负载。 |
因为同一用户的不一样会话被随机分配到不一样节点处理,所以须要开发、部署和维护专门的消息推送集群,同时专门确保该集群的高性能和高可用性。 这不但增长了开发和运维成本,并且因为须要将每条消息先投递到消息推送服务后,再由该服务转发给客户端,所以也加剧了服务器集群的内部网络负载,同时也加大了用户请求的处理延迟。 |
6 平衡 |
集群可以使用主被动负载平衡相结合的手段进行调度。 被动平衡:集群中的每一个节点均会按期将其麾下再也不活跃的用户和会话卸载掉,同时批量通知 BYPSS 服务释放这些用户所对应的端口。此算法实现了宏观上的负载平衡(以较长的时间周期来讲,集群是平衡的)。 主动平衡:集群会经过 BYPSS 服务推选出负载平衡协调节点,该节点连续监视集群中各个节点的负载状况,并主动发出指令进行负载调度(如:要求 A 节点将其麾下 5000 位用户的全部权转移给 B 节点)。不一样于宏观层面的被动平衡,主动平衡机制能够在更短的时间片内,以迅捷的反应速度来达成集群的快速配平。 主动平衡一般在集群中的部分节点刚刚从故障中恢复(所以处于空载状态)时效果明显,它比被动平衡反应更加迅速。如:在一个多活 IDC 集群中,某个 IDC 的光缆故障刚刚被修复而恢复上线时。 |
若启用了反向代理中的节点粘滞选项,则其负载平衡性与 BYPSS 集群的被动平衡算法至关。 若未启用反向代理中的节点粘滞选项,则在从故障中恢复时,其平衡性低于 BYPSS 主动平衡集群。与此同时,为了保证本地缓存命中率等其它性能指标不被过度劣化,管理员一般不会禁用节点粘滞功能。 另外,SOA 架构的多个服务间,容易产生负载不平衡,出现一些服务超载,另外一些轻载的状况,μSOA 集群则无此弊端。 |
值得一提的是,这样的精准协做算法并不会形成集群在可用性方面的任何损失。考虑集群中的某个节点因故障下线的状况:此时 BYPSS 服务会检测到节点已下线,并自动释放属于该节点的全部用户。待其用户向集群发起新请求时,该请求会被路由到当前集群中,负载最轻的节点。这个新节点将代替已下线的故障节点,成为此用户的属主,继续为该用户提供服务(见前文中的步骤 2-b-i)。此过程对用户透明,不须要在客户端中加入额外的处理逻辑。
上述讨论以几乎全部网络应用中都会涉及的用户和会话管理功能为例,为你们展现了 BYPSS HPC 集群精细协调能力的优点。但在多数真实应用中,并不仅有用户管理功能。除此以外,应用中一般还会包含可供其用户操做的其它对象。例如在优酷、土豆、youtube 等视频网站中,除了用户之外,至少还有“可供播放的视频”这种对象。
下面咱们就以“视频对象”为例,探讨如何使用 BYPSS 的精细化调度能力来大幅提高集群性能。
在这个假想的视频点播类应用中,与前文描述的用户管理功能相似,咱们首先经过 BYPSS 服务为每一个活动的视频对象选取一个属主节点。其次,咱们将视频对象的属性分为如下两大类:
此外,咱们还规定对视频对象的任何写操做(无论是普通属性仍是动态属性)均必须交由其属主来完成,非属主节点只能读取和缓存视频对象的普通属性,不能读取动态属性,也不能执行任何更新操做。
由此,咱们能够简单地推断出视频对象访问的大致业务逻辑以下:
与经典的无状态 SOA 集群相比,上述设计带来的好处以下:
项目 | BYPSS HPC 集群 | 传统无状态集群 |
1 运维 |
基于全部权的分布式缓存架构,省去 Memcached、Redis 等分布式缓存集群的部署和维护成本。 | 须要单独实施和维护分布式缓存集群,增长系统总体复杂性。 |
2 缓存 |
普通属性的读操做在本地缓存命中,若使用“优先以用户偏好特征来分组”的用户属主节点分配策略,则可极大加强缓存局部性,增长本地缓存命中率,下降本地缓存在集群中各个节点上的重复率。 正如前文所述,相对于分布式缓存而言,本地缓存有消除网络延迟、下降网络负载、避免数据结构频繁序列化和反序列化等优势。 此外,动态属性使用基于全部权的分布式缓存来实现,避免了传统分布式缓存的频繁失效和数据不一致等问题。同时因为动态属性仅被缓存在属主节点上,所以也显著提高了系统总体的内存利用率。 |
无专属服务器,用户请求随机到达集群中的任意服务器节点;本地缓存命中率低;各节点重复缓存的内容多;须要以更高的成本为代价依赖额外的分布式缓存服务。 后端数据库服务器的读压力高,要对其实施分库分表、读写分离等额外优化。 此外,即便为 Memcached、Redis 等产品加入了基于 CAS 原子操做的 Revision 字段等改进,这些独立的分布式缓存集群仍没法提供数据强一致保证(意即:缓存中的数据与后端数据库里的记录没法避免地可能发生不一致)。 |
3 更新 |
因为全部权肯定,能在集群全局确保任意视频对象在给定时间段内,均由特定的属主节点来提供写操做和动态属性的读操做等相关服务,再加上现代服务器突发宕机故障的几率也较低。 所以能够将动态属性中频繁变化但重要性或时效性较低的部分缓存在内存中,待积累一段时间后再批量更新至数据库。这可大大下降后端数据库服务器的写压力。 例如:视频的播放次数、点赞次数、差评次数、平均得分、收藏数、引用次数等属性都会随着用户点击等操做密集地变化。若每次发生相关的用户点击事件后,都须要即时更新数据库,则负载较高。而在发生“属主节点因为硬件故障宕机”等极端状况时,丢失几分钟的上述统计数据彻底能够接受。所以,咱们能够将这些字段的变动积累在属主节点的缓存中,每隔数分钟再将其统一地批量写回后端数据库。 这不但极大地下降了后端数据库收到的请求数量,并且将多个视频的数据在一个批量事务中打包更新,也大大减小数据库操做时的磁盘刷新动做,进一步提高了效率。 此外,由专门的属主节点单独发起对视频记录的更新也避免了无状态集群中多个节点同时请求更新同一对象时的争抢问题,进一步提升了数据库性能。 |
因为每次请求均可能被路由到不一样服务器节点来处理,所以没法实现累积写入优化和批量写入优化。后端数据库服务器的写负担很是重。存在多个节点争抢更新同一条记录的问题,这进一步加剧了数据库负担。 为此要对后端数据库进行额外的分库分表等优化,还会引起“须要由应用层来自行处理分布式事务”等反作用。 |
4 平衡 |
集群可以使用主被动负载平衡相结合的手段进行调度。 被动平衡:集群中的每一个节点均会按期将其麾下再也不活跃的视频对象卸载掉,同时批量通知 BYPSS 服务释放这些视频对应的端口。此算法实现了宏观上的负载平衡(以较长的时间周期来讲,集群是平衡的)。 主动平衡:集群会经过 BYPSS 服务推选出负载平衡协调节点,该节点连续监视集群中各个节点的负载状况,并主动发出指令进行负载调度(如:要求 A 节点将其麾下 10000 个视频对象的全部权转移给 B 节点)。不一样于宏观层面的被动平衡,主动平衡机制能够在更短的时间片内,以迅捷的反应速度来达成集群的快速配平。 主动平衡一般在集群中的部分节点刚刚从故障中恢复(所以处于空载状态)时效果明显,它比被动平衡反应更加迅速。如:在一个多活 IDC 集群中,某个 IDC 的光缆故障刚刚被修复而恢复上线时。 |
在从故障中恢复时,其平衡性低于 BYPSS 主动平衡集群。正常状况下则相差不大。 另外,SOA 架构的多个服务间,容易产生负载不平衡,出现一些服务超载,另外一些轻载的状况,μSOA集群则无此弊端。 |
与前文说起的用户管理案例相似,上述精准协做算法不会为集群的服务可用性方面带来任何损失。考虑集群中的某个节点因故障下线的状况:此时 BYPSS 服务会检测到节点已下线,并自动释放属于该节点的全部视频对象。待用户下次访问这些视频对象时,收到该请求的服务器节点会从 BYPSS 得到此视频对象的全部权并完成对该请求的处理。至此,这个新节点将代替已下线的故障节点成为此视频对象的属主(见前文中的步骤 2-c-i)。此过程对用户透明,不须要在客户端中加入额外的处理逻辑。
以上对“用户管理”和“视频服务”案例的剖析均属抛砖引玉。在实际应用中,BYPSS 经过其高性能、大容量等特征提供的资源精细化协调能力可适用于包括互联网、电信、物联网、大数据批处理、大数据流式计算等普遍领域。
咱们之后还会陆续增长更多实用案例,以供你们参考。
testtesttesttest 20190304 更新记录测试(for 吕老师)
更新测试:2019-3-3 阿里云由于 io hang 大面积宕机。
注:本文节选自《白杨应用支撑平台》中的“5.4 μSOA 基础库-libapidbc”小节。
注2:以上所述 μSOA 架构和 BYPSS 分布式协调算法均受到多项国家和国际发明专利保护。