Мы лицензировали коммерческий продукт (продукт не важен в данном контексте), который ограничен количеством одновременных пользователей. Пользователи получают доступ к этому продукту через Spring Controller.
У нас есть N лицензий на этот продукт, и если к нему обращаются N + 1 пользователей, они получают неприятное сообщение об ошибке о необходимости покупки дополнительных лицензий. Я хочу убедиться, что пользователи не видят это сообщение, и предпочел бы, чтобы запросы к продукту просто «стояли в очереди», а не имели к нему доступ N + 1 пользователей. Конечно, они предпочли бы, чтобы я купил лицензии, поэтому их инструмент не позволяет нам делать это изначально.
Вместо возможности управлять инструментом я хотел бы ограничить количество одновременных сеансов с контроллером, чтобы они никогда не превышали N. Все остальные могут подождать.
Мы используем Spring MVC.
Любые идеи?




Что вам нужно, так это ObjectPool. Проверьте пул Apache Commons 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
}
}
Если это не то, что вам нужно, вам нужно будет предоставить более подробную информацию о вашей коммерческой библиотеке.
Я думаю о SessionListener, чтобы увеличивать счетчик при создании сеанса и уменьшать его, когда сеанс недействителен или истекает время ожидания, и аспект для защиты вызовов к URL-адресу. Но дизайн, который явно сочетает в себе две идеи, ускользает от меня.
Spring имеет org.springframework.aop.interceptor.ConcurrencyThrottleInterceptor, который можно использовать через АОП (или базовый код может использоваться автономно). Это может быть более легкий подход, чем использование пула объектов.