CRM重构之——微服务设计导读(二)

之前,我们对于《微服务设计》前四章进行了导读,接下来跟着我继续阅读5~8章吧!

(微服务设计/(英)纽曼 著;崔力强,张骏译)

导读

第五章主要简述如何才能循序渐进把一个单块系统分解成可重用的小系统。我们原先的SIEBEL系统能借用的比较少,几乎是重建;

第六章 简述部署对微服务的影响;

第七章 深入测试主题,测试在部署多个分散的服务时很重要;

第八章 简述了监控的颗粒度,以及如何应对分布式系统的复杂性。

正文章节

目录简介

Part5:分解单块系统

Part6:部署

Part7:测试

Part8:监控

章节内容

Part5:分解单块系统

关键词

接缝、分离

关键是接缝,在单体系统里修改一行代码很容易,但是无法保证这一行修改不会对单体系统的其他部分造成影响,而且为了发布这个功能,我们还需要把整个系统重新部署一次。接缝,从接缝处可以抽取出相对独立的一部分代码,对这部分代码进行修改不会影响系统的其他部分,识别出接缝不仅仅能清理代码库,更重要的是,这些被识别出的接缝可以成为服务的边界。

在抽离时不要为了抽离而抽离,增量抽离并考虑哪些代码抽离出去得到的利益最大,团队结构、安全、技术等因素。

打破外键关系,通过暴露的API进行数据访问,而不是直接访问数据库,这时你会发现需要做两次数据库调用,对做成独立服务后就是这样,这时有人会担忧性能,那给出的答案很简单:你的系统需要多快?系统现在是多快?有时候让系统的一部分变慢会带来更大的好处,尤其是当这个“慢”事实上是还可以接受的时候。

共享静态数据分分离可以放入配置文件或者代码中解决。

共享可变数据的分离对系统来说是个大麻烦。需要具象化领域概念,例如把穿插在客户服务中的财务信息、仓库信息独立出单独的财务服务和仓库服务。对共享表也是拆分为独立的表。在这些拆分后,对于原先某个动作而言,对数据库的访问次数可能会变多,因为以前一个select语句就能得到所有的数据,现在则需要到不同的地方拿数据,然后在内存中了连接,事务可以帮助我们的系统从一个一致的状态迁移到另一个一致的状态,要么都完成要么都不变,在修改数据库时这点非常有用。分布式事务的常用算法是两阶段提交,但会有很多制约。(第11章再会详细阐述)

我们已经注意到在对单体系统分离时,也需要对数据存储进行分离,其中报表的数据获取方式不建议用标准的HTTP方式,会有额外的开销,也不建议专用API或批量API,还是建议独立的程序直接访问并把数据导出到单独的报表数据库。

需要理解的是,服务一定会慢慢变大的,直到大的需要拆分,我们希望系统架构随着时间的推移增量进行变化,而且要在拆分变得太过昂贵之前进行服务的拆分。

Part6:部署

关键词

CI、CD、单主机单服务

持续集成,CI(Continuous Intergration),CI能够保证新提交的代码与已有代码进行集成,从而让所有人保持同步。通过CI,我们能够得到关于代码质量的某种程度的快速反馈,并可以通过已部署的构建物回溯到相应的代码,并可以使这些代码和构建物上运行过的测试可视化。

如何判断是否在做CI,是否有签入代码到主线?是否有一组测试来验证修改?当构建失败后,团队是否把修改CI当作第一优先级的事情来做?

把持续集成映射到微服务,每个微服务都有自己的代码库,分别与相应的CI映射和构建,这样在部署到生产环境之前都可以独立做个快速验证,每个微服务相关的测试也应该和其本身的代码放在一起,这样很容易知道对于某个服务来说应该运行哪些测试。

CD(Continuous Delivery)持续交付:构建流水线可以很好地跟踪软件构建进度和质量。构建物在整个构建的第一个环节生产,然后会被应用在整个流水线中,通过各个不同的阶段。

大多数技术栈都有相应的构建物类型,Ruby有gem,Java有JAR包和WAR包,为了部署和启动这些构建物,需要安装配置一些其他软件,然后启动这些构建物。不同技术栈生成的构建物各不相同,混合不同的构建物进行部署就会很复杂。有一种方法避免多种技术栈下的构建物所带来的问题,那就是用操作系统支持的构建物。例如,CentOS,可以用RPM,对于Windows可以用MSI。但一开始构建脚本的过程会比较困难,而且要避免多种操作系统。

