5年时间服务器从0到200,一个创业公司的架构野蛮生长史

本文首发于InfoQ垂直公众号:聊聊架构, 5年时间服务器从0到200,一个创业公司的架构野蛮生长史,转发于InfoQ公众号: 一家创业公司的5年架构变迁史

贝聊成立于2013年,是中国幼儿园家长工做平台,致力于经过互联网产品及定制化解决方案,帮助幼儿园解决展现、通知、沟通等家长工做中的痛点,促进家园关系和谐。贝聊是威创股份(A股幼教第一股)、清华启迪、网易联手投资的惟一品牌。在短短几年内,用户规模迅速达到千万级别,每一年DAU均呈倍数级增加。面对如此快速的发展,原有的技术架构很难支撑愈来愈复杂的业务场景,在系统可用性以及稳定性方面,都给贝聊技术团队带来了很大的压力。所以,如何针对当前需求,选择合适的技术架构,保证架构平滑演进,值得咱们深刻思考。nginx


贝聊架构演进的三个重要历史阶段


贝聊架构整体经历了三次重大历程,由几台服务器搭建的单体架构到目前的几百台分布式部署架构,在整个变化过程当中,咱们踩过了不少坑,遇到过不少重大技术挑战。

诞生期—技术架构选型V1.0


创业初期,咱们的初始创业团队在进行架构选型时,主要基于如下几点进行考虑:

1.在创业初期,研发资源有限,研发人力有限,技术储备有限,须要选择一个易维护、简单的技术架构;

2.产品须要快速研发上线,并可以知足快速迭代要求,现实状况决定了一开始没有时间和精力来选择一个过于复杂的分布式架构系统,研发速度必需要快;

3.创业初期,业务复杂度比较低,业务量也比较小,若是选择过于复杂的架构,反而会增长研发难度以及运维难度;

4.听从选择合适的技术而不是最好的技术原则,并权衡研发效率和产品目标,同时创业初期贝聊只有一个PHP研发人员,过于复杂的技术架构必然会带来比较高昂的学习成本。

正是基于以上几点考虑,最终选择了经典的LNMP技术架构,贝聊V1.0架构就这样诞生了,为了加快产品研发速度,尽快上线产品,首期经过外包公司实现了研发以及部署,后续由咱们的PHP研发人员接手,并进行后续的迭代开发。


初期部署时,部署了三台ECS服务器,其中接入层nginx与系统部署在同一台机器,RDS数据库一台机器,Memcached缓存一台机器,V1.0架构具备如下特色:

  • 单体架构,架构简单,清晰的分层结构;
  • 能够快速研发,知足产品快速迭代要求;
  • 没有复杂的技术,技术学习成本低,同时运维成本低,无需专业的运维,节省开支。
LNMP架构支撑贝聊业务发展了将近一年半左右的时间,简单、易维护的架构为贝聊的快速发展作出了很大的贡献,期间业务发展迅速,用户体量也愈来愈大,原有架构逐渐暴露出愈来愈多的问题。

成长期—技术架构重构V2.0

我是在2015年初加入了贝聊,初始研发团队只有三人,有幸在这一时期
主导了贝聊技术架构重构,并经历了贝聊后续的几回架构演进路程,将原有PHP单体架构重构为JAVA分布式架构。

首先谈一谈咱们作技术架构重构的契机,重构并不是难在怎么作,而是难在什么时候开始作,因此咱们作架构重构的契机主要基于如下几点:

1.原有LNMP架构经历了两个团队研发和维护,外包团队和公司PHP研发人员,因为业务变化比较快,原有的数据库设计逐渐暴露出来不少问题,不少表设计不合理, 不少字段定义不清,比较混乱;

2.2015年,因为业务发展,贝聊app须要拆分为两个客户端:贝聊家长端和贝聊老师端,经过不一样的客户端来服务不一样的用户群体,达到精准运营的目的,若是在原有架构上继续进行开发,则会致使新旧接口逻辑混在一块儿,而且早期的不少接口定义不是很规范,维护起来愈来愈麻烦、愈来愈吃力;

3.原有API接口系统是单体架构,里面包含了各类接口,混合了各组业务逻辑处理,全部功能都集中在API接口系统中,代码很是臃肿,业务很是繁杂,迭代开发的速度也逐渐减慢,各类性能问题常常爆出,BUG也比较多,而且部署困难,任何修改每次都需总体部署。因为业务逻辑混杂在一块儿,新入职研发人员须要很长时间才可以彻底熟悉系统,很难快速经过以点及面的方式切入系统;

