我正在开发在Jetty嵌入式服务器上运行的Java 8 Spring 5微服务。我打算产生该微服务的多个实例,因此将有多个Jetty服务器在不同端口上同时运行,每个产生的实例一个。
所有实例共享一个与MongoDB数据库相同的数据库。
从我的微服务中,我调用第三方REST Web服务。我将这个REST WS返回的数据保存在数据库中,因此群集的所有实例都可以利用其中一个实例的请求。
但是,此数据会在一段时间后过期,因此一个实例将不得不在一段时间后调用外部Web服务。
我不希望集群的两个或更多实例同时调用此外部Web服务,如果一个实例正在调用此Web服务,而另一个实例需要数据,则它应等待第一个实例检索到数据,然后使用它。
这是我发现问题的时间,因为当另一个实例调用Web服务时,我不知道如何锁定码头服务器的一个实例。
我一直在研究MongoDBs 4.0事务功能,以尝试在服务被调用时锁定文档,但是没有成功(仍然:))。
答案 0 :(得分:0)
您需要一种序列化对该外部服务的访问的方法,即确保在任何特定时间执行单个请求。
这是数据库真正擅长的事情。通过特制的唯一索引,您可以准确地做到这一点。您甚至不需要为此进行事务处理,因为您只有一个集合(表)。
解决方案是使用乐观锁定。我没有在Java中使用过自己(仅在PHP中),但是发现this question可以为您提供帮助。长话短说,您在属性上使用@org.springframework.data.annotation.Version
。
您应该定义一个表示远程数据的新实体,该实体具有state
属性,并具有以下可能的值:old
(默认值),fetching
和{{1 }}。当本地服务需要数据时,它将加载实体并检查状态:
fetched
,则使用它; fetched
,则尝试将其更改为old
;如果数据库由于并发修改而拒绝它,则应等待状态变为fetching
为止;如果保存成功,则调用远程服务并将结果作为属性保留在Entity中; fetched
,则应等待状态变为fetching
。