微服务之间的数据共享
Data Sharing between micro services
当前架构:
问题:
我们在前端和后端层之间有一个两步流程。
- 第一步:
前端在微服务 1 (MS1)
上验证来自用户的输入 I1
- 第二步:
前端向微服务2
提交I1等更多信息
微服务 2 (MS2) 需要验证来自前端的 I1 的完整性。如何避免对 MS1 的新查询?什么是最好的方法?
我尝试优化的流程删除了步骤 1.3 和 2.3
流程 1:
- 1.1 用户X向MS2
请求数据(MS2_Data)
- 1.2 用户 X 在 MS1
上持久化数据 (MS2_Data + MS1_Data)
- 1.3 MS1 使用 B2B HTTP 请求
检查 MS2_Data 的完整性
- 1.4 MS1 使用 MS2_Data 和 MS1_Data 持久化数据库 1 并构建 HTTP 响应。
流程 2:
- 2.1 用户 X 已经将数据 (MS2_Data) 存储在 local/session 存储
- 2.2 用户 X 在 MS1
上持久化数据 (MS2_Data + MS1_Data)
- 2.3 MS1 使用 B2B HTTP 请求
检查 MS2_Data 的完整性
- 2.4 MS1 使用 MS2_Data 和 MS1_Data 持久化数据库 1 并构建 HTTP 响应。
接近
一种可能的方法是在 MS2 和 MS1 之间使用 B2B HTTP 请求,但我们会在第一步中重复验证。
另一种方法是将数据从 MS1 复制到 MS2。然而,由于数据量及其波动性,这是令人望而却步的。复制似乎不是一个可行的选择。
我认为更合适的解决方案是前端负责在微服务2上获取微服务1所需的所有信息并将其传递给微服务2。这将避免所有这种B2B HTTP 请求。
问题是微服务1如何信任前端发送的信息。也许使用 JWT 以某种方式对来自微服务 1 的数据进行签名,微服务 2 将能够验证消息。
备注
每次微服务 2 需要来自微服务 1 的信息时,都会执行 B2B http 请求。 (HTTP 请求使用 ETAG and Cache Control: max-age)。如何避免这种情况?
架构目标
微服务 1 需要微服务 2 的数据按需持久化 MS1_Data 和 MS2_Data 在 MS1 数据库上,所以 ASYNC 方法使用经纪人不适用于此处。
我的问题是是否存在一种设计模式、最佳实践或框架来实现这种推力交流。
当前架构的缺点是每个微服务之间执行的 B2B HTTP 请求的数量。即使我使用缓存控制机制,每个微服务的响应时间也会受到影响。每个微服务的响应时间都很关键。这里的目标是获得更好的性能,以及如何使用前端作为网关在多个微服务之间分发数据,但使用 推力通信 。
MS2_Data 只是一个实体 SID,例如 MS1 必须用来维护数据完整性的产品 SID 或供应商 SID。
可能的解决方案
想法是将网关用作 api 网关请求处理,它将缓存来自 MS1 和 MS2 的一些 HTTP 响应,并将它们用作对 MS2 SDK 和 MS1 SDK 的响应。这样就不会在 MS1 和 MS2 之间直接进行通信(SYNC 或 ASYNC),也避免了数据重复。
当然上面的方案只是针对跨微服务共享的UUID/GUID。对于完整数据,事件总线用于以异步方式(事件溯源模式)跨微服务分发事件和数据。
灵感:https://aws.amazon.com/api-gateway/ and https://getkong.org/
相关问题及文档:
- https://auth0.com/blog/introduction-to-microservices-part-4-dependencies/
- Transactions across REST microservices?
- https://en.wikipedia.org/wiki/Two-phase_commit_protocol
- http://ws-rest.org/2014/sites/default/files/wsrest2014_submission_7.pdf
- https://www.tigerteam.dk/2014/micro-services-its-not-only-the-size-that-matters-its-also-how-you-use-them-part-1/
不看 "inside" 方框就很难判断任何解决方案的可行性,但是:
如果您在这里唯一关心的是阻止前端可能篡改数据,您可以创建一种 "signature" 的数据包,由 MS2 发送到前端并将签名与数据包一起传播到 MS1。签名可以是数据包的哈希值,该哈希值与以确定方式从微服务共享的种子生成的伪随机数相结合(因此 MS1 可以重新创建与 MS2 相同的伪随机数,而无需额外的 B2B HTTP 请求,然后验证数据包的完整性)。
我想到的第一个想法是验证数据的所有权是否可以修改。如果 MS1 必须频繁访问 MS2 的数据子集,则可以将该子集的所有权从 MS2 转移到 MS1。
在理想的世界中,微服务应该是完全独立的,每个微服务都有自己的持久层和适当的复制系统。你说代理不是一个可行的解决方案,那么共享数据层呢?
希望对您有所帮助!
从问题和评论中我了解到您正在尝试重新排列块以提高系统性能。如图表所述,您建议网关查询微服务 2 而不是微服务 1 查询微服务 2,然后查询微服务 1,向其提供来自微服务 2 的信息。
因此,我看不出这将如何显着提高系统性能,而是这种变化似乎只是改变了逻辑。
要补救这种情况,应增强关键微服务 2 的性能。可以通过分析和优化 microservice2 软件(垂直扩展)and/or 来完成,您可以引入负载平衡(水平扩展)并在多个服务器上执行 microservice2。本例中使用的设计模式是Service Load Balancing pattern.
您可以考虑将 b2b 通信的同步方式更改为使用 publish-subscribe 模式的异步方式。在那种情况下,服务操作将更加独立,您可能不需要一直执行 b2b 请求。
在分布式系统中加快速度的方法是通过非规范化。如果 ms2data 很少更改,例如您阅读它的次数多于重写它,您必须跨服务复制它。通过这样做,您将减少延迟和时间耦合。在许多情况下,耦合方面可能比速度更重要。
如果 ms2data 是关于产品的信息,则 ms2 应该将包含 ms2data 的 ProductCreated 事件发布到总线。 ms1 应订阅此事件并将 ms2data 存储在其自己的数据库中。现在,只要 ms1 需要 ms2data,它就会在本地读取它,而不需要向 ms2 执行请求。这就是时间解耦的意思。当您遵循此模式时,您的解决方案将变得更加容错并且关闭 ms2 不会以任何方式影响 ms1。
考虑阅读描述微服务架构中同步通信背后问题的 good series of articles。
相关的 SO 问题 and here 讨论非常相似的问题,考虑看看。
查看关于我的问题的可能的解决方案部分:
想法是将网关用作 api 网关请求处理,缓存来自 MS1 和 MS2 的一些 HTTP 响应,并将它们用作对 MS2 SDK 和 MS1 SDK 的响应。这样就不会在 MS1 和 MS2 之间直接进行通信(SYNC 或 ASYNC),也避免了数据重复。
灵感:https://aws.amazon.com/api-gateway/ and https://getkong.org/
当前架构:
问题:
我们在前端和后端层之间有一个两步流程。
- 第一步: 前端在微服务 1 (MS1) 上验证来自用户的输入 I1
- 第二步: 前端向微服务2 提交I1等更多信息
微服务 2 (MS2) 需要验证来自前端的 I1 的完整性。如何避免对 MS1 的新查询?什么是最好的方法?
我尝试优化的流程删除了步骤 1.3 和 2.3
流程 1:
- 1.1 用户X向MS2 请求数据(MS2_Data)
- 1.2 用户 X 在 MS1 上持久化数据 (MS2_Data + MS1_Data)
- 1.3 MS1 使用 B2B HTTP 请求 检查 MS2_Data 的完整性
- 1.4 MS1 使用 MS2_Data 和 MS1_Data 持久化数据库 1 并构建 HTTP 响应。
流程 2:
- 2.1 用户 X 已经将数据 (MS2_Data) 存储在 local/session 存储
- 2.2 用户 X 在 MS1 上持久化数据 (MS2_Data + MS1_Data)
- 2.3 MS1 使用 B2B HTTP 请求 检查 MS2_Data 的完整性
- 2.4 MS1 使用 MS2_Data 和 MS1_Data 持久化数据库 1 并构建 HTTP 响应。
接近
一种可能的方法是在 MS2 和 MS1 之间使用 B2B HTTP 请求,但我们会在第一步中重复验证。 另一种方法是将数据从 MS1 复制到 MS2。然而,由于数据量及其波动性,这是令人望而却步的。复制似乎不是一个可行的选择。
我认为更合适的解决方案是前端负责在微服务2上获取微服务1所需的所有信息并将其传递给微服务2。这将避免所有这种B2B HTTP 请求。
问题是微服务1如何信任前端发送的信息。也许使用 JWT 以某种方式对来自微服务 1 的数据进行签名,微服务 2 将能够验证消息。
备注 每次微服务 2 需要来自微服务 1 的信息时,都会执行 B2B http 请求。 (HTTP 请求使用 ETAG and Cache Control: max-age)。如何避免这种情况?
架构目标
微服务 1 需要微服务 2 的数据按需持久化 MS1_Data 和 MS2_Data 在 MS1 数据库上,所以 ASYNC 方法使用经纪人不适用于此处。
我的问题是是否存在一种设计模式、最佳实践或框架来实现这种推力交流。
当前架构的缺点是每个微服务之间执行的 B2B HTTP 请求的数量。即使我使用缓存控制机制,每个微服务的响应时间也会受到影响。每个微服务的响应时间都很关键。这里的目标是获得更好的性能,以及如何使用前端作为网关在多个微服务之间分发数据,但使用 推力通信 。
MS2_Data 只是一个实体 SID,例如 MS1 必须用来维护数据完整性的产品 SID 或供应商 SID。
可能的解决方案
想法是将网关用作 api 网关请求处理,它将缓存来自 MS1 和 MS2 的一些 HTTP 响应,并将它们用作对 MS2 SDK 和 MS1 SDK 的响应。这样就不会在 MS1 和 MS2 之间直接进行通信(SYNC 或 ASYNC),也避免了数据重复。
当然上面的方案只是针对跨微服务共享的UUID/GUID。对于完整数据,事件总线用于以异步方式(事件溯源模式)跨微服务分发事件和数据。
灵感:https://aws.amazon.com/api-gateway/ and https://getkong.org/
相关问题及文档:
- https://auth0.com/blog/introduction-to-microservices-part-4-dependencies/
- Transactions across REST microservices?
- https://en.wikipedia.org/wiki/Two-phase_commit_protocol
- http://ws-rest.org/2014/sites/default/files/wsrest2014_submission_7.pdf
- https://www.tigerteam.dk/2014/micro-services-its-not-only-the-size-that-matters-its-also-how-you-use-them-part-1/
不看 "inside" 方框就很难判断任何解决方案的可行性,但是:
如果您在这里唯一关心的是阻止前端可能篡改数据,您可以创建一种 "signature" 的数据包,由 MS2 发送到前端并将签名与数据包一起传播到 MS1。签名可以是数据包的哈希值,该哈希值与以确定方式从微服务共享的种子生成的伪随机数相结合(因此 MS1 可以重新创建与 MS2 相同的伪随机数,而无需额外的 B2B HTTP 请求,然后验证数据包的完整性)。
我想到的第一个想法是验证数据的所有权是否可以修改。如果 MS1 必须频繁访问 MS2 的数据子集,则可以将该子集的所有权从 MS2 转移到 MS1。
在理想的世界中,微服务应该是完全独立的,每个微服务都有自己的持久层和适当的复制系统。你说代理不是一个可行的解决方案,那么共享数据层呢?
希望对您有所帮助!
从问题和评论中我了解到您正在尝试重新排列块以提高系统性能。如图表所述,您建议网关查询微服务 2 而不是微服务 1 查询微服务 2,然后查询微服务 1,向其提供来自微服务 2 的信息。
因此,我看不出这将如何显着提高系统性能,而是这种变化似乎只是改变了逻辑。
要补救这种情况,应增强关键微服务 2 的性能。可以通过分析和优化 microservice2 软件(垂直扩展)and/or 来完成,您可以引入负载平衡(水平扩展)并在多个服务器上执行 microservice2。本例中使用的设计模式是Service Load Balancing pattern.
您可以考虑将 b2b 通信的同步方式更改为使用 publish-subscribe 模式的异步方式。在那种情况下,服务操作将更加独立,您可能不需要一直执行 b2b 请求。
在分布式系统中加快速度的方法是通过非规范化。如果 ms2data 很少更改,例如您阅读它的次数多于重写它,您必须跨服务复制它。通过这样做,您将减少延迟和时间耦合。在许多情况下,耦合方面可能比速度更重要。
如果 ms2data 是关于产品的信息,则 ms2 应该将包含 ms2data 的 ProductCreated 事件发布到总线。 ms1 应订阅此事件并将 ms2data 存储在其自己的数据库中。现在,只要 ms1 需要 ms2data,它就会在本地读取它,而不需要向 ms2 执行请求。这就是时间解耦的意思。当您遵循此模式时,您的解决方案将变得更加容错并且关闭 ms2 不会以任何方式影响 ms1。
考虑阅读描述微服务架构中同步通信背后问题的 good series of articles。
相关的 SO 问题
查看关于我的问题的可能的解决方案部分:
想法是将网关用作 api 网关请求处理,缓存来自 MS1 和 MS2 的一些 HTTP 响应,并将它们用作对 MS2 SDK 和 MS1 SDK 的响应。这样就不会在 MS1 和 MS2 之间直接进行通信(SYNC 或 ASYNC),也避免了数据重复。
灵感:https://aws.amazon.com/api-gateway/ and https://getkong.org/