通过创建虚拟机镜像可以减少配置管理工具的启动时间,现有VMWare构建时间会比较长,而且空间占用比较大,容器技术Docker,它可以避免这些问题。镜像是对不同技术栈的抽象,我们不需要关心运行在镜像中的服务、语言、构建物,只需要关心其是否工作,然后把精力放在镜像创建和部署的自动化即可,不可变服务器。

CD流水线涉及的四个环境:用来运行耗时测试的环境,UAT,用于性能测试的环境,生产环境。

主机,即能运行服务的一个操作系统,每个台主机应该有多少个服务?

单主机多服务模式对监控是挑战,服务之间资源的相互影响是不可避免的;其次,对部署也是挑战,因为很难保证一个服务部署不会影响其他的服务;对团队自治也是挑战,需要更多的人协同才能完成服务的部署;最后,这个模式也会限制构建物的选择。

每个主机一个服务模式,这种模式避免了之前的问题,简化了监控和错误恢复,也可以减少潜在故障点,而且支持不同的部署技术,缺点是主机数量增加是个问题,需要管理更多的服务器。

平台即服务PaaS,应用程序越不标准,就越难一起和PaaS进行工作

单主机单服务模式会引入很多主机,从而产生很多管理开销,如果我们将主机控制、服务部署自动化,那工作量就不会随着主机数量增加而增加。

标准虚拟化(略),基于容器的虚拟化,Docker是构建在轻量容器之上的平台,屏蔽底层实现服务的技术,缓解运行多服务进行本地开发和测试的问题。Docker本身并不能解决所有的问题,它知识一个在单机上运行的简单PaaS,还需要一些工具来解决跨多台机器管理实例的服务,例如K8S。

总结:一个服务一个代码库,每个微服务一个CI实现独立部署,每个服务单独的主机/容器,自动化非常重要。

Part7:测试

关键词

分类、CDC、发布

使用微服务架构后,测试的复杂度进一步增加,如何高效且有效测试分布式系统的功能依然是个挑战。

不同的测试分类:敏捷测试的测试象限。象限底部的是面向技术的测试,这个可以大部分自动化,例如性能测试和小范围的单元测试;处于象限顶部的测试是帮助非技术背景的人了解系统是如何工作的,包括了左上角的大部分、端到端测试及右上角的由用户代表在UAT上进行的探索性测试。

手工测试是很用的,也有存在的必要,但放弃大规模的手工测试,尽可能地多使用自动化是近年的业界趋势,测试微服务架构的系统和测试独立系统的区别,很大程度上在于各种类型的自动化测试。如果当前你正在使用大量的手工测试,建议在深入微服务之前,先解决这个问题,否则很难获得微服务架构带来的好处,因为你无法快速有效地验证软件。

“测试金字塔”模型,把自动化测试划分为以下三层。

单元测试

单元测试通常只测试一个函数和方法调用,对于代码重构非常重要;

服务测试

服务测试是绕开用户界面直接针对服务的测试,打桩可以验证功能,mock可以用来验证预期的副作用;

端到端测试

端到端测试会覆盖整个系统,但是端到端测试有很多缺点,测试运行起来比较慢,定位失败也更加困难,特别是当流水线扇入到端到端测试中,测试中的服务数量越多,测试会越脆弱,不确定性也就越强;其次,这些测试是某服务流水线的一部分,一个合理的想法是,拥有这些服务的团队应该写这些测试,当端到端测试被多个团队共享时,谁该负责和维护这些测试?现在通常的一个答案是由一个专门的团队来写这些测试,这可能是灾难性的,开发软件的人渐渐远离测试代码,周期会变长,因为服务的拥有者实现功能需要等待测试团队来写端到端测试,因为这些测试是由别的团队编写,实现服务的团队很少参与,所以很难了解如何运行和修复这些测试,这是一个非常常见的组织模式,只要团队没有在第一时间测试自己所写的代码,就会出现很大的问题。最好的平衡方式是共享端到端测试套件的代码权,同时对测试套件联合负责,但实际上很少能做到这样的。测试周期长,大量的堆积,在测试环节将多个服务一同部署的耦合将逐步丢弃微服务的主要优势。太糟糕了。

CDC消费者驱动的契约(Consumer-Driven Contract)确保部署新服务到生产环境后,变更不会破坏新服务的消费者。当使用CDC时,我们会定义服务(生产者)的消费者期望,这些期望最终会变成对生产者的测试代码,这些CDC是CI流水线的一部分,当这些契约被破坏时,生产者就无法部署,更重要的是,因为只针对生产者运行这些CDC测试,它比要解决同样问题的端到端测试范围更小更快。一个好的实践是,生产者和消费者团队协作来写这部分的测试,所有对下游的依赖都可以使用打桩。某种意义下,测试团队正在更多靠近开发团队的特质

