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

在介入正题前,想谈一下如何阅读,因为技术类的文章虽好,但需要一定的门槛,而且会比较枯燥,读后可能很快就会忘记读了什么,只记得读过。

导读

带着兴趣

带着兴趣也可以带着疑惑去阅读是最好的起点,先不急于阅读,看到标题后,可以先假设一下想了解什么信息,想解决什么问题。千万不要用速度、字数、页数、本数去衡量阅读的成果,而是阅读之后能收获到的东西----知识点。

在知识管理领域有DIKW模型,也是前几年大数据经常会用到的,即数据DATA(文字、符号等)会告诉你大致的概念,信息Information会告诉你它是什么,知识Knowledge会告诉你他前因后果,而智慧Wisdom则是告诉你如何抽象出本质模型后,用之前和当下的DIK来理解、解释这些现象,即应用活用,能领会贯通到这一点时,你就把它变成了你的Wisdom,这就是知识增进和内化的过程。否则,只会停留在D或DI的层面,只是知道而已,被动单向的不断地被灌输和转述作者的观点和逻辑。

顺便提一下现在公司各部门间及领导间的PK往往是DIKW各层次的PK,有时甚至屏蔽了D层,而越基层则越是DI层次或D层的PK,这或许是因为D层和I层的屏蔽。

主题阅读

阅读不用去死记硬背作者讲了什么,怎么讲,而是找到对自己有价值的,能提升自己,解答心中疑惑的东西,主题阅读,顺着知识点阅读相关的内容、书籍,不懂的可以跳过,不求甚解,不感兴趣的无关的也可以跳过,提炼知识点,这样它在脑海中和其他节点的关联就越多越密切,从一个点,引出一条线,一张网,最终构建一个完整的知识体系。

以我为主,为我所用,这就是阅读最本质的地方。唯有这样,读到的东西才能真正成为你的养分,不断充实你的认知和精神世界。而非只是映射了作者的影子。

正文章节

目录简介

Part1:微服务

Part2:演化式架构师

Part3:如何建模服务

Part4:集成

章节内容

Part1:微服务

微服务的特点

分布式解决方案、面向纵向的细微架构领域

微服务并不是被发明的,是以往IT建设架构演进的必然趋势,是分布式解决方案,分布式的核心是拆分,按需创建资源(这里已经不再强调具体的物理机器,而是其能提供的计算、存储的资源)并且借助基础设施的自动化、虚拟化、容器化的能力调整资源的大小来支撑提供服务,再由这些服务的组合完成业务层面的支撑,不同于原先的分层架构,而是面向纵向的细微架构领域,围绕业务特质建模,更好地体现了业务逻辑。

以往分层架构中,随着新功能的增加,代码库会越来越大,以致要维护修改都很困难。微服务是把因相同原因变化的东西聚合在一起,而把因不同原因变化的东西分离出来。其法则是能否修改一个服务并对其部署而不影响其他任何服务。服务应彼此独立进行修改,一个服务部署不应该引起该服务消费方的变动。消费方于该服务的耦合会产生额外的协同工作,从而降低服务的自治性。

微服务的好处

1

解决方法多样:微服务帮你轻松采用不同的技术解决不同的应用需求,因为是较小的颗粒,在解决方法上有更多选择。当然服务越小,其独立性带来的好处越多,但管理大量服务也会越复杂。

2

降低服务不可用的风险:以往的单体结构一个不关键的服务往往导致整个系统的崩溃,现在服务边界是很显然的隔水舱,除非是核心服务。

3

能力扩展:可以针对那些需要扩展的微服务进行扩展。

4

降低发布风险:微服务简化发布,降低发布风险,以往单体的整体发布的版本差异越大,出错的可能性越大。

5

可组合性:在微服务架构中,系统会开放很多接口供外部使用(API),而以往的整体化应用程序只能提供一个非常粗粒度的接口供外部使用。

6

易被替换:当一个代码库只有几百行时,人们不会对它有太多的感情依赖,技术债务也较少,所以很容易替换。