4.全部数据存储在一个RDS数据库中,只使用了一个主库,没有从库,同时不少系统共用一个数据库,一方面数据库没有作到物理上的隔离,另外一方面不少表都放在了同一个数据库中,常常会碰到一个慢查询或者其余性能问题,致使整个RDS各项指标飙升,形成雪崩效应,全部系统连锁出现故障,最终都不能访问;

5.公共服务耦合比较严重,不少第三方服务都散落在各个系统里面,不便于统一维护,当须要修改公共服务参数或者作其余调整时,须要深刻到每一个系统里进行修改或者排查,很是麻烦,还很是容易出现遗漏,最终产生BUG,急需独立拆分出公共服务,将公共服务从业务系统中解耦出来,由专人进行独立维护、独立部署;

6.咱们新的研发团队都拥有丰富的JAVA分布式架构设计经验,拥有高并发、高可用经验,所以将原有的单体架构重构为JAVA分布式架构也是顺势而为。

因为公司业务高速发展,若是停下来专门作技术架构重构是不可能的,咱们选择了在维护现有系统的基础上,同时进行新的技术架构重构工做。重构期间,在原有PHP研发团队的大力支援下,咱们的重构工做还算很是顺利,既保障了业务的快速迭代需求,又成功完成了新的技术架构重构,新的V2.0架构以下:


在V2.0架构时期,初步实现了分布式部署架构,根据不一样的功能以及业务逻辑,完成系统级别的拆分,同时对第三方服务进行解耦,拆分出了独立的服务模块,针对DB,咱们实现了系统级拆分以及物理独立部署,并实现了数据库主从分离,同时引入了MQ消息队列,并使用SLB实现了负载均衡和带宽流量入口统一。

V2.0时期的架构具备如下特色:


  • 分布式部署架构,系统易扩展;
  • 系统级拆分,拆分出业务功能逻辑独立的子系统,并独立拆分出DB;
  • 初步实现了服务化,系统间调用使用Hessian实现RPC;
  • DB实现了物理隔离,避免之前单DB出故障,引起业务连锁故障,同时实现了数据库主从分离;
  • 引入MQ消息队列实现消息和任务异步化,加快接口响应速度,提高用户体验,同时针对一些消息推送任务也实现异步化,避免早期的轮询MySQL机制,减小消息推送延时,提高消息推送速度;
  • 使用SLB实现了Nginx负载均衡,在V1.0架构时期,咱们的Nginx是单点部署,若一台Nginx服务器挂掉,则会影响不少业务系统,有单点故障风险,经过SLB实现多台Nginx负载均衡,达到高可用的目的,避免单点故障。
系统拆分和DB拆分

针对系统拆分以及DB拆分,咱们经过两个阶段来完成该项工做。

第一阶段

首先在系统层面进行拆分,将原有的大系统拆分出多个业务逻辑独立的子系统,而DB暂时不进行拆分,多套系统还继续共用一个DB,只是根据业务逻辑划分各个系统所依赖的表,不一样业务逻辑系统之间不能互相访问表,这样新系统只访问本身所归属的表,经过此种方案,能够保证原有系统业务不受影响,同时新拆分的业务系统研发工做也能够顺利进行,此阶段大概花费了咱们几个月的时间,最终顺利完成系统层面的拆分。

第二阶段

在完成系统层面拆分以后,咱们紧接着实施DB层面的拆分,将各个子系统所依赖的表独立拆分出来,分别放置到不一样的RDS数据库,实现物理的隔离,同时实现了数据库主从分离。最终实现效果以下图:


初步服务化

本阶段,咱们采用了比较简单易用的Hessian实现初期的RPC服务化。针对第三方公共服务,从原有系统中解耦出来,独立拆分出服务化组件,并作独立部署,供其他业务系通通一调用。而系统间调用也经过Hessian来实现RPC远程调用。

SLB负载均衡

在V1.0架构期间,咱们的Nginx都是单点部署,一旦一台Nginx服务器出现故障,则会波及到大量业务系统,风险很是大,以下图:


在V2.0架构期间,咱们引入了SLB实现负载均衡,SLB配置了多台Nginx,同时在业务系统层面也实现了负载均衡,避免了单点故障,达到高可用的目的。


爆发期—微服务架构V3.0

