写于2018-02-01
互联网公司从创业、各轮融资、壮大发展、成功上市,各阶段适用于不同的技术架构,过早采用过于激进的架构可能会出现人力、成本、制度的不匹配,而采用过时的技术则会严重的掣肘业务的发展。好的架构是不断进化的,不是一开始就设计好的放之四海皆准的通用架构,但掌握其中有一些通用的原则,可以让我们少走很多弯路。
在创业初始阶段,通常你只有几号人,还没有做出一个产品投放市场,甚至你还不知道市场上反应如何,产品有无风险,这时你需要的是尽快做出第一版产品,怎么简单怎么来。你可以先不急着前后端分离,不需要专职的运维人员,如果你需要移动端,还需要找Android和IOS开发。完成这项任务,你最低需要一个Java开发(HTML + Java + 运维),一个移动端开发人员、一个美工(前期可以兼职),为什么你需要找Java开发,而不是.NET呢?第1是Java的跨平台(不会与特定操作系统绑定),第2是目前来说Java开发人员市场占有量最高,意味着你后面更容易招到人,第3是Java体系有很多开源的技术,在企业后期发展的不同阶段都或多或少能找到适用的开源产品,这能节省研发投入、缩短时间,提高产品服务质量。这个阶段,做为技术负责人的你,抛开业务层面的事情,技术上你需要关注:
版本管理:Git,分支管理?产品都还没做出来,直接在主干上堆代码吧
项目管理:Tower,跟移动端微信结合起来,简直利器
技术架构:SpringMVC/SpringBoot + Redis + 【Tomcat】 + Mybatis + Mysql/Oracle
纯后端项目,使用SpringBoot,内嵌容器,web项目,使用SpringMVC + Tomcat,ORM建议不要使用Hibernate而使用Mybatis,使用Hibernate的前提对它有绝对的掌控能力,其实辅以Mybatis自动生成工具,编码实现持久层操作并不比Hibernate工作量多。数据库根据情况选择,如果团队对数据库核心知识尤其是对索引的掌握不太彻底的话,可以酌情考虑Oracle,在数据库知识缺乏的情况下使用Mysql的风险在于:达到一定的数据量后,你需要不停地做很多SQL层面的性能优化(建索引啊 etc...),而且这个数据量绝对会比你认为的那个数小很多。使用Oracle的风险在于:未来将面临版权问题。但却赢得了时间去完善业务,即把性能优化的时间推后,前期赢得更多的实现业务的时间。具体如何选择,取决于团队的技术能力,你的能力,业务的压力,权衡而为。
这时的系统架构,通常按使用人分系统,最典型的莫过于:一个核心系统(用户用) + 管理后台(公司运营用),这时每个系统都是集中式的,做好模块化是这一阶段的目标(高内聚低耦合总是对的),注意前期的SQL尽量减少多表join,使用Java实现去Join。
团队组建: 首先,核心技术人员强烈建议要有知名互联网公司背景(广州的话:YY、UC、唯品会、网易等),然后在招聘时你可以适当以此作为宣传,这有利于你在激烈竞争的招聘市场上找到能力更强的技术人员,当然也有利于后期资本引入时的估值溢价。
这一阶段的架构关键点:组件化
终于产品面世,收获了第一批用户。恭喜你,有了历史数据负担了,这对你的技术能力提出了更高的考验。在生产环境替换class文件这种高危动作,在生产数据库上不小心手抖Delete某个表数据,应用不定时重启这些小差错都会让你的第一批用户流失。这时候在技术上你需要关注:
持续集成:jenkins,生产上的jar包或war包就不要用开发人员自己的机器打了,用Jenkins打吧
Bug管理:禅道,就不要继续用Ecxel来记录Bug了
接入层:nginx作为反向代理,后端的Tomcat或SpringBoot服务至少跑两个,完成高可用
数据库:至少一主一备,使用Keepalived等实现高可用
通常应用高可用后的调整点:
Session共享:Tomcat可以使用Tomcat redis session manager,SpringBoot则更简单,只需要几行代码就可以实现。也可以在接入层会会话粘滞(不建议,后端服务无状态才是我们追求的目标)
文件上传,在上一阶段可能是直接使用本地文件系统,现在则需要改成使用FTP服务器
定时quartz任务,使用Spring-quartz-schedule(本质是数据库锁)、Redis抢锁、Zookeeper leader选举共三种方案都可达到目标。
升级:某个夜黑风高的晚上,更新一半Tomcat/SpringBoot应用(可能就是一台,冏),再更新另一半
文件定期备份:数据库全备+增备、FTP服务器定时全备、应用log定期压缩归档
监控:网络、CPU、内存、磁盘等偏硬件资源的监控,直接用阿里云提供的吧
这一阶段的架构关键点:高可用
到这时候通常开发、测试、运维、需求的人员已相继到位,职责标准化后大致如下:
项目管理:原型工具Axure,团队协作Tower,文档服务器SVN
运维:
DBA体系
上线流程
自动化运维
服务器规划
监控体系,推动开发提供health check接口,日志标准化,引入Zabbix,除了系统级的监控还需要业务级的监控
线上数据库的更新、应用的部署只能由运维执行,引入轻审批机制。
账号权限管理,root权限回收,应用不能再用root启动了。推进各种以公司申请的开发者账号等必须由公司的公共账号申请(如果是以某个人的账号申请的,人员离职后相当麻烦) etc.关闭各种不需要的端口,预防安全漏洞。
测试:
持续集成,Jenkins
Bug、测试用例管理,禅道。压力测试
开发:
版本管理,再也不能像从前一样把Git当成代码存储服务器用了,版本管理流程必须建立起来,以下是一个较敏捷的版本管理流程供参考
说明:
正常版本以上线日作为目标建立release,(开发、测试、运维)目标清晰。
紧急修复版本以hotfix作为上线目标,上线时间较机动。
Master只记录线上稳定版本代码,版本管理员只需要在每次上线验证通过后将release(或hotfix)合并到Master。
技术栈:SpringMVC/SpringBoot + Redis + Tomcat + Mybatis + Mysql/Oracle + Zookeeper + RabbitMQ
RabbitMQ论性能比不上Kafka、RocketMQ,但在数据一致性、稳定性、可靠性、易用性、运维便利性上取得了一个不错的平衡,相信我,大多数时候消息中间件并不是系统真正的瓶颈。
这一阶段的架构关键点:标准化
上述阶段通常需要持续很长很长时间,甚至于很多公司在生命周期内都还没越过该阶段,有幸进入下个阶段后,面临的技术压力会指数级上升
业务垂直拆分(粗粒度的SOA,细粒度的微服务),数据分库分表(通常会引入中间件如Mycat等来实现),多层次Cache。
引入Zabbix监控平台,完善监控体系,包括硬件、系统级、应用级、业务级等多维度监控体系。完善自动运维及DBA流程。
系统拆分后,上下游之间如果还是通过持有对方的地址配置,将造成严重的反向依赖。这就是通常我们说的:凭什么改IP的是你,配合重启的是我。初始会采用域名代替IP的方式,但仍然有很多重复繁冗的配置工作,发展到一定程度时则会使用配置中心方案,(笔者使用过协程的Apollo,相对其它配置中心方案较轻量敏捷)。如果系统拆得更细,则还需要服务发现等服务治理框架,其中最常用的Zookeeper和Eureka。
此时有些数据处理,还使用单机Quartz定时任务已经不能胜任了,通常离线分布式计算会使用Hadoop,通过Map将任务分发给多机处理,通过Reduce汇合结果。而对于一些在线流计算,比如某大型电商通过access log实时统计PV和UV,经常会考虑使用Storm或Spark。
流控/熔断,接入层流控可以在nginx中配置,应用层的流控最见的有Hystrix。
平台化,与面向产品的方法不同,平台化是将中后台沉淀为基础能力,通过基础能力的排列组合再加个性化的前台,打造出多样化的产品,构建一致性品牌战略。
这一阶段的架构要点: 高性能、高可用、可扩展、安全性、平台化
梦醒