目录
读书笔记:微服务设计
/  

读书笔记:微服务设计

第1章 微服务

微服务就是一些小而自治的服务
很小,专注于做好一件事。单一职责:把因相同原因而变化的东西聚合在一起,而把因不同原因而变化的东西分离开来。使用用的服务越小,独立性带来的好处就越多。但是管理大量服务也会越复杂。
自治性。一个微服务就是一个独立的实体。
主要的好处:技术异构性;弹性,处理服务不可用和功能降级问题;扩展,可以只对需要扩展的服务进行扩展;简化部署;与组织结构相匹配;可组合性;对可替代性的优化。

第2章 演化式架构师

架构师的一个重要职责是,确保团队有共同的技术愿景,以帮助我们向客户交付他们想要的系统。
我们将架构师比做城市规划师。作为架构师,不应该过多关注每个区域内发生的事情,而应该多关注区域之间发生的事情。这意味着我们应该考虑不同的服务之间如何交互,或者说保证我们能够对整个系统的健康状态进行监控。应该担心服务之间的交互,而不需要过多关注各个服务内部发生的事情。
战略目标关心的是公司的走向以及如何才能让自己的客户满意。
能够清晰地描绘出跨服务系统的健康状态非常关键。这必须是系统级别而非单个服务级别进行考虑,建议确保所有的服务使用相同的方式报告健康状态及其与监控相关的数据。
架构师的职责就是从更高的层次出发,理解如何做权衡。理解技术债的层次及其对系统的影响非常重要。
技术治理:架构师的一个职责是确保有一个技术愿景,那么治理就是要确保我们构建的系统符合这个愿景,而且需要的时候还应对愿景进行演化。
架构师需要确保有一组可以指导开发的原则,并且这些原则要与组织的战略相符。还需要确保,以这些原则为指导衍生出来的实践不会给开发人员带来痛苦。需要了解新技术,需要之道在什么时候做怎样的取舍,同时还需要让同事也理解这些决定和取舍,并且执行下去。
演进式架构师应该承担的职责:
愿景:确保在系统有一个经过充分沟通的技术愿景,这个愿景应该可以帮助你满足组织的需求。
同理心:理解你所做的决定对客户和同时带来的影响。
合作:和尽量多的同事进行沟通,从而更好的对愿景进行定义、修订及执行。
适应性:确保在你的客户和组织需要的时候调整技术愿景。
自治性:在标准化和团队之间寻找一个正确的平衡点。
治理:确保系统按照技术愿景的要求实现。
演进式架构师应该理解,成功要靠不断地取舍来实现。

第 3 章 如何建模

什么样的服务是好服务?
松耦合,能够独立修改及部署而不需要修改系统的其他部分。一个松耦合的服务应该尽可能少地知道与之协作的那些服务的信息。这意味着,应该限制两个服务之间不同调用形式的数量,除了潜在的性能问题之外,过渡的通信可能会导致紧耦合。
高内聚,找到问题的边界就可以确保相关的行为能放在同一个地方,并且它们会和其他边界以尽量松耦合的形式进行通信。
界限上下文:一个显式边界限定的特定职责。每个上下文都有明确的接口,该接口决定了它会暴露哪些模型给其他上下文。
应该共享特定的模型,而不应该共享内部表示。
微服务应该清晰地和界限上下文保持一致。
过早讲一个系统划分成微服务的代价特别高,尤其是在面向新领域时。很多时候,将一个已有的代码库划分成微服务,要比从头开始构建微服务简单的多。

第4章 集成

