从SpringCloud开始,聊微服务架构
背景
随着公司业务量的飞速发展,平台面临的挑战已经远远大于业务,需求量不断增加,技术人员数量增加,面临的复杂度也大大增加。在这个背景下,平台的技术架构也完成了从传统的单体应用到微服务化的演进。
系统架构的演进过程
单一应用架构(第一代架构)
这是平台最开始的情况,当时流量小,为了节约成本,并将所有应用都打包放到一个应用里面,采用的架构为.net+sqlserver:
表示层 位于最外层(最上层),最接近用户。用于显示数据和接收用户输入的数 据,为用户提供一种交互式操作的界面,平台所使用的是基于.net的web形式。
业务逻辑层 业务逻辑层(Business Logic Layer)无疑是系统架构中体现核心价值的部分。它的关注点主要集中在业务规则的制定、业务流程的实现等与业务需求有关的系统设计,也即是说它是与系统所应对的领域(Domain)逻辑有关,很多时候,也将业务逻辑层称为领域层。 业务逻辑层在体系架构中的位置很关键,它处于数据访问层与表示层中间,起到了数据交换中承上启下的作用。由于层是一种弱耦合结构,层与层之间的依赖是向下的,底层对于上层而言是“无知”的,改变上层的设计对于其调用的底层而言没有任何影响。如果在分层设计时,遵循了面向接口设计的思想,那么这种向下的依赖也应该是一种弱依赖关系。对于数据访问层而言,它是调用者;对于表示层而言,它却是被调用者。
数据层 数据访问层:有时候也称为是持久层,其功能主要是负责数据库的访问,可以访问数据库系统、二进制文件、文本文档或是XML文档,平台在这个阶段使用的是hibernate.net+sqlserver。
第一代架构看似很简单,却支撑了平台的早期业务发展,满足了网站用户访问量在几万规模的处理需求。但是当用户访问量呈现大规模增长,问题就暴露出来了:
- 维护成本不断增高:当出现故障时,有可能引起故障的原因组合就会比较多,这也会导致分析故障、定位故障、修复故障的成本相应增高,故障的平均修复周期会花费很多时间,并且任何一个模块出现故障将会影响其它应用模块;在开发人员对全局功能缺乏深度理解的情况下,修复一个故障,经常引入其他的故障,导致该过程陷入“修复越多,故障越多”的恶性循环。
- 可伸缩性差:应用程序的所有功能代码都运行在同一个服务器上,将会导致应用程序的水平扩展非常困难,只能使用垂直扩展。
- 交付周期变长:应用程序做任何细微的修改以及代码提交,都会触发对整个应用程序进行代码编译、运行单元测试、代码检查、构建并生成部署包、验证功能等,这也就版本的反馈周期变长,单位时间内构建的效率变得很低。
- 新人培养周期变长:随着应用程序的功能越来越多,代码变得越来越复杂的同时,对于新加入团队的成员而言,了解业务背景、熟悉应用程序、配置本地开发环境,这些看似简单的任务,却会花费了更长的时间。
垂直应用架构(第二代架构)
为了解决第一代架构面临的问题,团队制定了如下的策略,并形成了第二代应用架构(垂直应用架构)
- 应用拆成独立的应用模块。
- 各个应用模块独立部署,并在负载均衡通过session保持解决应用模块的水平扩展问题。
Sticky就是基于cookie的一种负载均衡解决方案,通过cookie实现客户端与后端服务器的会话保持, 在一定条件下可以保证同一个客户端访问的都是同一个后端服务器。请求来了,服务器发个cookie,并说:下次来带上,直接来找我!。在项目中,我们使用了taobao开源的tengine中的session_sticky模块。
- 数据库拆分成不同数据库,由对应应用访问。
- 域名拆分。
- 动静分离。
可以看到第二代架构解决应用级别的水平扩展扩展,经过优化后,该架构支撑了几十万用户的访问需求,在这一阶段有部分应用已经使用java 完成了mvc架构的重写。当然也存在一些问题。
- 应用之间耦合度高,相互依赖严重。
- 应用模块之间交互复杂,有时直接访问对方模块数据库。
- 数据库涉及过多的关联查询与慢查询,数据库优化困难。
- 数据库单点访问严重,出现故障无法恢复。
- 数据复制问题严重,造成大量数据不一致。
我们曾经尝试使用sql server AlwaysOn 解决扩展问题,但是实验发现在复制过程中出现至少10s的延迟,因此放弃了这个方案。
- 系统扩展困难。
- 各个开发团队各自为战,开发效率低下。
- 测试工作量巨大,发布困难。
微服务化架构(平台现状:第三代架构)
为了解决第一代与第二代架构存在的问题,我们对平台进行了梳理优化。根据平台业务需要以及对第一二代架构的总结,我们确定了第三代架构的核心需求:
- 核心业务抽取出来,作为独立的服务对外服务。
- 服务模块持续独立部署,减少版本交付周期。
- 数据库按服务分库分表。
- 大量使用缓存,提高访问。
- 系统间交互使用轻量级的rest协议,摒弃rpc协议。
- 去.net化,开发语言使用java来实现。
并以此为基础进行了平台的第三代架构的重构工作。
看第三代架构里面的组成,主要分为八个部分:
-
CDN:CDN系统负责实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。
平台在选择CDN厂商时,需要考虑经营时间长短,是否有可扩充的带宽资源、灵活的流量和带宽选择、稳定的节点、性价比;综合前面几个因素平台采用了七牛的CDN服务。
-
LB层:平台包括很多个业务域,不同的业务域有不同的集群,LB层(Load Balancer)是对多台业务服务器进行流量分发的负载均衡服务,通过流量分发扩展应用系统对外的服务能力,并消除单点故障提升了应用系统的可用性。
选择哪种负载,需要综合考虑各种因素&#