云时代架构阅读笔记十六——架构设计思维(二)
架构的演变:
1、单体架构:Web应用程序发展的早期,在开发服务端企业应用时,应用需要支持各种不同类型的客户端,比如桌面浏览器、移动浏览器以及原生移动应用。应用还需要向第三方提供可访问的API,并通过Web Service或者消息代理与其它应用实现集成。大部分web工程是将所有的功能模块(service side)打包到一起并放在一个web容器中运行,很多企业的Java应用程序打包为war包。应用通过执行业务逻辑、访问数据库、与其它系统交换信息、并返回一条HTML/JSON/XML响应,来处理请求(HTTP请求与消息)。
2、SOA架构:
SOA架构,是一种粗粒度、开放式、松耦合的服务结构,要求软件产品在开发过程中,按照相关的标准或协议,进行分层开发。通过这种分层设计或架构体系可以使软件产品变得更加弹性和灵活,且尽可能的与第三方软件产品互补兼容,以达到快速扩展,满足或响应市场或客户需求的多样化、多变性。
3、微服务架构:微服务是一种用于构建应用的架构方案。微服务架构有别于更为传统的单体式方案,可将应用拆分成多个核心功能。每个功能都被称为一项服务,可以单独构建和部署,这意味着各项服务在工作(和出现故障)时不会相互影响。是应用的各项核心功能,而且这些服务均可独立运行。但是,微服务架构不只是应用核心功能间的这种松散耦合,它还涉及重组开发团队、涉及如何进行服务间通信以应对不可避免的故障、满足未来的可扩展性并实现新的功能集成。
集成方式:
1、 点对点方式:点对点方式中,服务之间直接用。每个微服务都开放REST API,并且调用其它微服务的接口。
2、 网关方式:API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能个。通常,网关也是提供REST/HTTP的访问API。服务端通过API-GW注册和管理服务。
3、 消息代理方式: 微服务也可以集成在异步的场景下,通过队列和订阅主题,实现消息的发布和订阅。一个微服务可以是消息的发布者,把消息通过异步的方式发送到队列或者订阅主题下。作为消费者的微服务可以从队列或者主题共获取消息。通过消息中间件把服务之间的直接调用解耦。
集成难点:
1、数据服务设计:
一库一服or一库多服:
无论是单体应用,还是微服务应用,有一点是肯定的:应用的各个模块之间都需要进行较为频繁的通信,通过一起协同合作,来实现应用的整体价值。在单体应用中,这种通信是通过方法调用来完成的。在微服务中,则通过 API 调用来完成。这些模块或者服务间调用,大部分时候是为了共享数据。 共享数据最贱的方式当然就是采用一种共享数据库的模式,也就是单体应用常用的方式 - 应用可以有多个系统模块,但一般都是只有一个数据库。
混合持久化:
混合持久化在大型互联网公司是一个比较风行的模式,它秉承的原则就是为特别的任务提供最好的工具。比如说某个系统提供一个高并发低延迟的共享用户会话方案 (shared session storage), Redis 可能是一个非常理想的选择。如果是实现一个产品目录,涉及到大量不定结构的商品数据及属性的建模管理,系统可能会采用模式灵活,动态 schema 的 MongoDB 来作为我的数据库解决方案。如果系统希望支持非常强大的全文搜索,ElasticSearch 则是行业中的佼佼者。
2、数据一致性:一种比较常见的做法就是使用分布式事务来搞定,比如2PC等。但是这种做法对于现代应用来说也许不是一种可行的方案。CAP定理要求你必须在可用性和一致性之间选择,可用性通常是较好的选择。而且,许多现代技术,例如大多数NoSQL数据库,甚至不支持ACID事务,更不用说2PC。所以管理数据的一致性需要使用其他的方式。我们使用事件驱动架构中的一种技术叫事件源(event sourcing)来解决分布式事务。
Event sourcing (事件源)通过使用根本不同的事件中心方式来获得不需2PC的原子性,保证业务实体的一致性。 这种应用保存业务实体一系列状态改变事件,而不是存储实体现在的状态。应用可以通过重放事件来重建实体现在状态。只要业务实体发生变化,新事件就会添加到时间表中。因为保存事件是单一操作,因此肯定是原子性的。
3、分布式查询:实现查询的好方法是使用称为命令查询责任分离(CQRS)的体系结构模式: Command Query Responsibility Segregation。如名称所示,CQRS将应用程序分为两部分。第一部分是命令侧(command-side),其处理命令(例如,HTTP POST,PUT和DELETE)以创建,更新和删除聚合。前提是这些聚合是使用事件源实现的。应用程序的第二部分是查询侧(query-side),其通过查询聚合的一个或多个物化视图(materialized views)来处理查询(例如HTTP GET)。查询侧通过订阅由命令侧发布的事件来保持视图(view)与聚合(aggregate)同步。查询侧(query-side)视图可以使用任何类型的能满足需求的数据库来实现。根据需求,应用程序的查询端可能使用一个或多个以下数据库;在很多场合,CQRS是一个以事件为基础(event-based)的综合体,比如使用RDBMS作为记录系统再使用比如Elasticsearch来处理文本查询。CQRS的查询侧可以使用其它类型的数据库,支持多种类型的数据库,不仅仅是文本搜索引擎。而且,它通过订阅事件准实时地去更新查询侧的视图。