【问题标题】:Limit Access To a Spring MVC Controller -- N sessions at a time限制对 Spring MVC 控制器的访问——一次 N 个会话
【发布时间】:2008-12-21 23:35:20
【问题描述】:
我们已授权商业产品(在此上下文中不重要的产品),该产品受并发用户数量的限制。用户通过 Spring Controller 访问该产品。
我们有该产品的 N 个许可证,如果 N+1 用户访问它,他们会收到一条令人讨厌的错误消息,提示需要购买更多许可证。我想确保用户看不到这条消息,并且希望对产品的请求只是“排队”,而不是让 N+1 用户实际访问它。当然,他们更愿意我购买许可证,所以他们的工具不会让我们在本地这样做。
为了代替能够控制该工具,我想将与控制器的并发会话数限制为永远不会超过 N。其他人可以等待。
我们正在使用 Spring MVC。
有什么想法吗?
【问题讨论】:
标签:
java
multithreading
spring
session
controller
【解决方案1】:
您需要的是一个 ObjectPool。查看 Apache Commons Pool http://commons.apache.org/pool
在应用程序启动时,您应该创建一个带有许可证或商业库对象的对象池(不确定它们有什么样的公共接口)。
public class CommercialObjectFactory extends BasePoolableObjectFactory {
// for makeObject we'll simply return a new commercial object
@Override
public Object makeObject() {
return new CommercialObject();
}
}
GenericObjectPool pool = new GenericObjectPool(new CommercialObjectFactory());
// The size of pool in our case it is N
pool.setMaxActive(N)
// We want to wait if the pool is exhausted
pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK)
当您需要代码中的商业对象时。
CommercialObject obj = null;
try {
obj = (CommercialObject)pool.borrowObject();
// use the commerical object the way you to use it.
// ....
} finally {
// be nice return the borrwed object
try {
if(obj != null) {
pool.returnObject(obj);
}
} catch(Exception e) {
// ignored
}
}
如果这不是您想要的,那么您需要提供有关您的商业图书馆的更多详细信息。
【解决方案2】:
Spring 有一个 org.springframework.aop.interceptor.ConcurrencyThrottleInterceptor 可以通过 AOP 使用(或者底层代码可以单独使用)。这可能是比使用对象池更轻的方法。
【解决方案3】:
我正在考虑使用 SessionListener 在创建会话时增加计数,并在会话无效或超时时减少计数,以及保护对 URL 的调用的方面。但是一个将这两个想法明显结合在一起的设计让我望而却步。