进入2016年以来,贝聊业务高速发展,用户规模在短期内增加数百万,同时各个业务线逐渐铺开,业务场景更加复杂,代码规模膨胀得也很是快,研发团队迅速达到了几十人规模,一个系统多人开发,研发人员层次不一,规范难以统一,同时业务逻辑耦合严重,每次上线都须要将整个大系统总体打包上线,风险很是大,而且新人入职以后学习成本很是高。所以咱们引入了微服务架构,将业务逻辑拆分为独立的微服务组件,每一个微服务都围绕着具体业务进行构建,由专人研发和维护,并由专人作性能优化和架构优化,各个微服务组件的研发与上线互不影响。

结合V2.0架构,在实施微服务架构时,基于多方面考虑,咱们选择了Dubbo做为分布式微服务框架。


  • 成熟的高性能分布式框架,目前不少公司都在使用,已经经受住各方面性能考验,比较稳定;
  • 能够和Spring框架无缝集成,咱们的架构正是基于Spring搭建,而且接入Dubbo时能够作到代码无侵入,接入也很是方便;
  • 具有服务注册、发现、路由、负载均衡、服务降级、权重调节等能力;
  • 代码开源,能够根据需求进行个性化定制,扩展功能,进行自研发;
在作微服务时,咱们考虑了如下几个关键点:
  • 以服务为中心,一切都是服务,每一个服务都针对单一业务进行封装,保证功能完整性和职责单一性;
  • 松耦合性,服务之间功能独立,可以独立部署,服务之间相互依赖;
  • 高扩展性,分散资源,团队协同工做,可无限扩展,更高的代码重用率。
在实施微服务架构时,主要考虑从如下几个方面进行实施:

  • 独立功能逻辑拆分为微服务,独立部署,独立维护;
  • 系统功能所有经过调用微服务实现,系统不能直接访问DB;
  • 小数据量高并发调用使用Dubbo长链接协议进行通信,大数据量服务好比文件、图片、视频等使用Hessian协议进行通信;
  • 每一个微服务都维护独立的DB。

微服务拆分案例

1 班级动态微服务

贝聊的班级动态是一个高频率使用功能,园长、老师、家长均可以在班级进行发布动态,经过点赞、回复进行互动。随着贝聊业务飞速发展,用户规模爆发,天天都产生数十万的班级动态量,同时日回复量和点赞量均达到了数百万级别。面对如此大规模的数据量,咱们一方面要应对高并发的性能压力,另外一方面又要应对数据压力,原有的班级动态功能散落在API接口系统以及后台管理系统中,相关的表也与原有系统共享一个DB,迫切须要咱们拆分出独立的班级动态微服务组件,同时还须要作分库分表减小单数据库压力。所以咱们专门抽调精干研发人力,拆分出了班级动态微服务组件。
旧班级动态调用方式以下


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

拆分出班级动态微服务以后,咱们解决了如下问题:
  • 班级动态微服务对业务调用方透明,业务调用方只需调用接口便可,无需关注技术实现细节;
  • 代码复用性,班级动态业务逻辑单独抽出来作成独立微服务组件,业务系统再也不散落班级动态业务逻辑代码、无需再进行代码拷贝;
  • 采用DRDS实施了分库分表,解决了单数据库数据量大、数据处理能力有限的瓶颈问题,在单数据库状况下,因为数据量比较大,高并发时期,常常遇到性能问题,接口响应速度很是慢,在实施分库分表以后,班级动态接口的总体性能提高了几倍,用户体验很是好,高并发时期也没有了性能问题。
2 用户通行证微服务

不少创业公司,在一开始发展时,为了追求速度,同时因为人力不足,都是将用户数据表与业务数据表暂时放在了一个DB里面,贝聊早期也是这样,这就形成了各个业务系统都是本身分别写DAO来获取用户数据,产生了大量重复的用户逻辑拷贝代码。随着业务发展的愈来愈快,愈来愈多的业务系统都须要访问用户数据,用户逻辑代码散落在各个业务系统,用户数据愈来愈难维护,复杂度愈来愈高,同时用户量愈来愈大,常常会遇到高并发性能问题,不容易作独立性能优化,所以拆分出独立的用户通行证微服务迫在眉睫。

旧用户数据获取方式



用户通行证微服务