那天,有领导问微服务和接口有什么区别,虽然都是接口,但本质上是略有区别的,微服务是以提供功能为主,而接口是为了共享数据,因此在提供的效能和复用性上存在一定的差异,原来的接口是大而全的犹如一辆卡车,即便只要刷新一两个参数也是整个接口调用,而且针对特定的上下游系统,耦合性很高;而微服务架构下的接口相对会高内聚松耦合些,好比只要一辆小货车即可完成小数据量的服务调用,而且这辆小车可以到处被订阅调用,也不关心上下游是什么。

我们过去的经验更多是关于单体系统的,在急切投入微服务之前必须说明的是:微服务不是万能钥匙,微服务也不可能来解决所有问题,我们需要面对分布式系统的复杂性,需要在部署、测试、监控、网络等方面做很多工作,还需要考虑如何扩展系统,并保持他们的弹性(隔离度)以及CAP问题。

每个公司、组织及系统都不一样,微服务是否合适,取决于很多因素。

Part2:演化式架构师

架构师职责

1

在IT建设中我们会面临大量的需求变更,工具和技术也具有多样性。对于大多数我们创造的IT产品并不是在某一时刻后就不变了,软件本身会继续演化,IT产品交付后还是要响应客户(业务部门)的变更需求,所以架构师必须改变一开始就要那种大而全的完美产品的想法,相反我们需要预期可能发生的变化设计一个允许业务变化的合理的框架,在这个框架下逐步演化出正确的系统。

2

架构师应该考虑不同服务之间的交互,保证能对整个系统的健康状态监控。

3

技术债务的层次及其对系统的影响。

Part3:如何建模服务

好服务

高内聚+松耦合

高内聚:把相关的行为聚集在一起,把不相关的行为放在别处(和第一章呼应),在修改某个行为最好能够在一个地方修改,这样才能尽快的发布和应用,如果这个功能需要很多不同的地方做修改,那就需要修改发布多个微服务才能交付这个功能,多个不同地方修改则会很慢,同时发布多个服务也容易出现风险。所以需要找到问题域的边界,并界定行为的相关性。即限界上下文(bounded context),任何个领域都包含多个可限界上下文的内容,每个限界上文的内容中包含了不需要与外部交互的部分和需要交互的部分,用个比喻“细胞之所以会存在,是因为细胞膜定义了什么在细胞内,什么在细胞外,并且确定了什么物质可以通过细胞膜。”在逐步限界上下文时,不应该从共享数据的角度来考虑,而应该从这些上下文能够提供的功能来考虑。作者批评贫血型的仅基于CRUD的服务,更倾向于做什么提供什么功能,然后再是考虑需要什么数据。

松耦合:简单说就是修改一个服务不需要修改另外一个与之相关的其他服务。一个松耦合的服务应该尽可能地少知道与之协作的其他服务,频繁的服务间通讯可能导致紧耦合。微信通讯联系相比较电话通讯就是个松耦合的案例,打电话通常都是要求对方能及时的高耦合的响应和回复。

Part4:集成

微服务之间的通信方式有很多,SOAP、RPC、REST、Protocol Buffer。

完美集成技术

1

避免破坏性修改,如果一个微服务在一个响应中增加一个字段,则已有的消费方不应该受到影响。

2

保证API的技术无关性:不应该选择那种对微服务具体实现技术有限制的集成方式。

3

使服务易于消费。

4

隐藏内部实现细节:我们不希望消费方与服务的内部细节绑定在一起,这样只会增加耦合。

共享数据库

共享数据库不是好选择,这是数据库是个很大的共享API,外部系统能够查看内部实现细节,我方的维护性修改都必须非常小心避免影响消费方。这时只能做大量的回归测试来保证功能的正确性。其次,消费方与特定的技术选择绑定在一起了,假如有一天发现使用mysql是更好的选择,原先oracle的数据库替换,耦合性?最后,我们考虑一下维护,肯定会有一部分逻辑对订单进行修改,这时消费方也会直接操作数据库,工单拆分后、派工单、施工单完成时,多个地方来修改订单状态,而且这些修改是分别做的部署,当然也会有人提出数据副本,此时的内聚性?共享数据库很容易共享数据,但无法共享行为。

同步通信

发起一个远程服务调用后,调用方会阻塞自己等待整个操作完成;如果异步通信,调用方不需要等待操作完成就可以返回,甚至不需要关心操作是否完成。

跨服务业务流程

跨服务业务流程问题,编排与协同。编排会使某中心承担太多的职责,成为网状结构的中心及很多逻辑的起点,而重量级的编排通常是修改代价较大且不稳定;协同方式降低了耦合度,需要额外的工作来监控上下游之间的工作流程,以确保其正确。

针对请求/响应方式的两种技术RPC(Remote Procedure Call)和REST( Representational state transfer)(RPC略过):

REST技术

REST是受WEB启发而产生的一种架构风格,其重要的一点是资源的概念,即一个资源的对外显示方式和内部存储方式之间无耦合。REST常用的底层协议是HTTP,HTTP的一些特性使之实现REST简单得很多。HTTP生态系统提供了缓存代理、负载均衡、监控和安全控制机制等好处,可以帮助我们更好地处理流量、路由,而且这些操作对终端用户基本上是透明的。为了避免客户端和服务端之间的耦合,REST引入“HATEOAS”约束----超媒体作为程序状态的引擎,客户端可以通过服务端提供的资源的表达来智能地自行地发现相关API及可以执行的操作。当服务端发生了变化时,客户端并不需要做出修改,因为资源的 URI 和其他信息都是动态发现的。 Richardson 的 REST 成熟度模型把 REST 服务按照成熟度划分成 4 个层次,HATEOAS 的 REST 服务是成熟度最高的,但这需要一定的投入。

基于HTTP的REST的缺点

1

HTTP不适用重要的低延迟场景。

2

从易用性角度,基于HTTP的REST无法帮你生成客户端的桩代码(用来代替某些代码的代码)。

3

有些web框架无法很好支持所有的HTTP动词,这意味着很容易处理GET和POST请求,但PUT和DELETE就有问题了。

4

性能上也有问题。

5

不能支持高级的序列化和反序列化机制。

尽管如此,基于HTTP的REST仍然是较合理的选择。

功能

【异步协作方式】

A:实现基于事件的异步协作方式,主要考虑微服务发布事件机制和消费者接收事件机制。

B: 推荐方式是消息代理,它具有较好的伸缩性和弹性,但增加了开发流程的复杂度,需要尽量让中间件保持简单,把业务逻辑做到自己的服务中去。

C:另外一种方式是使用HTTP传播事件,ATOM发布协议,可以通过它提供资源聚合的发布服务。

事件驱动架构和异步编程会带来一定的复杂性,我们需确保各个流程有很好的监控,并考虑使用关联ID,以便跨进程的请求进行追踪。

【响应式扩展】

响应式扩展,就是通常所说的 Rx,是一组定义良好的API,大规模扩展了观察者模式。

【微服务中的DRY和代码重用】

微服务中的DRY和代码重用的风险:避免系统行为和知识的重复。如果相同的代码做同样的事情,代码规模就会变大,从而降低可维护性,要修改时容易遗漏某些部分,从而导致BUG;但如果抽取重复代码做共享代码,可能会导致服务和消费者的过度耦合。在微服务内部不要违反DRY,但跨服务的情况下可以适当违反DRY。服务之间引入大量耦合会比重复代码带来更糟糕的问题,平衡取舍。

【按引用访问】

按引用访问:相比较获取查询,通过引用查询来传递领域实体的相关信息更可靠。微服务应该包含核心领域实体(比如客户)全生命周期的相关操作,客户引擎应该是关于客户信息的唯一可靠来源。

【版本管理】

版本管理:Postel法则(伯斯塔尔法则),系统每个模块应“宽进严出”,即对自己发送的东西要严格,对接收的东西要宽容,客户端尽可能灵活消费服务响应;尽可能推迟发布;及早发现破坏性修改;使用语义化的版本管理;支持不同接口共存,允许消费者进行逐步迁移;运行多个版本的统一服务来支持老的接口。

【用户界面】

用户界面,使用多个API来组合界面;服务直接提供UI组件供业务组装;BFF为前端服务的后端。

【工具定制化】

与第三方集成,工具定制化;意大利面式的集成;在可控平台定制化;绞杀者模式。

第四章覆盖了很多内容,虽然每个话题都未太深入,但指引了方向,这对后面的学习有进一步的帮助。(待续)

柳林志

文:陈孚

编辑:徐梦;赵晓燕

图片:来源于网络

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

扫码关注云+社区