淘宝
淘宝
2021年06月29日入驻 合计 1 个作品 累计 9.47 万字 共有 1 订阅
  • 5.5. 新老系统过渡方案

    我们谈了很多微服务改造的点,但已有项目转微服务势必会遇到一个棘手的问题:新系统怎么替换老系统?下面我就讨论下几种主流方案。
  • 5.4. 日志追踪与收集

    微服务的特点决定了它会存在较长的调用链路,一个请求一般会跨3个以上的服务(网关->应用聚合层->服务化层)而跟踪它的调用情况是异常定位及性能优化的关键之一。要能跟踪我们势必需要在日志中记录每个请求唯一的跟踪Id,我们可以在HTTP请求或MQ接收时判断消息Header是否存在Trace_Id,如果不存在则认为是新的请求,进而生成一个UUID作为Trace_Id,如果存在则沿用这个Trace_Id,然后在打日志时加上这个Trace_Id。最后通过日志收集工具将这个本地日志收集到一个聚合平台上进行查询。这能解决问题,实际上这也是Google Dapper(《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》)的核心思路,Google Dapper是Google的日志追踪服务。
  • 5.3. 节点伸缩与故障转移

    容器化部署是微服务非常理想的选择,它可以实现上文提到的快速发布及本节要谈的自动化节点伸缩与故障转移。
  • 5.2. 服务监控

    服务监控是保证生产环境稳定最基础也是最重要的措施,微服务下尤是。如果没有成熟的一套监控方案那微服务化注定会失败!
  • 5.1. 自动化部署

    传统的服务运维对自动化的要求不需要太高,但使用微服务后服务的数量会急剧上升,一个成熟的微服务可能有几十到几百个组件,每个组件做HA,最终可能有成百上千个实例,同时还要考虑开发、测试、UAT/预发、生产、灰度等环境,人工部署将是灾难性的。
  • 4.4. 单元测试

    测试是保障软件质量的关键,对一个成熟稳定的产品而言开发的质量未必一定很高,但绝对是非常注重测试以把守好发布上线的最后一关。
  • 4.5. 可测试性设计

    单元测试的重要性不言而喻,这是所有测试的第一道关,是所有测试的基础。在微服务下会有很多个服务,对各服务组件自身的测试也会很重要,组件测试会覆盖当前服务的所有对外接口实现对各个服务的功能边界验证。单元测试和组件测试可以很好地发现各单点或各服务的问题,但它无法检查系统的流程行为,而这就需要集成测试来验证组件之间的通信路径和交互,集成测试关注的一次请求或一个业务流程是否正常,集成测试多针对接口,某些情况下我们可能会特别关注用户交互,而UI测试(或End-To-End测试)可以比较好发现这类问题。
  • 4.3. 接口管理

    接口(API)是服务能力的包装及体现,是服务提供的直接途径,也是做为服务使用方最关注的方面,一个设计合理、稳定不易变、文档清晰的接口集合是服务质量重要组成。
  • 4.2. 代码管理

    上文讲的是人员和团队,提出要将团队划小管理,那具体到开发层面,我们如何建立与之对应的工程结构及版本管控呢?
  • 4.1. 团队架构

    在传统的SOA架构中我们以系统为边界进行划分,通过标准的协议实现系统间交互,在这一体系架构下成员归属于某个具体系统,工作任务即为所属系统的需求,所对应的组织结构会相对稳定、清晰,而微服务架构以服务的粒度进行划分,要求打破系统边界实现更小粒度的服务级重用,这带来的结果是随着业务的增长技术架构的重心会越来越下沉到公共服务层,逐渐形成我们现在常说的大中台小前台体系,可以让前台业务项目做得很“薄”,这时我们发现开发一个项目原本拉一个新的业务开发团队就可以独立完成,但现在有很多公共的服务可以重用,新的业务开发团队人员会减少、项目的工期会缩短,但与之而来是需要有大量跨团队的沟通协调、开发测试工作,这就与我们之前的团队管理有比较大的区别。上面的情况会出现在服务化相对成熟的公司,对于刚开始做微服务化的公司而言没有那么多可以重用的服务,如何通过一个个项目的迭代实现从0到1的服务化建设,如何在一个中大型项目中设计符合微服务体系的团队架构成了项目成败的关键之一,这是每个项目负责人在立项时不得不考虑的问题。
  • 3.17. CP与AP的取舍

    上文我们讨论过ACID、基于2PC、TCC等方案的分布式事务、FLP Impossibility、拜占庭与非拜占庭下的领导者选择及其Paxos、Raft等实现算法,而这之中最核心的问题在于调和分布式环境的数据一致性与服务可用性。对此在2002年来自MIT的Seth Gilbert 和Nancy Lynch教授在《Brewer's conjecture and the feasibility of consistent, available, partition-tolerant web services》论文中证明了Eric Brewer于早前提出的猜想并正式确立了CAP理论。于今天而言在众多的分布式系统架构基础理论中CAP可能为人所知,本节我们花些篇通俗地介绍下CAP及其相关概念。
  • 3.16. 一致性与共识

    有某些场景下我们希望一些任务只在一个实例执行,最常用的可以考虑用MQ实现,但例如定时任务,到时间后执行一个任务,同一时间任务只能执行一次,在没有分布式调度服务的前提下我们更倾向于用一个特定的节点执行,但如何确定这个节点呢?显然我们不能只部署一个实例,这违反了高可用性要求,再考虑实例可能会宕机所以我们其实需要有一个机制可以动态找到一个特殊节点用于执行特定工作,并且在这一节点宕机后可以快速重新指定新的特殊节点,而这就是领导者选举所应对的一个典型场景。
  • 3.15. 延迟队列

    上节介绍了顺序处理,我们实际场景中还会遇到诸如这些情况,比如对页面操作记录时要求操作事件是顺序的:Beforeload必须先于Unload,事件由同一个终端设备发送,通过设备ID Hash到同一个节点服务处理,这之中不存在时钟一致性问题,但由于事件发送是异步的,所以接收可能乱序,再比如在大数据系统中分析OAuth关系,OAuth表记录的是A应用的X用户与B应用的Y用户的关联(如果B应用没有对应的用户则Y用户为新增记录),但用户表、应用表和OAuth表都是分开采集的,即不能保证分析OAuth表时用户表对应的用户就一定已经存在。对于这类需求比较通用的解决方案是使用延迟队列。
  • 3.14. 顺序处理

    绝大多数的场景下,我们的业务操作不需要保证严格的顺序处理,但在数据存储上却是最常规的要求。比如MySQL在集群模式下多节点间的数据写入顺序必然是需要一致的。在业务操作上比较典型的是数据库日志(MySQL的Biglog或Mongo的OptLog等)的同步,我们一般会订阅到Kafka,然后从Kafka异步消费,这之中就要保证消费时记录的顺序与数据库一致。
  • 3.13. 全局ID策略

    Id(Identification)是我们熟知的概念,用于标注对象身份,比如表主键、订单号、交易流水号、业务编码等,这些字段要确保全局唯一,在分布式环境下视场景的不同可以从极为简单到非常复杂,以订单号为例,不同的系统下订单号需求可能是随机的,可能是要求有顺序的,为了避免被竞争对手分析也可能要求是顺序与随机组合的(比如高位为日期,低位为随机数),不同的系统规模实现的手段可能是完全不同的,一些大型平台的Id生成服务会由成百上千个节点组成。总的来看全局Id策略的实现常见于以下几种:
  • 3.12. 幂等与去重处理

    幂等一词源自数学概念,在程序中如果相同条件下多次请求对资源的影响表现一致则称请求为幂等请求,对应的接口为幂等接口。
  • 3.11. 分布式事务实现

    事务大家都比较熟悉,主流的框架都做了很好的封装以至于我们都不用太关心其实现细节。日常开发中我们会经常使用,但这多为单机版本的事务,而本节我们要关注的是分布式事务,在讲分布式事务前我们先看下传统关系数据库中事务的ACID特性:
  • 3.10. 分布式锁使用

    锁是我们经常接触的用于保护资源避免并发竞争的工具,在JVM的发展过程中锁的演化更是历久弥新,当下我们可以用公平锁实现顺序排队用非公平锁实现优先级管理,用可重入锁减少死锁的几率,用读写锁提升读取性能,JVM更是实现了从偏向锁到轻量级锁再到重量级锁的逐渐膨胀优化,更多的情况下我们还可以基于CAS 的原子操作包(java.util.concurrent.atomic)实现无锁(乐观锁)编程。
  • 3.9. 缓存设计

    缓存的重要性无需多言,合理的缓存设计既可以提升系统的性能又兼具一定的防攻击能力。
  • 3.8. 可降级设计

    接上文书,服务各接口要考虑熔断与降级,这更偏向于技术手段及具体的接口或服务,我们的系统由众多的服务组成,在系统层面上也必须考虑整体的可降级设计,而这更偏向于业务设计。
  • 前一页 后一页