拆分出用户通行证微服务以后,咱们解决了如下问题:
  • 代码复用性,原先几乎每一个业务系统都散落有用户逻辑代码,处处都是拷贝代码,拆分出用户通行证微服务以后,业务系统只需调用用户通行证微服务接口便可;
  • 用户数据一致性,之前因为获取以及修改用户数据代码散落在各个业务系统,常常会产生一些用户脏数据,而且很难查询在哪一个系统修改了用户数据,同时因为不一样的研发人员开发维护不一样的业务系统,也给维护用户数据一致性带来了很大的挑战,拆分出用户通行证微服务以后,全部跟用户逻辑相关的功能,都由用户通行证微服务提供,保证了修改数据以及获取数据的接口一致性;
  • 用户数据解耦,原有业务系统中常常会join用户表获取用户数据,难以拆分,拆分出微服务以后,用户数据库独立设计部署,方便进行扩容以及性能优化。
微服务治理

微服务架构开发、测试、部署复杂度远远大于单体架构,所以须要构建可以支撑微服务架构的交付和运维能力。

1 版本发布系统

微服务架构的应用开发、部署的复杂度都是远大于单体架构应用的,大量的微服务组件若是依然靠运维人员手工的配置管理显然是难于应付了,所以咱们研发了自动化部署和发布的版本发布系统,咱们的版本发布系统具备如下特性:




  • 项目配置包括项目名称、管理员、项目成员、SVN/Git地址、账号、服务启动的Shell、自定义脚本、不一样环境的JVM配置、Web容器配置等等;
  • 按照项目配置好以后,能够发起上线申请单,经过审批以后,一键便可部署;
  • 支持灰度发布,能够灰度选择服务器进行版本发布,确保版本发布安全稳定;
  • 能够实时收集部署过程产生的日志,可视化实时监控部署过程产生的问题;
  • 针对发布异常,咱们有发布异常处理机制,针对有多台服务器的状况,能够选择只要有失败就中止发布,即一台发布出错,后续其他服务器中止发布,也能够选择无论是否有失败都继续发布;
  • 快速回滚,针对版本发布出现异常的状况,咱们支持快速回滚,能够快速回滚到上一个稳定的版本。
经过版本发布系统,实现代码版本管理、一键部署上线、一键快速回滚、上线单申请、上线审核以及上线日志等。

2 开发测试发布部署

针对微服务复杂的架构,为了保证每一个微服务交付的质量,咱们部署了四个环境:

  • 开发环境,供研发人员在开发、调试阶段使用;
  • 测试环境,研发人员在开发环境完成全部功能开发、测试以后,部署给测试人员进行验收的环境;
  • 预发布环境,在完成测试环境的功能验收以后,功能发布至生产环境前的一个预演环境,与生产环境共用相同的数据库、缓存、MQ消息队列等,用来在微服务上线生产环境前,确认是否还存在BUG等问题,不会影响生产环境的用户,最终用来确保上线生产环境成功;
  • 生产环境,即线上环境,是面向用户的线上环境。
经过以上四个环境,确保微服务组件的研发、测试、发布的质量。

3 分布式配置中心以及分布式任务调度平台

随着微服务架构的实施,咱们拆分出了不少的微服务以及子系统,各类配置信息都以明文形式配置在配置文件中,同时各类定时任务也散落在各个微服务以及子系统中,很是难管理。所以咱们选择了合适的分布式配置中心以及分布式任务调度平台
  • Disconf分布式配置管理平台,实现了配置发布统一化,全部配置都存储在云端系统,用户统一在平台上进行发布、更新配置,更改配置时,无需从新打包或重启微服务,经过管理平台直接修改便可,同时咱们进行了个性化定制研发,全部配置信息都实现了加密方式,避免帐号、密码等敏感信息泄露;
  • Elastic-Job分布式任务调度平台,实现了定时任务注册中心、任务分片、任务运行服务器弹性扩容缩容、失效转移、任务中止恢复和禁用等特性,更方便的管理分布式架构环境中的定时任务。
4 全链路跟踪

微服务架构拆分了大量的子系统以及微服务组件,面对如此复杂大规模分布式集群,一次链路调用可能会发生在多个微服务组件之间,如何进行链路调用追踪,如何快速发现一次接口调用过程当中哪些地方须要优化、哪一个微服务接口致使了总体调用比较慢。针对上述问题,咱们引入了美团点评的APM工具Cat实时监控系统,与Dubbo服务化框架进行整合,经过全局链路ID,实现链路追踪功能。

