关于企业上云,业内已经有了非常多的讨论和论述。这里主要是从极光自身的实际情况阐述几个理由:
1. 传统自建机房在扩充底层软硬件资源时,需要进行选型、采购、参数测试验证、实施部署等流程,整个过程需要消耗很多的人力和时间,对于快速发展的业务来说是很大的负担。云服务可以极大的缩减整个流程,对于部分云服务例如云主机可以实现分钟级别的资源交付。
2. 自建机房需要投入高额的硬件资源准备,包括机房配套基础设施、服务器、网络、安全设备等,大量的冗余资源闲置,整体资源利用率不高。上云可以实现按需购买使用,实现更高的资源利用率。
3. 基础设施建设和维护需要投入大量的人力和精力,往往还吃力不讨好。特别是虚拟化方面一直以来都是极光的痛点,资源隔离做得不好很容易受到其他虚拟机的影响,往往因为某个业务的突增影响同一个物理机上的所有虚拟机。云厂商有庞大的专业团队进行建设和维护,各方面相当可靠。
4. 云厂商提供成熟稳定的PaaS层服务可以进一步释放我们的精力,让我们更专注在我们的业务,例如天然支持多AZ的RDS可以为我们在考虑同城双机房架构时提供很大的助益。
极光机房架构变迁历史
早期极光只有一个单一的机房,随着业务的发展,系统规模越来越庞大,单一机房的资源不足以支撑极光的业务。因此我们将业务系统迁移到了新建的机房,数据业务继续保留在原有机房,整个过程磕磕碰碰历时一年左右。
后来业务系统所在的机房再进一步优化,在同城增加一个机房,并用专线进行互通,迟延在1ms到2ms之间,并将部分子系统迁移到新的AZ。由于我们的业务量级非常大,部分子系统的QPS超过了百万,在业务峰值偶尔出现延迟增加的情况,因此也做了相关的调整,访问量大的子业务系统尽量不跨AZ进行访问。此时的多AZ,并不是每个AZ都有完整的业务流程,仅仅形成一个大内网,在部署的时候进行优化处理。
由于机房仅有单一的网络出入口,带宽也有限,很容易受到同机房的其他客户的影响。曾经出现过出口带宽用满甚至整个出口中断的情况,业务受到严重的影响。我们也考虑了异地双机房、单机房多网络出口方案,但是这些方案仅仅是针对性的解决我们的一些问题,没有系统性的解决我们当时的困境,因此这两个方案并没有真正意义的实行。同时内部也在考虑上云的方案,外加一些外部因素,上云的方案就推到了首位。至于云厂商的选型此处就不做陈述,最终选择了华为云。
极光推送的业务特征分析
极光推送为开发者提供服务,一个开发者可以有多个Appkey也就是多个应用,每个Appkey的全部数据互不相关,一个Appkey有多个终端设备用户。累计终端用户超过500亿,同时还有各个维度的数据,例如tag、alias等等,单副本数据总量超过80TB;月活跃终端用户超过5亿,各个API接口请求总量超过5万QPS。使用超过2万核CPU,超过2500台虚拟机来支撑这些业务。
对外有2类网络通信:极光推送业务和开发者服务的通信,主要形式是RestfulAPI;极光推送业务和应用的通信,主要形式是基于TCP长链接的自定义协议。
自建机房/华为云基础设施分析
推送业务部署在虚拟机和K8S上,这里主要分析对比虚拟机的CPU、网络、磁盘的相关指标,以及K8S网络的指标。
从物理机看,自建机房的物理机相对华为云目标AZ的物理机性能低一些,例如华为云的物理机使用更高主频更高配的CPU。在虚拟化层面,华为云的虚拟化做得更好,资源隔离更加严格,提供各种规格的云主机和磁盘,从整体上来说计算能力更加强,但是在网络和磁盘IO吞吐和QPS有严格的限制,需要做好规划。经过测试对比,选择了相关规格的云主机和磁盘。
自建机房-云环境架设专线,云主机和自建机房机器之间的RTT在5ms以内,常规情况下为2-3ms,自建机房内网机器之间RTT为0.2ms左右,同一AZ云主机之间RTT为0.2-0.3ms。
在K8S网络方面,自建机房做了相关的优化,通过专用的网络设备能够使用Underlay的路由模式,可以说是目前可用的原生网络模式中性能最好的模式。华为云自建K8S集群仅仅支持Overlay模式,性能相对差了一些;同时也提供了K8S服务,通过硬件加速等优化提供了较好的网络性能。
上云方案的选型
上云有几个需要考虑的要素:
● 业务无中断迁移,尽量不影响客户的使用,尽量不需要客户做任何变更。
● 迁移前后业务功能一致,需要保证数据和业务的完整性。
● 需要考虑切换过程中极端情况导致的回滚操作,并且需要保证数据和业务的完整性。
基于以上几点,在方案选型方面,我们主要考虑2个方案:
方案一:自建机房和云环境是2套独立、隔离的环境,关联的仅仅是自建到云环境的数据同步,业务上相互隔离。以Appkey为单位,迁移Appkey所有的数据和业务。数据通过专线进行迁移同步,同时尽量保证原有自建机房数据完整,最好能够数据双向同步/或者数据双写,方便极端异常情况下的业务回滚,至少保证能够回滚后业务正常。
方案二:自建机房和云环境通过专线连接起来后,形成一个大内网。将数据耦合度比较低的子业务单独切换到云环境;对数据耦合度比较高并且访问量/访问迟延要求高的子业务,需要都跟随数据一起迁移。内部业务系统逐渐迁移切换完成后再对入口进行整体切换。
2个方案均能实现业务无中断,同时各有优缺点,方案一需要额外开发少部分数据同步/恢复工具,前期准备工作充分的情况下,可以比较简单快速的切换;方案二不需要开发额外工具,但是需要操作的模块多,操作时间长,切换相对复杂,容易出现差错;综合考虑下选择了方案一,尽量保证切换过程简单无差错。
上云的详细方案
自建机房和云环境拉通专线进行数据同步,从业务层面来说,两个机房各自承载全部的业务数据,为了方便故障回滚,各个数据项尽可能的保持双向同步,保持数据最终一致性即可;两个环境的推送业务是相互独立的,先保证全量数据同步到云环境,以Appkey为单位进行流量迁移,将Appkey的流量迁移到云环境,迁移期间各自承担一部Appkey的推送业务,最终将全部流量迁移到云环境。
部署方案
为了快速迁移,采用1:1对等资源部署的方式即云环境部署一套和自建机房同等资源的系统,涉及业务模块、存储集群、依赖组件、监控体系等。同时新建另一套内部域名跟原有域名作区分,对外域名不进行变更,在迁移的最后阶段再进行变更切换。
在系统入口的部署做了特殊的处理:
● API入口 - 部署同等规模的API服务器以及前端Nginx,由于对外域名只有一套,只能在自建机房和云环境做二选一,请求流量都进入到自建机房,在Nginx的Lua代码中判断请求信息,根据Appkey归属信息决定是否转发到云环境;同时新建备用域名指向云环境的入口以备异常情况使用。
● SDK接入网关入口 - 接入网关分成2个集群,各自服务自建机房和云环境,同时接收另一个机房的下行数据;SDK先连接到调度服务,根据Appkey归属信息分配到相应的接入网关集群,同时调度服务跟自建机房互通,最后再迁移到云环境。
为了快速部署,并且避免遗漏某些业务模块或者组件缺失,也为了避免配置错误,我们整理了所有的机器列表以及相关信息例如IP,将自建机房的机器信息和云环境的机器信息一一对应起来,当然还包括域名信息也进行一一对应,在部署的时候对着这些信息进行配置和部署。
数据迁移方案
推送业务的数据存储涉及ES、CouchBase、Redis、PIKA、MySQL,需要把全部存量数据同步到云环境,同时建立实时同步通道进行同步增量数据,保证云环境的数据最终一致性。
数据同步方式为组件工具同步、业务双向同步,确保迁移整个过程数据在2个机房的完整性和最终一致性。专线的拉通,使得2个机房之间RTT为2-3ms,为数据全量迁移和增量同步提供了非常强的支撑。
根据各存储组件,我们先预研了通用的迁移方案:
● ES同步方式1:云环境新建集群,拷贝源集群的数据文件到新集群,完成存量数据的迁移;增量数据由程序写入(即由业务实现数据在2个集群的双写);使用脚本工具补充切换窗口的数据。
● ES同步方式2:新增云环境节点加入到集群,逐步剔除自建机房节点,即云环境和自建机房当成同一个内网,简称大内网模式。
● CouchBase同步方式1:使用自带集群同步工具XDCR进行同步。
● CouchBase同步方式2:存量数据使用业务工具导入,增量数据由程序写入(即由业务实现数据在2个集群的双写)。
● CouchBase同步方式3:大内网模式。
● Redis同步方式1:存量数据使用redis-shake或者主从同步,增量数据由程序写入(即由业务实现数据在2个集群的双写)。
● Redis同步方式2:存量数据使用业务工具导入,增量数据由程序写入(即由业务实现数据在2个集群的双写)。
● PIKA同步方式1:存量数据使用主从同步,增量数据由程序写入(即由业务实现数据在2个集群的双写)。
● PIKA同步方式2:存量数据使用业务工具导入,增量数据由程序写入(即由业务实现数据在2个集群的双写)。
● MySQL同步方式1:存量数据使用主从同步,增量数据由程序写入(即由业务实现数据在2个集群的双写)。
● MySQL同步方式2:双主复制
以上为几种通用的迁移方式,但是每个数据集群实例的特性不一样,从业务依赖程度、数据量、读请求量、写请求量几个维度评估,最终采取的迁移方案也不一样,我们梳理了自建机房的所有数据集群实例列表,对存量数据迁移、增量数据同步、切换方式、数据一致性需要的时间、切换操作、数据验证等都做了详细的评估和说明。
测试方案
测试分为功能测试和性能测试两部分,这两部分都使用我们自己的内部账号进行测试,先进行功能测试,在功能都完备的情况下再进行压力测试。
在平时的开发过程中我们积累了大量的测试用例,覆盖到了全功能和内部细节,整理这些测试用例构造测试数据并执行,从而实现功能测试的目的。
对于压力测试,原计划的压力测试方案是:
1.在压力测试的过程中,切断云环境写入数据机房以及自建机房的数据链路,避免测试数据污染线上系统。
2.执行压力测试,确认压力测试的结果满足要求。
3.清理云环境由于测试过程导致的脏数据。
4.恢复第一步被切断的数据链路。
5.重新进行相关数据的数据同步。
6.由于第四步和第五步造成了数据和系统的变更,需要再次进行功能测试。
这个方案比较复杂,并且执行时间会比较长,特别是数据同步消耗比较多的时间,因此我们根据业务特性重新调整了压力测试的方案。测试以Appkey为单位,并且系统中各个Appkey是相互独立的,基于测试Appkey进行测试产生的测试结果数据仅属于Appkey本身,并且只对系统的整体运营数据有影响;测试Appkey也当做正常的Appkey存在在系统中,相关数据也不需要进行清理,后续如果有需要可以继续使用这些测试Appkey。因此决定在功能测试之后,构造压力测试数据,然后直接进行测试,并且对整体运营数据做清洗过滤。压力测试场景和测试用例由业务团队和测试团队根据业务特征和系统特性来构造,覆盖所有的核心功能和核心模块,压测结果数据至少不低于当前业务的峰值。
整个测试在存量数据同步完成并持续同步增量数据之后进行,主要是考虑在做压力测试的时候存储集群有等量的数据量才能使压测结果更加接近原有系统。
流量切换方案
在功能完备、数据完整的情况下,迁移操作非常简单,执行脚本,修改Appkey归属信息就可以了,具体内部逻辑如下:
● 修改Appkey归属信息。
● 在API请求入口判断Appkey的信息,将流量转发到云环境的入口,后续所有流程都在云环境执行。
● 调度服务器获取Appkey归属信息,SDK新的请求返回新的接入网关集群信息,连接到正确的接入网关服务器。
● 调度服务器通知接入网关服务器断开不属于该集群的Appkey SDK链接。
● API入口和接入网关入口变更有个时间差,2个机房的业务逻辑都能够完整执行,并且有数据同步,不管是SDK连接到哪个接入网关集群,都能够接收相关数据。
执行迁移操作后,需要进行验证,包括但不限于以下部分:
● 基础监控是否正常(网络/CPU/内存/磁盘等)
● Prometheus业务监控是否正常
● 推送业务运营数据是否正常
整个推送业务体量非常大,很难一次性全部切换,为了保证迁移过程有序稳定的进行,我们按照一定的策略和迁移比例制定迁移计划,分批次逐步迁移整个系统,每批次操作完成后都进行验证和观察一定的时间。优先测试账号并进行回滚验证,其次是非VIP,最后是VIP。
迁移实施管理
整个迁移过程,我们建立了实施过程跟踪,每天跟进当前的进度,下一计划步骤的工作任务,有哪些依赖工作,当前有哪些风险并且由谁来跟进解决等等,尽量确保迁移工作计划持续有序的执行。
尽管我们做了详细的方案,在实施过程中难免会碰到一些问题,我们尽量快速分析定位问题,直接解决问题或者方案微调,在风险可控的范围内解决问题,这里摘选几个问题陈述一下:
● 有一个CouchBase Bucket实例在实施过程中发现有分钟级别的数据不一致。经过分析发现不一致的数据都有主动删除的操作,CouchBase在删除时并不是真正的删除,仅仅是标记为删除,然后在后端线程异步执行数据删除。CouchBase采用XDCR进行跨集群数据同步,可能是在数据同步过程中,删除操作未能及时同步。考虑到该实例的数据访问量级并不大,跨专线的访问时延并不影响到业务,因此进行方案的调整,仅保留云上的实例,自建机房和云上的系统共同访问。
● 有一个Redis实例偶尔出现CPU负载增高的情况,自建机房的实例观察正常。在此期间Redis没有进行数据备份,业务访问量也相对平稳,虚拟机并未受到同台物理机的其他虚拟机的影响;分析日志发现CPU负载增高时,Redis有内存碎片清理的动作,比对相关的配置发现配置不一样。怀疑内存碎片清理消耗过多CPU,经过调整Redis配置,该情况不再出现。
● 业务操作MySQL时偶尔出现迟延增加甚至超时。通过监控发现期间有业务突增,但是业务量属于正常范围内,并且自建机房的MySQL访问正常;虚拟机/物理机负载正常,业务机器/MySQL机器的网络IO/磁盘IO均正常,MySQL各项数据也正常;再细看业务机器的基础监控发现网络丢包重传相对增加,怀疑网络链路有异常,经过华为云团队排查发现网络设备的光模块异常。更换光模块后业务恢复正常,该情况不再出现。
上云后的规划
上云不是终点,而是另一个起点。虽然已经将业务迁移上云完成,但是依然有很多工作需要做。云厂商提供了稳健的IaaS层,也提供了很多PaaS层服务,充分利用云资源的优势,拥抱云原生,持续演进优化我们的架构,为我们的客户通过更加优质的服务。以下是上云后的一些工作:
- 持续优化现有运行在虚拟机上的系统,提升系统资源利用率。
- 继续推进全面容器化,在尽量保证业务互不影响的情况下,采用混合部署的方式,进一步提升资源利用率。
- 采用云厂商的服务优化替换现有自建服务,例如文件存储等等。
- 进一步考虑多AZ甚至多Region的架构