简体   繁体   English

如何使用Java Spring同步在码头集群中运行的微服务实例

[英]How to synchronize microservices instances running in a jetty cluster using Java Spring

I am developing a Java 8 Spring 5 microservice that runs on a Jetty embedded server. 我正在开发在Jetty嵌入式服务器上运行的Java 8 Spring 5微服务。 I intend to spawn several instances of this microservice, so there will be several Jetty servers running concurrently on different ports, one for each spawned instance. 我打算生成该微服务的多个实例,因此将有多个Jetty服务器在不同端口上同时运行,每个生成的实例一个。

All instances share the same database which is a MongoDB database. 所有实例共享同一个数据库,该数据库是MongoDB数据库。

From within my microservice I invoke a third party REST Web Service. 从我的微服务中,我调用第三方REST Web服务。 I am saving the data returned by this REST WS in my database, so all instances of the cluster can take advantage of the request made by one of the instances. 我将此REST WS返回的数据保存在数据库中,因此群集的所有实例都可以利用其中一个实例的请求。

However, this data expires after some time, so one instance will have to invoke the external Web Service after some time. 但是,此数据会在一段时间后过期,因此一个实例将在一段时间后不得不调用外部Web服务。

I do not want two or more instances of my cluster to invoke this external web service at the same time, if one instance is invoking this web service, and another one requires the data, it should wait for the first instance to retrieve the data and then use it. 我不希望集群的两个或更多实例同时调用此外部Web服务,如果一个实例正在调用此Web服务,而另一个实例需要该数据,则它应等待第一个实例检索数据,并然后使用它。

This is when i find the problem, because i do not know how to lock one instance of the jetty server when another one is invoking the web service. 这是我发现问题的时间,因为当另一个实例调用Web服务时,我不知道如何锁定码头服务器的一个实例。

I have been looking into MongoDBs 4.0 Transaction feature, to try and lock a document while the service is being invoked, but without success (still :) ). 我一直在研究MongoDBs 4.0事务功能,以尝试在服务被调用时锁定文档,但是没有成功(still :))。

You need a way to serialize access to this external service, that is, to ensure a single request is performed at any particular moment in time. 您需要一种序列化对该外部服务的访问的方法,即,确保在任何特定时间执行单个请求。

This is that thing the databases are really good at. 这就是数据库真正擅长的事情。 With a specially crafted unique index you get exactly that. 通过特制的唯一索引,您可以准确地做到这一点。 You don't even need transactions for this, because you will have only one collection (table). 您甚至不需要为此进行事务处理,因为您只有一个集合(表)。

The solution is to use optimistic locking. 解决方案是使用乐观锁定。 I haven't used myself in Java (only in PHP) but I found this question that could help you. 我没有在Java中使用过自己(仅在PHP中),但是发现了这个可以帮助您的问题。 Long story short, you use @org.springframework.data.annotation.Version on a property. 长话短说,您可以在属性上使用@org.springframework.data.annotation.Version

You should define a new Entity that represents the remote piece of data, having a state property with the following possible values: old (the default), fetching and fetched . 您应该定义一个新的Entity,它代表远程数据,并具有一个state属性,该属性具有以下可能的值: old (默认值), fetchingfetched When a local service needs the data, it loads the Entity and check the status: 当本地服务需要数据时,它将加载实体并检查状态:

  • if the status is fetched then it uses it; 如果fetched了状态,则使用该状态;
  • if the status is old , then it tries to change it to fetching ; 如果状态是old ,它将尝试将其更改为正在fetching ; if the database rejects it because of concurrent modification then it should wait until the status becomes fetched ; 如果数据库由于并发修改而拒绝了它,那么它应该等待直到状态被fetched ; if the saving succeeds then it calls the remote service and persist the result in the Entity as a property; 如果保存成功,则调用远程服务并将结果作为属性保留在Entity中;
  • if the status is fetching it should wait until it becomes fetched . 如果状态为fetching ,则应等待直到fetched

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM