如果我没有获得保持活动信号,如何设置一个自动超时的锁?

时间:2022-11-07 06:48:17

I have a certain resouce I want to limit access to. Basically, I am using a session level lock. However, it is getting to be a pain writing JavaScript that covers every possible way a window can close.

我有一定的资源我想限制访问权限。基本上,我正在使用会话级锁。然而,编写JavaScript的痛苦已经成为一种痛苦,它涵盖了窗口可以关闭的所有可能方式。

Once the user leaves that page I would like to unlock the resouce.

一旦用户离开该页面,我想解锁资源。

My basic idea is to use some sort of server side timeout, to unlock the resouce. Basically, if I fail to unlock the resource, I want a timer to kick in and unlock the resouce.

我的基本想法是使用某种服务器端超时来解锁资源。基本上,如果我无法解锁资源,我想要一个计时器启动并解锁资源。

For example, after 30 seconds with now update from the clientside, unlock the resouce.

例如,现在从客户端更新30秒后,解锁资源。

My basic question, is what sort of side trick can I use to do this? It is my understanding, that I can't just create a thread in JSF, because it would be unmanaged.

我的基本问题是,我可以用什么方法来做这件事?我的理解是,我不能只在JSF中创建一个线程,因为它不受管理。

I am sure other people do this kind of thing, what is the correct thing to use?

我相信其他人会做这种事情,使用什么是正确的?

Thanks, Grae

谢谢,格雷

1 个解决方案

#1


1  

As BalusC right fully asked, the big question is at what level of granularity would you like to do this locking? Per logged-in user, for all users, or perhaps you could get away with locking per request?

正如BalusC完全问到的那样,最大的问题是你希望锁定的粒度级别是多少?每个登录用户,对于所有用户,或者您可能会因为每个请求而锁定?

Or, and this will be a tougher one, is the idea that a single page request grabs the lock and then that specific page is intended to keep the lock between requests? E.g. as a kind of reservation. I'm browsing a hotel page, and when I merely look at a room I have made an implicit reservation in the system for that room so it can't happen that somebody else reserves the room for real while I'm looking at it?

或者,这将是一个更难的,是单个页面请求抓住锁定,然后该特定页面旨在保持请求之间的锁定的想法?例如。作为一种保留。我正在浏览一个酒店页面,当我只看一个房间时,我已经在该系统中为该房间进行了隐含的预订,所以当我正在查看它时,其他人不能保留真实的空间吗?

In the latter case, maybe the following scheme would work:

在后一种情况下,可能以下方案可行:

  1. In application scope, define a global concurrent map.
  2. 在应用程序范围中,定义全局并发映射。
  3. Keys of the map represent the resources you want to protect.
  4. 地图的键代表您要保护的资源。
  5. Values of the map are a custom structure which hold a read write lock (e.g. ReentrantReadWriteLock), a token and a timestamp.
  6. 映射的值是一个自定义结构,它包含一个读写锁(例如ReentrantReadWriteLock),一个标记和一个时间戳。
  7. In application scope, there also is a single global lock (e.g. ReentrantLock)
  8. 在应用程序范围内,还有一个全局锁(例如ReentrantLock)
  9. Code in a request first grabs the global lock, and quickly checks if the entry in the map is there.
  10. 请求中的代码首先获取全局锁定,并快速检查映射中的条目是否存在。
  11. If the entry is there it is taken, otherwise it's created. Creation time should be very short. The global lock is quickly released.
  12. 如果该条目在那里被采用,否则它被创建。创作时间应该很短。全局锁定很快就会发布。
  13. If the entry was new, it's locked via its write lock and a new token and timestamp are created.
  14. 如果条目是新的,则通过其写锁定锁定,并创建新的令牌和时间戳。
  15. If the entry was not new, it's locked via its read lock
  16. 如果条目不是新条目,则通过其读锁定锁定
  17. if the code has the same token, it can go ahead and access the protected resource, otherwise it checks the timestamp.
  18. 如果代码具有相同的令牌,它可以继续访问受保护的资源,否则它会检查时间戳。
  19. If the timestamp has expired, it tries to grab the write lock.
  20. 如果时间戳已过期,它会尝试获取写锁定。
  21. The write lock has a time-out. When the time-out occurs give up and communicate something to the client. Otherwise a new token and timestamp are created.
  22. 写锁定具有超时。当超时发生时,放弃并向客户传达某些信息。否则,将创建新的令牌和时间戳。

This just the general idea. In a Java EE application that I have build I have used something similar (though not exactly the same) and it worked quite well.

这只是一般的想法。在我构建的Java EE应用程序中,我使用了类似的东西(尽管不完全相同)并且它运行得很好。

Alternatively you could use a quartz job anyway that periodically removed the stale entries. Yet another alternative for that is replacing the global concurrent map with e.g. a JBoss Cache or Infinispan instance. These allow you to define an eviction policy for their entries, which saves you from having to code this yourself. If you have never used those caches though, learning how to set them up and configuring them correctly can be more trouble than just building a simple quartz job yourself.

或者,您可以使用石英作业,定期删除过时的条目。另一种替代方案是用例如替换全局并发映射。 JBoss Cache或Infinispan实例。这些允许您为其条目定义逐出策略,这使您无需自己编写代码。如果您从未使用过这些缓存,那么学习如何设置它们并正确配置它们可能比仅仅自己构建一个简单的石英工作更麻烦。

#1


1  

As BalusC right fully asked, the big question is at what level of granularity would you like to do this locking? Per logged-in user, for all users, or perhaps you could get away with locking per request?

正如BalusC完全问到的那样,最大的问题是你希望锁定的粒度级别是多少?每个登录用户,对于所有用户,或者您可能会因为每个请求而锁定?

Or, and this will be a tougher one, is the idea that a single page request grabs the lock and then that specific page is intended to keep the lock between requests? E.g. as a kind of reservation. I'm browsing a hotel page, and when I merely look at a room I have made an implicit reservation in the system for that room so it can't happen that somebody else reserves the room for real while I'm looking at it?

或者,这将是一个更难的,是单个页面请求抓住锁定,然后该特定页面旨在保持请求之间的锁定的想法?例如。作为一种保留。我正在浏览一个酒店页面,当我只看一个房间时,我已经在该系统中为该房间进行了隐含的预订,所以当我正在查看它时,其他人不能保留真实的空间吗?

In the latter case, maybe the following scheme would work:

在后一种情况下,可能以下方案可行:

  1. In application scope, define a global concurrent map.
  2. 在应用程序范围中,定义全局并发映射。
  3. Keys of the map represent the resources you want to protect.
  4. 地图的键代表您要保护的资源。
  5. Values of the map are a custom structure which hold a read write lock (e.g. ReentrantReadWriteLock), a token and a timestamp.
  6. 映射的值是一个自定义结构,它包含一个读写锁(例如ReentrantReadWriteLock),一个标记和一个时间戳。
  7. In application scope, there also is a single global lock (e.g. ReentrantLock)
  8. 在应用程序范围内,还有一个全局锁(例如ReentrantLock)
  9. Code in a request first grabs the global lock, and quickly checks if the entry in the map is there.
  10. 请求中的代码首先获取全局锁定,并快速检查映射中的条目是否存在。
  11. If the entry is there it is taken, otherwise it's created. Creation time should be very short. The global lock is quickly released.
  12. 如果该条目在那里被采用,否则它被创建。创作时间应该很短。全局锁定很快就会发布。
  13. If the entry was new, it's locked via its write lock and a new token and timestamp are created.
  14. 如果条目是新的,则通过其写锁定锁定,并创建新的令牌和时间戳。
  15. If the entry was not new, it's locked via its read lock
  16. 如果条目不是新条目,则通过其读锁定锁定
  17. if the code has the same token, it can go ahead and access the protected resource, otherwise it checks the timestamp.
  18. 如果代码具有相同的令牌,它可以继续访问受保护的资源,否则它会检查时间戳。
  19. If the timestamp has expired, it tries to grab the write lock.
  20. 如果时间戳已过期,它会尝试获取写锁定。
  21. The write lock has a time-out. When the time-out occurs give up and communicate something to the client. Otherwise a new token and timestamp are created.
  22. 写锁定具有超时。当超时发生时,放弃并向客户传达某些信息。否则,将创建新的令牌和时间戳。

This just the general idea. In a Java EE application that I have build I have used something similar (though not exactly the same) and it worked quite well.

这只是一般的想法。在我构建的Java EE应用程序中,我使用了类似的东西(尽管不完全相同)并且它运行得很好。

Alternatively you could use a quartz job anyway that periodically removed the stale entries. Yet another alternative for that is replacing the global concurrent map with e.g. a JBoss Cache or Infinispan instance. These allow you to define an eviction policy for their entries, which saves you from having to code this yourself. If you have never used those caches though, learning how to set them up and configuring them correctly can be more trouble than just building a simple quartz job yourself.

或者,您可以使用石英作业,定期删除过时的条目。另一种替代方案是用例如替换全局并发映射。 JBoss Cache或Infinispan实例。这些允许您为其条目定义逐出策略,这使您无需自己编写代码。如果您从未使用过这些缓存,那么学习如何设置它们并正确配置它们可能比仅仅自己构建一个简单的石英工作更麻烦。