下面看一下AKF的拆分实践。
- 拆分应用
x轴:从单体系统或服务,水平克隆出许多系统,通过负载均衡平均分配请求。
y轴:面向服务分割,基于功能或者服务分割,例如,电商网站可以将登录、搜索、下单等服务进行y轴的拆分,每一组服务再进行x轴的扩展。
z轴:面向查找分割,基于用户、请求或者数据分割,例如,可以将不同产品的SKU分到不同的搜索服务,可以将用户哈希到不同的服务等。
- 拆分数据库
x轴:从单库水平克隆为多个库上读,一个库写,通过数据库的自我复制实现,要允许一定的读写时延。
y轴:根据不同的信息类型分割为不同的数据库,即分库,例如,产品库、用户库等。
z轴: 按照一定算法进行分片, 例如,将搜索按照MapReduce 的原理进行分片,把SKU的数据按照不同的哈希值进行分片存储,每个分片再进行x轴冗余。
要做好微服务的分层:梳理和抽取核心应用、公共应用,作为独立的服务下沉到核心和共能力层,逐渐形成稳定的服务中心,使前端应用能更快速地响应多变的市场需求。
对于服务的拆分,要使用迭代演进的方式,不能一次性 完成所有的服务的拆分,需要确保团队可接受,粒度适中,同时需要优先考虑API的版本兼容性。不能够单纯以代码量来对服务拆分的成果进行评估。
设计原则之前后端分离
==========
在传统的Web应用开发中,大多数的程序员会将浏览器作为前后端的分界线。将浏览器中为用户进行页面展示的部分称之为前端,而将运行在服务器,为前端提供业务逻辑和数据准备的所有代码统称为后端。
由于前后端分离这个概念相对来说刚出现不久,很多人都是只闻其声,不见其形,所以可能会对它产生一些误解,误以为前后端分离只是一种Web应用开发模式,只要在Web应用的开发期进行了前后端开发工作的分工就是前后端分离。
其实前后端分离并不只是开发模式,而是Web应用的一种架构模式。 在开发阶段,前后端工程师约定好数据交互接口,实现并行开发和测试;在运行阶段前后端分离模式需要对Web应用进行分离部署,前后端之前使用HTTP或者其他协议进行交互请求。
前后端分离原则,简单来讲就是前端和后端的代码分离,也就是技术上做分离。推荐的模式是直接采用物理分离的方式部署,进一步进行更彻底的分离。不要继续使用以前的服务端模板技术,比如JSP,把Java JS HTML CSS都堆到一个页面里,稍复杂的页面就无法维护。
这种分离模式的方式有几个好处:
-
前后端技术分离,可以由各自的专家来对各自的领域进行优化,这样前端的用户体验优化效果会更好。
-
分离模式下,前后端交互界面更加清晰,就剩下了接口和模型,后端的接口简洁明了,更容易维护。
-
前端多渠道集成场景更容易实现,后端服务无需变更,采用统一的数据和模型,可以支撑前端的WebUI/移动App等访问。
前后端分离意味着前后端之间使用JSON来交流,两个开发团队之间使用API作为契约进行交互。从此,后台选用的技术栈不影响前台。
前后端分离并非仅仅只是前后端开发的分工,而是在开发期进行代码存放分离、前后端开发职责分离,前后端能够独立进行开发测试;在运行期进行应用部署分离,前后端之间通过HTTP请求进行通信。前后端分离的开发模式与传统模式相比,能为我们提升开发效率、增强代码可维护性,让我们有规划地打造一个前后端并重的精益开发团队,更好地应对越来越复杂多变的Web应用开发需求。
前后端分离的核心:后台提供数据,前端负责显示。
设计原则之版本控制
=========
在团队的内部,尤其是API设计优先的微服务架构中,接口的版本管理显得尤其重要。
微服务的一个主要优势是,允许服务独立地演变。考虑到微服务会调用其他服务,这种独立性需要引起高度注意,不能在API中制造破坏性更改。
接纳更改的最简单方法是绝不破坏API。如果遵循稳健性原则,而且两端都保守地发送数据,慷慨地接收数据,那么可能很长一段时间都不需要执行破坏性更改。当最终发生破坏性更改时,可以选择构建一个完全不同的服务并不断退役原始服务,原因可能是领域模型已进化,而且一种更好的抽象更有意义。
如果对现有服务执行破坏性的API更改,应决定如何管理这些更改:
该服务是否会处理API的所有版本?是否会维护服务的独立版本,以支持API的每个版本?服务是否仅支持API的最新版本,依靠其他适应层来与旧API来回转换?在确定了困难部分后,如何在API中反映该版本是更容易解决的问题。
通常可通过3种方式处理REST资源的版本控制。
- 将版本放入URI中
将版本添加到URI中,这是指定版本的最简单方法。它的优点是非常容易理解,容易在微服务应用构建服务时实现,与API浏览工具和命令行工具兼容。如果将版本放在URI中,版本应该会应用于整个应用程序,所以使用/api/vl/accounts而不是/api/accounts/v1。
- 使用自定义请求标头
可以添加自定义请求标头来表明API版本。在将流量路由到特定后端实例时,路由器和其他基础架构可能会考虑使用自定义标头。但是,此机制不容易使用,原因与Accept标头不容易使用相同。此外,它是一个仅适用于应用程序的自定义标头,这意味着使用者需要学习如何使用它。
- 将版本放在HTTPAccept标头中,并依靠内容协商
Accept标头是一个定义版本的明显位置,但它是最难测试的地方之一。URI 很容易指定和替换,但指定HTTP标头需要更详细的API和命令行调用。
设计原则之围绕业务构建
===========
正所谓“不围绕业务构建的架构就是耍流氓"。
微服务应当聚焦于某一特定的业务功能,并且确保完成它。其实这给需求管理也带来了挑战,需求需要切分将更加精细,以满足系统业务的不断变化。在传统的方式中,一般是产品人员进行需求调研,然后经过整理后提交给开发团队,这种方式在微服务的环境下需要重新定义,即产品核实需求后,需要在提交给开发团队之前进行评审,评审需要开发团队的人员参与,确认无误后再提交给开发团队。
从技术上说,微服务不应该局限于某个技术栈或者后端存储,可以非常灵活,以便于解决业务问题。这一点在非微服务的系统设计时,可能导致我们做一些妥协。而微服务可以让你用你认为最合适的方式解决问题。这和上面的统一框架 并不冲突,统一是指构建团队的过程中,尽量保持统一.的架构,从而降低交互和沟通所带来的额外成本。
系统可以根据业务切分为不同的子系统,子系统又可以根据重要程度切分为核心和非核心子系统。切分的目的就是当出现问题时,保证核心业务模块正常运行,不影响业务的正常操作。同时解决各个模块子系统间的耦合、维护及拓展性。方便单独部署,确保当一个系统出现问题时,不会出现连锁反应而导致整个系统瘫痪。
各个系统间合理地使用消息队列,解决系统或模块间的异步通信,实现高可用、高性能的通信系统。
设计原则之 CAP
=========
CAP原则又称CAP定理,指的是在一个分布式系统中,Consistency (一致性)、Availability(可用性)和Partition tolerance (分区容错性),三者不可兼得。
下面对分布式系统中的三个特性进行了归纳。
-
一致性 ©:在分布式系统中的所有数据备份在同一时刻是否有同样的值。
-
可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。
-
分区容忍性§:以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
掌握CAP定理,尤其是能够正确理解C、A、P的含义,对于系统架构来说非常重要。因为对于分布式系统来说,网络故障在所难免,如何在出现网络故障时,维持系统按照正常的行为逻辑运行就显得尤为重要。可以结合实际的业务场景和具体需求来进行权衡。
例如,对于大多数互联网应用来说,因为机器数量庞大,部署节点分散,网络故障是常态,可用性是必须要保证的,所以只有舍弃一致性来保证服务的AP。而对于银行等需要确保一致性的场景,通常会权衡CA和CP模型,CA模型网络故障时完全不可用,CP模型具备部分可用性。所以,在设计微服务的时候一定要选择合适的模型。
CA (consistency + availability),这样的系统关注一致性和可用性, 它需要非常严格的全体一致的协议,比如“两阶段提交”(2PC)。CA系统不能容忍网络错误或节点错误,一旦出现这样的问题,整个系统就会拒绝写请求,因为它并不知道对面的那个结点是否挂掉了,还是只是网络问题。唯一安全的做法就是把自己变成只读的。
CP (consistency + partition tolerance),这样的系统关注一致性和分区 容忍性。它关注的是系统里大多数人的一致性协议,比如Paxos算法(Quorum 类的算法)。这样的系统只需要保证大多数节点数据一致,而少数的节点会在没有同步到最新版本的数据时变成不可用的状态,这样能够提供一部分的可用性。
AP (availability + partition tolerance),这样的系统关心可用性和分区容忍性。因此,这样的系统不能达成一致性,需要给出数据冲突,给出数据冲突就需要维护数据版本,Dynamo 就是这样的系统。
设计原则之数据一致性
==========
数据一致性分为以下几种情况。
- 强一致性
当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值。这种是对用户最友好的,就是用户上一次写什么,下一次就保证能读到什么。根据CAP理论,这种实现需要牺牲可用性。
- 弱一致性
系统并不保证后续进程或者线程的访问都会返回最新的更新过的值。系统在数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体地承诺多久之后可以读到。
- 最终一致性
弱一致性的特定形式。系统保证在没有后续更新的前提下,系统最终返回上一次更新操作的值。在没有故障发生的前提下,不一致窗口的时间主要受通信延迟、系统负载和复制副本的个数影响。DNS是一个典型的最终一致性系统。
在工程实践上,为了保障系统的可用性,系统大多将强一致性需求转换成最终一致性的需求,并通过系统执行幂等性来保证数据的最终一致性。
微服务架构下,完整交易跨越多个系统运行,事务一致性是-一个极具挑战的话题。依据CAP理论,必须在可用性(Avaliablitity) 和一致性(Consistency) 之间做出选择。我们认为在微服务架构下应选择可用性,然后保证数据的最终一致性。
在实践中有三种模式:可靠事件模式、业务补偿模式和TCC模式。