5年时间服务器从0到200,一个创业公司的架构野蛮生长史
贝列表于2013年创立
面对业务需求的快速增长,在现有架构下难以实现对日益复杂应用场景的有效支撑,在系统可用性和稳定性这两个关键指标方面出现了明显不足。鉴于此,在当前技术环境下如何实现适配性提升与技术创新的有效结合值得我们深入探讨。
贝聊架构总体经历了三个关键阶段,在这一演变过程中,我们从单一服务器群组逐步演变为如今的多节点分布式架构,并积累了宝贵的经验教训。在这一过程中,我们遇到了一系列复杂的技术难题。
诞生期:技术架构选型 V1.0
在初创阶段时期间内期间内我们团队选择架构设计方案时当时时往往综合以下几个关键因素做出决策。
在初期创业阶段, 开发资源较为有限, 同时开发人员数量不足, 技术支持也存在欠缺; 因此建议选择易于维护且结构简单的技术架构以确保项目顺利推进.
产品不仅需要能够在短时间内完成发布流程,并且还需要具备良好的适应性以支持后续版本的快速更新;然而,在当前情况下,由于缺乏足够的时间和精力资源来深入研究和评估各种可用选项,并且考虑到系统的维护成本较高以及潜在的安全风险问题等多方面因素的影响,在初期阶段选择一个过于复杂的分布式架构系统并不现实;因此,在这种情况下,为了确保开发效率和系统的稳定运行,"研发速度必须要快"
在初创阶段,项目业务规模相对较小且复杂度较低;如果在架构设计上过于复杂,则不仅会增加研发难度,并且可能导致运维难度显著提升.
- 遵循采用合适而非最佳技术原则,并权衡研发效率与产品目标。同时,在贝聊初期阶段只有一个PHP开发人员的情况下,过于复杂的架构会导致高昂的学习成本。
基于以上分析和考量后决定采用经典的 LNMP 技术架构方案, 贝聊 V1.0 构建方案也就随之确定下来, 为缩短研发周期、提高效率, 首期阶段由第三方外包公司完成项目的研发与部署工作, 后续将由我们内部 PHP 开发团队负责后续优化与改进工作

在初期部署阶段, 配置了三台 ECS 服务节点, 其中前端层 Nginx 与系统同属一台服务器上, 同时配置了一套 RDS 数据库和一套 Memcached 缓存, .V1.0 架构的特点如下:
-
单体架构,架构简单,清晰的分层结构;
-
可以快速研发,满足产品快速迭代要求;
该系统采用的是简单易学的技术方案,在技术的学习与应用过程中都较为便捷,在日常的维护管理中也十分经济实惠,并且完全不需要专业的运维团队介入即可实现日常操作的同时还能显著降低运营支出
LNMP架构在贝聊业务的发展过程中持续存在了大约18个月的时间。该架构以其简单性和易于维护的特点,在推动贝聊快速发展的过程中发挥了显著作用。随着时间的推移,原有架构逐渐显现出了诸多问题。
成长期:技术架构重构 V2.0
自2015年初起,我便加入了贝聊。当时研发团队规模较小,在这期间我主导完成了技术架构重构,并见证了后续几次架构演进过程。通过这次经历,我成功实现了从模块化到Java分布式架构的升级转型。
就谈谈我们在技术架构重构方面遇到的关键时刻。也不是很难在于如何实施这项工作?不过真正困难的是什么时候启动这项工作?因此我们可以总结出架构重构成功的关键因素主要集中在以下几个方面:
基于原有 LNMP 架构的系统经历了两个开发团队的协同研发与持续维护工作。项目由外部技术团队负责实施,并由公司内部 PHP 开发人员参与维护。随着业务环境的变化日益加快,在线新闻管理平台(LNMP)的应用场景变得更加复杂多变。随着时间推移发现现有数据库架构存在诸多问题:多个表的设计方案存在不合理之处,并且字段的定义不够清晰且存在混乱状态。
2015年时因业务扩展需求可知, 贝聊app需要将其拆分成两个客户端: 贝聊家长端和贝略老师端, 分别服务于不同类型的用户群体, 实现精准运营的目标; 若继续沿用现有架构设计路线则可能导致新旧系统接口混合混乱, 并且早期制定的许多接口规范不够完善, 维护工作会愈发繁重与困难
原有API接口系统采用单体架构设计,并对多套接口进行整合与优化融合。该系统将多种业务处理逻辑集中于API接口系统中运行管理, 导致代码量较大, 业务处理较为复杂, 开发效率逐渐降低, 常见性能问题频发, Bug数量较多且部署难度较大, 每次改动都需要进行全面的部署流程。由于业务逻辑融合程度较高, 新入职研发人员通常面临较长的学习曲线, 难以迅速掌握全局操作方法
所有数据均存于单一RDS数据库中,并且仅有一个主数据库用于存储全部数据。然而由于多个系统共享同一个数据库,在物理隔离方面存在不足,并且存在大量表位于同一数据库内。这种配置方式常会遇到缓慢查询或其他性能问题。结果导致RDS各项指标急剧上升并引发雪崩效应反应。最终造成系统间连锁故障无法正常访问
- 存在严重的功能耦合问题,在线的第三方服务分布在各个业务系统的外部服务,并不利于集中统一管理。当需要修改公共服务参数或进行其他调整时,则必须深入到各业务系统中去处理,并且经常需要排查各种问题。工作量极大且容易导致诸多疏漏的情况必然会产生BUG。亟需将分散的服务功能进行整合,并将这些分散的功能从业务系统中解耦出来,在线人员负责独立维护和部署
我们新的研发团队成员都积累了深厚的Java分布式系统设计经验,并且具备处理高强度并发任务和确保系统可靠性的能力;基于上述丰富经验和能力积累,在现有技术基础之上实现了原有单体架构向Java分布式架构的迁移。
鉴于公司业务发展迅速,在停止专注于仅进行技术架构重构时是不可行的。我们决定在维持现有系统基础上的同时开展新的技术架构重建工作。在原有PHP研发团队的支持下,在原有PHP研发团队的支持下,在原有PHP研发团队的支持下,在原有PHP研发团队的支持下,在原有PHP研发团队的支持下,在原有PHP研发团队的支持下,在原有PHP研发团队的支持下,在原有PHP研发团队的支持下

在V2.0版本中已实现分布式部署架构的初步构建,在功能模块与业务流程划分的基础上完成了系统层级的分解工作;通过第三方服务解耦处理并分离出独立的服务组件;针对数据库(DB)领域实施了系统级拆分策略并保证其物理独立部署;通过技术手段实现了数据库主从分离能力;同时引入消息队列(MQ)技术并利用SLB实现了负载均衡及带宽入口的一致性管理
V2.0 时期的架构具有以下特点:
-
分布式部署架构,系统易扩展;
-
系统级拆分,拆分出业务功能逻辑独立的子系统,并独立拆分出 DB;
-
初步实现了服务化,系统间调用使用 Hessian 实现 RPC;
DB 通过物理隔离机制实现与主从数据库的隔离连接,在单一数据库出现问题时可有效防止因单点故障导致的业务连续性问题,并成功实现了主从复制功能;
- 采用 MQ 消息队列技术实现消息与任务的异步运行, 从而显著提升了接口响应效率, 进一步优化了用户体验水平; 同时对部分消息推送任务实施了异步处理策略, 避免传统轮询的 MySQL 机制影响, 从而降低了整体的消息推送延迟时间, 进一步提高了消息传递效率; *
通过 SLB 实现了 Nginx 的负载均衡功能,在 V1.0 架构阶段,当时采用的 Nginx 部署模式为单一节点架构。若单机故障可能导致多个业务系统受波及,则存在潜在的高危单点故障问题。通过负载均衡技术实现多节点 Nginx 分布式部署,并以提升整体系统的可用性和可靠性为目标,在确保服务稳定性的前提下实现资源优化配置。从而有效规避单一节点失效可能带来的系统性影响。
系统拆分和 DB 拆分
针对系统拆分以及 DB 拆分,我们通过两个阶段来完成该项工作。
第一阶段
首先从系统的层次结构出发,在不影响现有数据库服务的前提下
第二阶段
在完成系统级模块划分后,紧接着进行了数据库层的独立划分工作。具体而言,在完成系统层面拆分之后, 我们紧接着实施 DB 层面的拆分, 将各子系统的相关数据库表独立分离出来, 分别放置于不同的RDS数据库中, 从而实现了物理隔离的同时也完成了数据库主从分离功能。经过实验验证, 最终实验结果如图所示:

初步服务化
本阶段,我们采用了一种较为简便易懂的方式通过Hessian实现了初期的RPC服务化.对于第三方公共服务,我们从现有系统中分离出来了相应的服务化组件,并单独部署了相关组件,以便供其他业务系统统一调用.同时,则通过Hessian实现了RPC远程调用.
SLB 负载均衡
在V1.0架构阶段期间,在每台Nginx服务器均采用单点部署模式的情况下,在发生故障时可能会导致多个关键业务系统的停机运行,并可能产生严重的系统性风险(如图所示)。

在本次V2.0架构升级中,我们部署了SLB以达成负载均衡配置,并设置了多台Nginx作为负载分发单元;同时,在业务系统层同样进行了负载均衡的实现。通过这种方式消除了潜在的单点故障风险,并以确保系统的高可用性为目标完成了此次架构优化工作。

爆发期:微服务架构 V3.0
自2016年以来
基于此考虑与需求的驱动下, 我们决定引入微服务架构, 将复杂的业务逻辑拆解为若干独立且相互关联的微服务组件。每个微服务均聚焦于特定领域或功能模块进行设计与构建, 并由专业人员负责研发、维护以及相应的优化工作, 同时完成性能优化以及架构层面的优化工作。这些独立化的开发流程确保各组成部分能够在不影响彼此的情况下顺利研发并投入运行。
基于 V2.0 架构设计,在采用微服务架构进行开发的情况下,我们综合考量了多个因素,并最终选择了 Dubbo 作为我们的分布式微服务框架。

经过严格筛选与验证的高性能分布式架构,在多个行业领域已广泛应用,并通过多维度性能测试检验其可靠性;具有良好的稳定性保障。
能够与 Spring 框架实现无缝对接,并在接入 Dubbo 时实现了对原有代码的最小干扰;该架构完全由 Spring 框架完成搭建,并在接入 Dubbo 时实现了对原有代码的最小干扰;同时具有极高的接入效率和便利性
-
具备服务注册、发现、路由、负载均衡、服务降级、权重调节等能力;
-
代码开源,可以根据需求进行个性化定制,扩展功能,进行自研发;
在做微服务时,我们考虑了以下几个关键点:
以客户为中心的思想贯穿始终,在整个系统架构中无处不用的服务理念指引着我们的方向;所有服务均聚焦于单一业务领域,在此过程中我们始终坚持功能完整性的同时实现职责分离。
-
松耦合性,服务之间功能独立,能够独立部署,服务之间相互依赖;
-
高扩展性,分散资源,团队协同工作,可无限扩展,更高的代码重用率。
在实施微服务架构时,主要考虑从以下几个方面进行实施:
-
独立功能逻辑拆分为微服务,独立部署,独立维护;
-
系统功能全部通过调用微服务实现,系统不能直接访问 DB;
大规模服务包括文件、图片和视频等内容时采用了Hessian协议来进行通信;
- 每个微服务都维护独立的 DB。
微服务拆分案例 1. 班级动态微服务
贝聊提供的班级互动功能具有极高的活跃度,在线园长、教师以及家长均可参与内容发布环节。无论是园长还是教师亦或是家长,在日常管理中都能通过发送信息与相关人员展开互动交流。随着贝聊业务的迅速扩展,其用户规模呈现爆发式增长态势,在线平台内的每日活跃度持续攀升。具体而言,在线群体每天会产生数十万条独特的班级动态内容,并伴随这一现象而来的是一举一动均被即时记录下来:每日产生的互动信息总量也突破了百万大关
面对如此庞大的数据量, 我们一方面需应对高并发性能的压力, 另一方面还需应对数据的压力。原有的班级动态功能分散部署于API接口系统及后台管理系统中, 相关数据库表与现有系统共享同一个数据库(DB)。鉴于此需求紧迫性极高, 急需将现有系统的班级动态功能独立化为一个微服务组件, 同时还需要实施分库分表策略以缓解单一数据库带来的压力问题。为此, 我们专门抽调精干研发力量成立项目组对其进行开发整合
旧班级动态调用方式如下:

班级动态微服务组件调用方式如下:

拆分出班级动态微服务之后,我们解决了以下问题:
班级动态微服务采用开放透明的方式向业务调用方提供服务,在实际操作中业务调用方只需简单地调用相关接口即可,并不需要深入关注接口背后的技术实现细节。
提升代码复用能力,并将班级动态业务逻辑提取出来形成独立的微服务组件。通过这种方式,业务系统避免了分散管理班级动态业务逻辑的代码,并且无需额外复制相关代码。
基于 DRDS 技术实现了数据分库与表分离,在单一数据库场景下针对其存在的海量数据存储需求及处理能力受限的问题进行了优化设计。系统在高并发状态下往往会出现响应速度缓慢的情况,在实施后显著提升了整体性能表现,在高并发环境下也未出现性能瓶颈现象。
2. 用户通行证微服务
许多初创企业在初期阶段
都面临着需要兼顾快速开发与资源有限之间的挑战。
他们通常会将这两个关键表格整合到同一个数据库中。
贝聊公司早期也采取了这一做法。
这样一来
每个业务系统都需要自行编写DAO(Data Access Object)来获取用户数据
最终导致大量重复的逻辑代码被复制粘贴。
随着业务规模的不断扩大,在线服务与后台处理的需求日益增长。如今,越来越多的企业业务系统都需要直接处理用户的各项数据。由于用户的逻辑代码通常分布于各个独立的应用系统中,这些数据的安全性和完整性也面临着严峻挑战。与此同时,系统的并发处理能力也需要承受更大的压力。为了实现高效的负载均衡和资源调度管理,在保证服务质量的同时最大限度地提升用户体验方面存在诸多技术难点。在这种情况下,“单点故障”的风险也随之增加。因此,在现有架构无法满足高性能需求的前提下,“单点故障”的风险随之上升。这种分离化的架构设计成为解决当前技术难题的关键所在。
旧用户数据获取方式:

用户通行证微服务:

拆分出用户通行证微服务之后,我们解决了以下问题:
- 在原有架构下, 各业务系统分散存在独立的用户逻辑代码, 在实际开发中普遍存在大量手动复制粘贴的情况;
- 通过分离出用户通行证作为独立的服务,
- 使得各业务系统在进行操作时只需调用该服务接口即可;
用户的数据显示不一致的问题长期存在。原因在于不同业务系统的代码分散管理导致频繁出现所谓的"脏数据"现象,并且很难追踪具体是在哪个系统中修改了用户的账户信息;同时由于开发人员各自负责不同的业务系统进行维护,在保障账户信息统一性方面也面临着诸多挑战;经过分离出独立的用户通行证微服务之后,在所有涉及用户逻辑操作的功能模块都由该微服务统一管理的情况下;不仅实现了修改操作与查询操作的一体化管理;而且确保了相关接口的一致性。
- 通过实现用户数据解耦,在传统的业务系统架构中,默认情况下会通过 join 用户表来获取相关数据这一做法导致难以实现模块化设计。引入微服务架构后
- ,将用户的数据库独立化部署成为可能
- ,从而能够方便地进行扩展,并提升系统的性能。
微服务治理
相较于单一架构模式,在开发难度及系统扩展性方面体现出显著差异。这促使我们不得不建立一套完整的交付流程与运维管理体系。
相较于单一架构模式,在开发难度及系统扩展性方面体现出显著差异。这促使我们不得不建立一套完整的交付流程与运维管理体系。
1. 版本发布系统
微服务架构的应用开发与部署过程在复杂度上明显高于单体架构应用模式;面对众多微服务组件的存在,在运维人员无法通过手工方式有效管理众多组件的情况下,则难以实现高效的运维效率;基于此需求背景,我们团队决定开发一套自动化部署与发布机制;该机制具备以下特点:
项目的配置内容主要包括以下几项:首先是项目名称设置;其次是系统管理员的权限分配;接着是核心团队成员信息的管理;此外还包括版本控制系统(如SVN/Git)的具体地址配置;同时还需要设置系统的账号分配方案以及服务启动时使用的 shell 路径;另外还需要规划和管理自定义运行脚本路径;同时对于不同的开发环境还需要制定相应的 JVM 配置参数设置方案;最后还需完成 Web 应用服务器相关的配置参数设置等各项内容。
- 按照项目配置好之后,可以发起上线申请单,通过审批之后,一键即可部署;
采用灰度发布策略进行版本更新,并可按需选择服务器进行部署以实现版本更新的安全性保障
能够实时采集运行部署过程中产生的日志信息,并通过可视化手段实现对这些日志的实时监控分析。
对于发生发布的异常情况而言,在多台服务器的场景下我们采用了以下两种策略:第一种方案是当出现故障时立即暂停所有其他服务;第二种方案则是即使出现故障也依然保持服务的连续性以确保数据完整性。
紧急退化措施:在发生版本发布异常时,请确保将应用迅速退化至前一个稳定版本。
借助该 versions 管理系统的框架设计下,在线提交需求和修改功能模块时会触发自动生成的配置项;同时支持一次性批量导入项目中现有的配置文件;此外还实现了自动化的测试用例执行功能以及结果报告生成能力。
2. 开发测试发布部署
考虑到微服务架构的复杂性,在确保每个微服务交付质量的基础上,我们设置了四个不同的环境。
- 开发环境,供研发人员在开发、调试阶段使用;
测试用例,在开发团队完成所有功能模块设计与验证后(即经过全面的功能开发和测试阶段),系统将该验证环境部署至测试组成员手中作为质量评估依据。
预发布部署环境中,在经过测试环境中功能验证的全部完成后,在线部署至生产环境中之前的一个preview部署阶段,在此阶段将使用与主生产环境共享的数据库、缓存和MQ消息队列等资源配置;该preview部署阶段旨在确认微服务在即将上线到主生产环境下时是否存在问题(BUGs或缺陷),并且不涉及主生产用户的任何方面;通过这一验证过程最终确保主生产环境下服务的顺利上线。
- 生产环境,即线上环境,是面向用户的线上环境。
通过以上四个环境,确保微服务组件的研发、测试、发布的质量。
3. 分布式配置中心以及分布式任务调度平台
随着微服务架构的推行,我们划分成了多个独立的微服务及子系统,并将所有配置信息以明确的形式记录在专门的配置文件中。这些定时任务则分布在各个微服务及其子系统中,目前难以有效管理和维护。因此建议采用专业的分布式配置中心和任务调度平台来提升管理效率。
基于分布式架构的Disconf 配置管理平台,在实现对所有配置的统一发布流程的同时,默认将所有配置数据被存储于云端集中管理系统的前提下,在线用户可以通过统一化的平台访问界面完成发布的更新操作。此外,在修改任何一项配置时,默认情况下无需重新部署或重启任何微服务组件即可完成变更操作,并通过管理平台直接修改对应的资源参数设置;同时完成了针对不同场景的个性化定制研发工作,并采用高级加密技术对所有的配置信息进行了保护,在确保账号管理和密码存储的安全性的同时有效防止了敏感信息泄露风险。

Elastic-Job 分布式任务调度平台具备了定时任务注册中心、任务分片以及弹性扩容和缩容操作,并支持失效转移、任务停止恢复和禁用等功能特性,在分布式架构中使得管理更加便捷。
4. 全链路跟踪
将复杂的系统划分为多个独立的子系统和微服务组件,在如此复杂的分布式集群环境中。单次请求可能跨越多个微服务组件,请问如何实现对链路调用的跟踪?是否能够快速识别单次接口调用中的性能瓶颈,并定位导致整体延迟的主要因素?为此我们引入了美团点评的 APM 工具 Cat 实时监控系统,并将其与 Dubbo 服务化框架进行了深度整合。通过全局链路 ID 的机制实现了精准的链路追踪功能。
5. 微服务授权
默认情况下,Dubbo未实现服务授权功能。在系统中,进行微服务间交互时,尚未实施授权验证机制。为此,我们对Dubbo进行了专门化的定制开发工作,最终开发出了一个用于管理微服务权限的认证平台。该平台能够有效保障核心API的安全运行。
6. 微服务监控
将众多微服务组件进行拆分后所面临的问题是如何实时监控这些微服务的状态变化情况
7. 微服务管理
我们借助Dubbo平台提供的管理控制台功能,在运维中完成对各微服务组件的路径路由配置、权限管理、权重分配、降级处理以及永久性移除等功能设置。
经过一年多的微服务化历程,V3.0 架构如下:

V3.0 微服务架构具有以下特点:
-
完全实现了分布式部署架构,系统与微服务组件都非常容易扩展;
-
以服务为中心,全面构建了微服务组件;
-
这些关键组成部分(如系统和微服务组件)均为无单点风险,并且充分保证了系统的高可用性;此外,在缓存和MQ消息队列方面也达到了HA目标;同时数据库(DB)同样实现了这一目标。
未来:贝聊架构演进 V4.0
V3.0 架构虽然实现了微服务架构,但该架构还存在以下可以继续演进的点:
*采用Docker容器部署策略, 该技术体系具有轻量化设计特点, 在部署效率上具有显著优势; 能够实现应用间的完全隔离; 同时支持多平台环境下的良好运行. 基于微服务架构的设计理念与Docker容器技术的有效结合能够显著提升系统的部署效率. 当前系统已经实现了基于微服务架构的基础设计, 但在实际运行中还存在无法实现资源按需自动扩缩的问题; 我们预期通过将微服务组件与容器化技术相结合, 能够在资源需求发生变化时实现自动化扩缩能力提升.
- 统一 API 网关,目前我们的核心 API 还只是一个统一的代理层,尚不具备网关的身份认证、防报文重放与防数据篡改、业务鉴权、流量与并发控制等等功能,实施 API 网关后,可以实现前后端分离,提供便捷的监控、报警、分析,还可以提供严格的权限管理以及流量限制,保障 API 的安全稳定。接下来我们将实施统一的 API 网关控制;
在推进跨区域IDC(Internet Data Center)部署方面,目前系统的架构仅支持本地单一机房的运行,而这种架构无法提供足够的冗余保障和容灾能力.为此,我们计划逐步引入本地同区域多节点部署方案,以便在发生本地故障时能够快速切换至备用节点.待此方案成熟后,再过渡到更加复杂的异地跨区域IDC部署模式.该方案旨在通过异地架构提升系统可靠性并满足用户本地需求.
复盘与总结
架构演进正稳步推进中,在推动过程中必须确保架构与业务保持紧密关联,并根据不同的发展阶段采取相应的策略和措施。对于不同类型的业务形态和运营模式,在选择和构建体系时需充分考虑其特殊性。
单一应用场景模式更适合初创期公司
随着企业规模不断扩大, 业务线不断增加, 并且逐渐变得复杂, 同时, 研发人员的数量也成百上千地激增. 单体应用架构在这种情况下逐渐显现出了问题, 因为成百上千的研发人员集中在同一个系统中进行开发, 缺乏多线程开发能力, 导致大量而复杂的业务代码之间存在高度关联性, 同时严重影响了整体效率水平.
微服务架构能够实现业务解耦的优化,在可扩展性和自主运行能力方面表现突出。它不仅有助于缩短项目周期并提升开发效率,还能显著增强代码复用程度。该架构体系支持更稳定的运行和快速响应的需求。然而在服务治理方面存在较高要求,在维护成本上相较于单一应用系统更为高昂;这对开发团队的专业水平和系统设计能力提出了更高的要求。
目前我们仍在进行架构演进的过程,并已成功完成了若干个关键的架构阶段。尽管在技术上已经取得了一定的进步但仍然面临诸多尚未解决的技术难题和挑战需要我们持续努力去突破和应对。在规划技术架构时需综合考量多个因素包括业务规模、业务时效性以及研发团队的能力等一个系统的整体架构应当与其所服务的应用系统相匹配在整个系统的生命周期内保持这种匹配关系才能达到最佳的效果
