捍卫巨石的几句话

我们比较了微服务和整体架构的特点,以及它们的优缺点。 本文是根据2019年2月9日在萨马拉举行的meta Hot Backend的材料为Habr准备的。 我们根据具体任务考虑架构选择的因素。

即使在5年前,也没有人听说过微服务。 但是,根据Google趋势的统计 ,它们的受欢迎程度逐年增加。



整体和微服务:示例


如果项目使用整体架构,则开发人员只有一个应用程序,其所有组件和模块都可以在一个基础上使用。



微服务架构涉及分解为模块的模块,这些模块可以作为独立的进程运行,并且可以具有独立的服务器。 每个微服务都使用自己的数据库,并且所有这些服务都可以同步(http)和异步进行通信。 而且,为了优化架构,期望最小化服务之间的关系。

下图是简化的,它首先反映了业务组件。



微服务:好处


微服务架构至少有四个优点:

独立扩展和部署

为每个微服务提供了独立的部署,这在更新单个模块时很方便。 如果模块上的负载增加,则可以扩展相应的微服务而不会影响其他微服务。 这使您可以灵活地分配负载并节省资源。

独立发展

每个微服务(例如,一个内存模块)可以由一个团队开发,以提高创建软件产品的速度。

可持续发展

一种微服务的故障不会影响其他模块的性能。

异质性

每个团队可以自由选择自己的语言和技术来实现微服务,但是,希望它们具有兼容的接口。

在开发人员中,您会听到以下观点:单片架构已经过时,难以维护和扩展,它在“一大堆泥土”中迅速增长,并且实际上是反模式的,也就是说,它在代码中的存在是不可取的。 通常会引用大型公司(例如Netflix)在其项目中转而使用微服务架构作为这种观点的证据。

让我们看看是否每个人都应该按照最大品牌的榜样真正从单一服务转向微服务?

切换到微服务:可能的困难


问题一:分解

理想情况下,应将应用程序划分为微服务,以使它们彼此之间的交互尽可能少,否则应用程序将难以维护。 同时,在开发之初很难分解,而随着新要求的出现,业务问题和主题领域仍然可以改变。 重构很昂贵。

如果有必要将部分功能从服务A转移到服务B,则可能会遇到困难:例如,服务以不同的语言执行,对服务的内部调用成为网络,需要连接其他库。 我们只能借助测试来验证重构的正确性。



问题二:交易

另一个问题是微服务没有分布式事务的概念。 我们只能在一项微服务中保证业务运营的架构完整性。 如果操作涉及多个微服务,则可以在此处使用不同的数据库,并且必须放弃这种交易。 为了解决此问题,当可访问性比完整性更重要时,业务中会使用各种方法。 同时,提供了补偿机制,以防万一出现问题。 例如,如果货物没有库存,则需要退款到买方的帐户。

如果整体式自动为我们提供体系结构完整性,那么使用微服务,您需要提出自己的机制,并使用具有现成解决方案的库。 在服务之间分配操作时,最好同步请求数据,然后异步执行后续操作。 如果无法访问其中一项服务,则团队将在再次可用时排队。

在这方面,有必要修改用户界面的方法。 应该通知用户某些操作不是立即执行,而是在一定时间内执行。 处理完申请后,他会收到邀请以查看结果。



问题三:报告

如果我们使用具有单个数据库的整体架构,则要构建复杂的报表,您可以编写select并提取几个数据标签:迟早会显示它们。 但是,在微服务上,这些数据可能分散在不同的基础上。

例如,我们需要列出具有特定指标的公司。 有了简单的公司列表,一切都可以正常工作。 并且,如果您需要添加位于另一个数据库中的度量标准? 是的,我们可以根据TIN提出其他请求和请求指标。 如果需要对列表进行过滤和排序? 公司列表可能非常庞大,然后我们必须使用自己的数据库-报告来引入其他服务。



问题四:发展高度复杂

分布式服务的工作更为复杂:所有请求都是通过网络发出的,可以关闭,您需要提供一种回调机制(它将再次进行调用吗?多少次?)。 这些是逐渐积累的“砖头”,并有助于增加项目的复杂性。

服务可以由几个不同的团队开发,您需要对其进行记录,保持文档最新,在更改版本时警告其他团队。 这些是额外的人工成本。

如果每个团队都有独立的部署,则您至少需要维护先前的版本并仅在该服务的所有使用方都已切换到新的API之后将其禁用。
当然,我们可以将所有API放入某种可以公开获得的构件中。 但是,首先,可以使用不同的语言编写服务,其次,不建议这样做。 例如,在我们的一个项目中,出于安全考虑,我们应客户要求拒绝了此请求。 每个微服务都有一个单独的存储库,客户不授予对其的访问权限。

在开发过程中,一切都可以正常工作,然后-不。 碰巧在发生异常的情况下,应用程序会无限尝试处理这些异常,这给系统带来了沉重的负担-整个系统“瘫痪”。 为了避免这种情况,您需要配置所有内容,例如,限制尝试次数,而不是在同一秒内将此调用返回到队列中,等等。





第五个问题:测试,跟踪和调试的复杂性

要测试问题,您需要下载所有涉及的微服务。 调试成为一项艰巨的任务,所有日志都需要收集在一个地方的某个地方。 在这种情况下,您需要尽可能多的日志以了解发生了什么。 要跟踪问题,您需要了解消息传播的整个路径。 这里的单元测试还不够,因为在服务的结合处可能会出错。 进行更改时,只有在支架上运行后才能验证可操作性。 我们可以将每个微服务限制为一定的内存量(例如500兆字节),但是有时需要两个峰值才能达到峰值。 有时系统会开始变慢。 结果,可以将资源花费在不属于客户端即时任务的事务上:例如,只有两个业务微服务,而一半的资源花费在支持其他事务的三个附加微服务上。



微服务或整体:选择标准


首先,在单片和微服务架构之间进行选择时,您需要从主题领域的复杂性和扩展需求出发。

如果主题领域很简单,并且不希望在全球范围内增加用户数量,那么毫无疑问可以使用微服务。 在其他情况下,如果不需要扩展,最好在整体上开始开发并节省资源。 如果主题领域很复杂,并且在初始阶段还没有定义最终要求,那么最好还是从整体开始,以免多次重做微服务。 随着项目的进一步发展,有可能在微服务中区分其各个部分。



加号的是项目开始时存在边界,因为这将有助于在开发过程中不破坏边界。 从一个数据库开始,但为每个模块定义一个方案(例如,付款方案)也是有意义的。 随后,这将有助于简化将模块划分为微服务的过程。 在这种情况下,我们观察模块的边界并可以使用微服务。

每个模块必须具有自己的API,以便以后可以分配它并使该模块成为微服务。



确定了模块的边界之后,如有必要,您可以继续分解为微服务。 在大约90%的情况下,可以保留在整体结构上,但如有必要,更改体系结构将更容易且更便宜。

在使用整体和微服务的实践中,我们得出以下结论:
  • 不要仅仅因为微服务被Netflix,Twitter,Facebook使用而切换到微服务
  • 从两个或三个相互交互的微服务开始,详细计算出对它们的所有非功能性需求(安全性,容错性,可伸缩性等),然后再转移到其他服务
  • 自动化一切可能
  • 设置监控
  • 编写自动测试
  • 不要使用分布式事务(但这不是拒绝保证数据完整性的理由)。
  • 如果要使用微服务架构,请做好准备,因为开发成本可能比整体成本高3倍左右。 但是,两种技术都有其自身的劣势和优势;每种技术都有其自身的优势。

Source: https://habr.com/ru/post/zh-CN453932/


All Articles