寻找理想的集成技术:避免破坏性修改;保证 API 的技术无关性;使你的服务易于消费方使用;隐藏内部实现细节。
编排(orchestration),依赖某个中心大脑来指挥并驱动整个过程;系统(choreography),仅仅告知系统中各个部分各自的职责,而把具体怎么做的细节留给他们自己。通常来说,使用协同的方式可以降低系统耦合性,并且你能更加灵活地对现有系统进行修改。
不要对远程调用过渡抽象,以至于网络因素被完全隐藏起来;确保你可以独立地升级服务端的接口而不用强迫客户端升级;在客户端中一定不要隐藏我们是在做网络调用这个事实。
尽量让中间件保持简单,而把业务逻辑放在自己的服务中。
DRY,Don't Repeat Yourself,避免重复代码,更精确的含义是避免系统行为和知识的重复。我们想要避免微服务和消费者之间的过渡耦合,否则对微服务的人和小的改动都会引起消费方的改动。而共享代码就有可能引起这种耦合。在微服务内不要违法 DRY,但在跨服务的情况下可以适当违反 DRY。
减少破坏性修改影响的最好方法就是尽量不要做这样的修改。Postel 法则(鲁棒性法则),系统中每个模块都应该“宽进严出”,即对自己发送的东西要严格,对接受度而东西这要宽容。
扩展/收缩模式,允许我们对破坏性修改进行平滑的过渡,首先,扩展服务的能力,对新老两种模式都进行支持;然后等到老的消费者都采用了新的方式,在通过收缩 API 去掉旧的功能。
BFF(Beckend For Frontends),风险在于包含不该包含的逻辑。业务逻辑应该处在服务中,而不应该泄露在这一层。
在自己可控的平台进行定制化。人和定制化都只能在自己可控的平台上进行,并限制工具的消费者数量。
无论如何,避免数据库集成。
理解 REST 和 RPC 之间的取舍,但总是使用 REST 作为请求/响应模式的起点。相比于编排,优先使用协同。
将用户界面视为一个组合层。

第5章 分解单块系统

关键是接缝:从接缝处可以抽取出相对独立的一部分代码。对这部分代码进行修改不会影响系统的其他部分。识别出接缝不仅仅能够清理代码库,更重要的是,这些被识别出的接缝可以作为服务的边界。
最好考虑一下把哪部分代码抽取出去得到的收益最大,而不是为了抽取而抽取。
相对于使用事务来保证系统处于一致的状态,最终一致性可以接受系统在未来的某个时间达到一致。
做小的增量的修改的一个关键好处是,能够理解做出的哪些改变会造成什么影响。

第 6 章 部署

测试是否真正理解 CI(Continuous Intergration)的三个问题:
你是否每天都签入代码到主线?
你是否有一组测试来验证修改?
当构建失败后,团队是否把修复CI当做第一优先级的事情来做?
CD,continuous Delivery,持续交付,能够检查每次提交是否达到了部署到生产环境的要求,并持续把这些信息反馈给我恩,它会把每次提交当成候选发布版本来对待。
专注保持服务能够独立于其他服务进行部署的能力,无论采用什么技术,请确保它能够提供这个能力。我倾向于一个服务一个代码库,对于每个微服务一个 CIA 的事情,因为只有这样才能实现独立部署。
如果可能的话,将每个服务放到当度的主机/容器中。
自动化的文化对一切管理来说都非常重要。自动化一切,如果你采用的技术不支持的话,就选用一个新的技术吧。

第7章 测试

测试金字塔的关键是,为不同目的选择不同的测试来覆盖不同的范围。
测试时间/反馈周期/覆盖范围 的权衡。 平均修复时间(MTTR,Mean Time To Repair)胜过平均故障间隔时间(MTBF,Mean Time Between Failures)。

第8章 监控

将系统拆成更小的、细粒度的微服务会带来很多好处。然而,它也增加了生产系统的监控复杂度。
关键是让做正确的事情边容易。
对单个服务而言:
最低限度要跟踪请求响应时间。做好之后,可以开始跟踪错误率及应用程序级的指标。
最低限度要跟踪所有下游服务的健康状态,包括下游调用的响应时间,最好能跟踪错误率。
标准化如何收集指标以及存储状态。
如果可能的话,以标准的格式将日志记录到一个标准的位置。如果每个服务各自使用不同的方式,聚合会非常痛苦。
监控底层操作系统,这样你就可以耿总流氓进程和进行容量规划。
对系统而言:
聚合 CPU 之类的主机层面的指标及应用程序级监控。
确保你选用的指标存储工具可以在系统和服务级别做聚合,同时也允许你查看单台主机的情况。
确保指标存储工具允许你维护数据足够长时间,以了解你的系统的趋势。
使用单个可查询工具来对日志进行聚合和存储。
强烈考虑标准化关联标识的使用。
了解什么情况下需要行动,并根据这些信息构造响应的报警和仪表盘。

第9章 安全