5 微服务受权

默认Dubbo没有实现服务受权功能,系统调用微服务、微服务之间调用均没有实现受权验证,都是直接访问微服务组件接口,所以咱们针对Dubbo进行了个性化定制研发,研发了微服务受权认证中心,经过受权认证保证核心微服务接口的调用安全性。

6 微服务监控

拆分出大量的微服务组件,咱们面对的是如何监控这么多的微服务运行状态,咱们采用了Dubbo自带的简易监控中心,监控微服务组件的成功率、失败率、平均耗时、最大耗时、并发量等指标,经过这些指标发现微服务性能瓶颈,进而优化微服务性能。同时咱们进行个性化定制扩展与研发,针对Dubbo接口调用,统计接口耗时排行、接口失败排行、接口访问异动排行等等,经过定制化研发的统计报表,更直观的监控Dubbo接口性能。

7 微服务管理

咱们使用Dubbo的管理控制台,实现对微服务的路由规则配置、访问控制、权重调节、服务降级、服务禁用、容错等功能,能够很是方便的管理运行中的微服务组件。

通过一年多的微服务化历程,V3.0架构以下:



V3.0微服务架构具备如下特色:

  • 彻底实现了分布式部署架构,系统与微服务组件都很是容易扩展;
  • 以服务为中心,全面构建了微服务组件;
  • 系统、微服务组件、缓存、MQ消息队列、DB等均无单点风险,所有实现了HA高可用;

将来—贝聊架构演进V4.0

V3.0架构虽然实现了微服务架构,但该架构还存在如下能够继续演进的点:
  • Docker容器部署,Docker具有轻量级、快速部署、隔离应用、跨平台的优点,微服务很是适合与Docker结合进行快速部署,目前虽然咱们实现了微服务架构,但还未作到快速弹性扩展,若是将微服务与Docker容器进行结合,能够实现快速弹性扩展,业务高峰期能够快速自动扩展服务器,业务低峰期能够自动回收服务器,接下来咱们即将实施微服务组件的Docker容器化部署;
  • 统一API网关,目前咱们的核心API还只是一个统一的代理层,尚不具有网关的身份认证、防报文重放与防数据篡改、业务鉴权、流量与并发控制等等功能,实施API网关后,能够实现先后端分离,提供便捷的监控、报警、分析,还能够提供严格的权限管理以及流量限制,保障API的安全稳定。接下来咱们将实施统一的API网关控制;
  • 跨IDC机房部署,目前咱们的系统仍是单机房部署,单机房不具有冗余以及容灾机制,首先咱们将逐渐实施同地多机房部署,先具有多机房部署能力,避免单机房故障,最后咱们再实施异地跨IDC机房部署,达到异地冗余高可用以及用户就近访问的目的。

总结

架构演进一直在路上,架构要围绕业务进行,不能脱离于业务,不一样的业务时期须要不一样的架构。

单体应用架构,更适合创业初期,公司须要快速试错以及验证市场反应,须要更快的研发速度,同时研发人员比较少,而单体应用架构比较简单,能够快速切入,对研发人员的技术栈要求不是特别高,能够快速上手快速研发,但在设计单体应用架构时最好能够提早规划好将来的扩展性,能够在业务层面先规划好,便于往后业务发展到必定规模,能够快速进行解耦,实施微服务化架构。

当企业发展到必定规模,业务线变的愈来愈多、愈来愈复杂,同时研发人员的数目也快速增加,单体应用架构就会慢慢暴露出来弊端,大量的研发人员在一个系统上进行开发,缺乏并行研发能力,大量的业务代码耦合在一块儿,同时研发效率很是低。微服务架构能够更好的进行业务解耦,具有更好的扩展性以及独立性,能够提升研发团队间的并行化研发速度,提高效率、提升模块复用性,具有高可用、高并发特性。但微服务架构对服务治理的能力要求比较高,维护成本也会比单体应用高,须要强大的服务治理支持,对研发人员的技术能力要求也比较更高。

目前咱们依然在架构演进的路上,经历了以上几回架构历程,虽然取得了必定的进步,但依然有不少挑战等待咱们去迎战。规划技术架构须要综合考虑业务的规模、业务的时效性、研发团队的规模、研发的技术能力、基础环境配置等。架构来源于业务,架构演进的生命周期只有完美匹配好业务的生命周期,才能最终发挥出最好的效果。
相关文章
相关标签/搜索