Kubernetes微服务实战
上QQ阅读APP看书,第一时间看更新

2.14.2 运行分布式查询

我们同意每个微服务都应该具有自己的数据存储。这意味着系统的整体状态将分布在多个数据存储中,只允许它们自己的微服务来访问。你最感兴趣的查询通常涉及多个数据存储中的可用数据,每个消费端都可以访问所有这些微服务并聚合所有数据以满足他们的查询。然而,这并不理想,原因如下:

·消费端需要非常了解系统是如何管理数据的。

·消费端需要访问存储与查询有关的数据的每一项服务。

·更改架构可能需要更改许多消费端。

解决这些问题的方法通常有两种:CQRS和API组合。有趣的是,支持这两种解决方案的服务具有相同的API,因此可以从一种解决方案切换到另一种解决方案,甚至可以混合使用而不会有影响。这意味着某些查询将由CQRS提供服务,而另一些查询则由API组合提供服务,所有这些都由相同的服务实现。总的来说,我建议从API组合开始,只有在适当的条件存在并且在好处非常明显的情况下再转换到CQRS,因为它的复杂性要高得多。

1.使用命令查询职责分离

使用命令查询职责分离(Command Query Responsibility Segregation,CQRS),来自各种微服务的数据将被聚集到一个新的只读数据存储中,该存储旨在响应特定的查询。它的含义是将更新数据(命令)的职责与读取数据(查询)的职责分开。这些活动由不同的服务负责。它通常通过监控所有数据存储的更改来实现,并且需要一个合适的变更通知系统。你也可以使用轮询方式,但这通常是不可取的。当存在经常使用的查询时,这个解决方案将会表现得非常出色。

以下是CQRS实际应用的一个例子。CQRS服务(负责查询)从三个微服务(负责更新)接收变更通知,并将它们聚合到自己的数据存储中。

当查询到来时,CQRS服务通过访问自己的聚合视图而不是微服务来做出响应,如图2-4所示。

图2-4 CQRS应用示例

它的优点如下:

·查询不会影响主数据存储的更新。

·聚合器服务公开了针对特定查询定制的API。

·在不影响消费端的情况下,更容易更改后台数据的管理方式。

·快速的响应时间。

它的缺点如下:

·增加了系统的复杂性。

·数据冗余。

·部分视图需要显式处理。

2.使用API组合

API组合方法更加轻巧。从表面上看,它看起来很像CQRS解决方案。它公开了可以在多个微服务之间响应已知查询的API。区别在于它不保留自己的数据存储。每当有请求进入时,它都会访问包含相关数据的单个微服务,组合这些结果,然后返回。当系统不支持针对数据更新的事件通知,并且可以接受对主数据存储查询的负载时,这个解决方案非常友好。

这是一个实际的API组合示例,其中对API组合服务的查询在后端被转换为对三个微服务的查询,如图2-5所示。

图2-5 API组合应用示例

它的优点如下:

·轻量级解决方案。

·聚合服务公开了针对特定查询定制的API。

·结果始终是最新的。

·不会对架构提出新需求,例如不需要增加变更通知系统。

它的缺点如下:

·任何服务的失败都会导致查询失败,这需要围绕重试和超时设计策略。

·大量查询可能会影响主数据存储的性能。