首页 > 解决方案 > 在分布式环境中调用一堆 REST API

问题描述

我在 python 库中有我的应用程序逻辑。我的库提供的每个操作都涉及调用一些 REST api 一次或多次。所以我有:

def OperationA(resource_id, params):

   Call REST Api /X/resource_id/params
   Call REST Api /Y/resource_id/params
   Call REST Api /Z/resource_id/params

def OperationB(resource_id params):

   Call REST Api /R/resource_id//params
   Call REST Api /S/resource_id//params
   Call REST Api /T/resource_id//params

该库在分布式环境中执行,并调用操作以响应用户操作。因此,例如 OperationA 的两个实例可能同时执行。如果执行影响不同的资源,则同时运行操作是可以接受的。但是,影响相同资源的操作调用应按顺序执行。这是因为交叉调用 REST api 会导致 REST 服务的状态不一致。例如,如果 OperationA 在 id 为 3 的资源上同时执行,就会发生这种情况:

OperationA(3, "foo"): Call REST Api /X/3/foo
OperationA(3, "bla"): Call REST Api /X/3/bla
OperationA(3, "bla"): Call REST Api /Y/3/bla
OperationA(3, "foo"): Call REST Api /Y/3/foo
OperationA(3, "foo"): Call REST Api /Z/3/foo
OperationA(3, "bla"): Call REST Api /Z/3/bla

问题是最终端点 Y 处的资源 3 处于状态 foo 而在所有其他端点处资源处于状态 bla。

我可以在调用 REST api 之前获取分布式锁,但我还需要 REST api 本身的支持,正如Martin Kleppmann 指出的(以围栏令牌的形式),这是不可能的,因为我无法控制 REST api。

是否有一些现有的技术/服务可以用来防止不可接受的并发执行并且仍然能够水平扩展服务?

标签: restarchitecturemicroservicesdistributed-computingdistributed

解决方案


如果您控制所有访问此 API 的客户端,您可以尝试通过一致的哈希来序列化对同一资源的所有访问——给定的资源将始终由同一台机器处理,然后您只需要获取本地锁。

如果有其他客户端同时访问此 API,并且该 API 没有为您的操作提供足够的表达能力(例如,只允许设置A10,而不是允许说增量A1),也没有任何条件/测试和设置更新(例如A10如果其先前的值为 ),则设置为9),也不是多键事务(例如A,递增1和递减B2),也不是锁……您可能不走运,因为无法保证您想要的属性。


推荐阅读