不要实现自己的加密算法。不要发明自己的安全协议。除非你有一个有多年经验的密码专家,如果你尝试发明自己的编码或精密的加密算法,你会出错。即使你是一个密码庄家,仍然可能会出错。
团队并不总能看到自己所犯的错误,因为他们太接近于问题本身了。如果是一个足够大的公司,可能有一个专门的信息安全团队帮助你。如果不是,找一个外部方也可以。早点接触他们,了解他们是如何工作的,并向其学习做一个安全测试需要关注哪些内容。

第10章 康威定律和系统设计

康威定律:任何组织在设计一套系统(广义概念上的系统)时,所交付的设计方案在结构上都与该组织的沟通结构保持一致。
如果构建系统的组织更加松耦合,其所构建的系统则倾向于更加模块化,因此耦合度也越低。一个拥有许多服务的单个团队对其管理的服务会倾向于更紧密的集成,而这种方式在分布式组织中是很难维护的。
微服务:服务会根据业务领域,而不是技术进行建模。如果负责某个微服务的团队与业务领域相匹配,则它更容易保持对客户的关注,也更容易进行以特性为导向的开发,因为它对服务相关的所有技术有一个全面的了解并且拥有所有权。
当考虑允许不受信赖的提交者提交更改到你的代码库时,你必须做出决定,专门专门设置一个守护者的开销是否值得:核心团队是否可以把花费在审批更改上的时间,用在更有意义的事情上。
每个组织都有自己的节奏,了解 你的员工能够承受的变化,不要逼他们改变太快。
请记住,如果没有把人们拉到一条船上,你想要的人和变化从一开始就注定会失败。
第11章 规模化微服务
假设一切都会失败,会让你从不同的角度去思考如何解决问题。
规模化后,即使你买最好的服务,最昂贵的硬件,也无法边它们会发生故障的事实。
处理系统缓慢要比处理系统快速失败困难的多。在分布式系统,延迟是致命的。
应对故障需要做的事情:
超时。给所有的跨进程调用设置超时,并选择一个默认的超时时间,当超时发生后,记录到日志里看看发生了什么,并相应的调整它们。
断路器。
舱壁,把自己从故障中隔离开的一种方式。我们应该为每个下游使用不同的连接池;关注点分离,通过把功能分解成独立的微服务,减少因为一个功能的宕机而影响另一个的可能性。
隔离。
幂等。多次执行所产生的影响们,均与一次执行的响应相同。
扩展
更强大的主机
拆分负载。
分散风险。
负载均衡。
基于 worker 的系统。
重新设计。考虑 10 倍的容量的增长,但超过 100 被容量时就要重写了。
缓存:那种缓存最合理取决于你正在试图优化什么。
客户端、代理和服务器端缓存
HTTP 缓存
为写使用缓存
为弹性使用缓存
隐藏服务资源
保持简单。如果你认为缓存是一个好主意,请保持简单,先在一处使用缓存,在添加更多的缓存前慎重考虑。
CAP 定律:一致性(consisitency)、可用性(availability)和分区容忍性(partition tolerance)。最多职能保持三个中的两个。

第12章 总结

微服务的原则:
围绕业务建模。使用界限上下文来定义可能的领域边界。
接受自动化文化。
隐藏内部实现细节。
让一切都去中性化。确保团队对服务的所有权是最重要的一步,理想情况下,甚至可以让团队自己决定什么时候让那些更改上线。
可独立部署。你的消费者应该自己决定何时更新,你需要适用他们。
隔离失败。如果我们部考虑调用下游可能会失败的事实,系统会遭受灾难性的级联故障,系统也会比以前更加脆弱。如果我们心中持有反脆弱的信条,预期在人和地方都会发生故障,这说明我们走在正确的路上。
高度可观察。聚合你的日志和数据,关联标识可以帮助你跟踪系统间的调用。
什么时候你不应该使用微服务
你越是不了解一个领域,为服务找到界限上下文就越难。如果你不了解一个单块系统领域的话,在划分服务之前,第一件事是花一些时间了解系统是做什么的,然后尝试识别出清晰的模块边界。
请再次考虑首先构建单块系统,当稳定以后再进行拆分。
尽量缩小每个决策的影响范围。这样一来,如果做错了,只会影响系统的一小部分。学会拥抱演进式架构的概念,在这个概念下,系统会在你学到一些新东西之后扩展和变化。不要去大爆炸式的重写,取而代之的是随这时间的推移,逐步对系统进行一些列更改,这样做可以保持系统的灵活性。