Pact是一个消费者驱动的测试工作,Ruby语言支持JVM和.NET版本。

随着时间的推移,我们会逐步意识到CDC工具和更好的监控来代替端到端测试,当然并不意味要全部扔掉端到端测试,端到端测试可以辅助服务部署到生产环境,形成一个安全网,这是在周期时间和低风险之间的取舍。还有,再怎么测试也不可能消除所有的缺陷,所以在生产环境中有效监控和修复是有必要的,从生产环境中学习是个明智的决定。

蓝绿布署

蓝绿部署是不停用老版本,部署新版本然后进行“冒烟测试”,确认OK后,将流量切到新版本,然后老版本同时也升级到新版本。蓝绿部署无需停机,并且风险较小. 在非隔离基础架构( VM 、 Docker 等)上执行蓝绿部署,蓝色环境和绿色环境有被摧毁的风险。

滚动发布

(略)

灰度发布

灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式。AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度,而我们平常所说的金丝雀部署也就是灰度发布的一种方式 。灰度发布比蓝绿发布部署需要更复杂的配置和更多的思考。

有时花费相同的努力让发布变更变得更好,比添加更多的自动化功能测试更加有益。这通常是平均故障间隔时间,MTBF(Mean Time Between Failure)和平均恢复时间MTTR(Mean Time To Restoration)之间的权衡。

性能测试让我们纠结是否要准备真正的类似生产环境,性能测试对追踪性能的瓶颈仍然仍然是有价值的,但需要注意结果有时可能是假阴性,甚至是假阳性。性能测试需要与系统监控同时进行,理想情况下,应该在性能测试环境下使用与生产环境相同的可视化工具。

Part8:监控

关键词

监控领域标准化

微服务架构增加了生产系统的监控复杂性,监控小的服务,然后聚合起来看整体。

无论是单一服务单一主机,还是多个服务,多个主机,首先,我们需要监控主机本身,CPU,内存等数据,我们要知道系统健康的时候,它们是怎样的,当它们超出边界时,就可以预警;接下来,我们要看服务器本身的日志;最后我们要监控应用程序本身。总之,从日志到应用程序指标,集中收集和聚合尽可能多的数据。

Logstash是一款轻量级的日志搜集处理框架,可以方便的把分散的、多样化的日志搜集起来,并进行自定义的处理,然后传输到指定的位置,比如某个服务器或者文件。Kibana是一个基于ElasticSearch查看日志的系统。

尽可能暴露一切数据,然后依靠指标系统对它们处理。使用关联标识来跟踪多个服务的调用。级联故障特别危险,当网络链接瘫痪了,服务本身是健康的,但它们之间无法交互,如果仅看这个服务的健康状态,我们不会知道已经出了问题,使用合成监控,会将问题暴露出来,我们需要报告出一个服务无法访问另一个服务的情况。每个服务实例都应该追踪和显示其下游服务的健康状态。可以使用库实现一个断路网络调用,以帮助你及时处理级联故障和功能降级。

监控领域的标准化至关重要,服务之间使用多个接口,以很多不同的方式合作为用户提供功能,你需要以整体视角查看系统,标准的方式记录日志,需要为度量提供一个标准名称的列表。

对每个服务而言

最低限度要跟踪请求响应时间,做好之后,可以跟踪错误率和应用程序的指标

最低限度要跟踪所有下游服务的健康状态,包括下游调用的响应时间,最好能够跟踪错误率

标准化如何收集指标及储存指标

如果可能的话,以标准的格式将日志记录到一个标准位置

监控底层操作系统,这样可以跟踪流氓进程和进行容量规划

对系统而言

聚合CPU之类的主机层级的指标及应用程序级指标

确保你选用的指标存储工具可以在系统和服务级别做聚合,同时也允许你查看单台主机的情况

确保指标存储工具允许你维护数据足够长的时间,以了解你的系统趋势

使用单个可查询工具对日志进行聚合和存储

标准化关联标识的使用

了解什么样的情况需要行动,并根据这些信息构造相应的警报和仪表盘

调查对各种指标聚合方式做统一化的可能

• 待续 •

柳林志

文:陈孚

编辑:赵晓燕,徐梦

图片:来源于网络

  • 发表于:
  • 原文链接:http://kuaibao.qq.com/s/20171228G0JMQ400?refer=cp_1026

相关快讯

扫码关注云+社区