1)我的环境是web应用程序,我开发servlet来接收请求。
A)在某些块/方法中,我想控制并发到不大于5
B)如果该块中有5个请求,则新的必须等待最多60秒然后抛出错误
C)如果有超过30的睡眠/等待请求,则第31个请求将被抛出错误
我是怎么做到的?
上面的2)(可选问题)我必须将控制逻辑分发给所有集群主机。 我计划使用hazelcast来共享控制逻辑(例如当前计数器)
我看到他们提供了BlockingQueue& ExectorService,但我不知道如何在我的情况下使用。 如果您有任何想法,请推荐。
答案 0 :(得分:1)
对于A,请看一下:http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Semaphore.html
对于B,请查看Object.wait()和Object.notify()
如果你有A和B,那么C应该很容易。
答案 1 :(得分:1)
@Roman和@David Soroko的回答说如何在servlet中执行此操作(如OP所要求的那样)。
但是,这种方法的问题是tomcat必须为每个请求分配一个线程,以便它们可以参与servlet实现的排队/超时逻辑。每个线程都使用内存和其他资源。 这不能很好地扩展。如果您没有配置足够的线程,请求将被tomcat请求调度程序删除或使用不同的逻辑排队/超时。
另一种方法是在Web服务器中使用非servlet体系结构;例如Grizzly,更具体地说是Grizzly Comet。这是一个很大的话题,坦率地说,我不太了解它,深入了解实施细节。
编辑 - 在servlet模型中,每个请求在其整个生命周期内都会分配给单个线程。例如,在典型的“服务器推送”模型中,每个活动客户端都有一个未完成的HTTP请求,要求服务器提供更多数据。当新数据到达服务器时,服务器发送响应,客户端立即发送新请求。在经典的servlet实现模型中,这意味着服务器必须具有“正在进行中”的请求...以及针对每个活动客户端的线程......即使大多数线程只是等待数据到达。
在可扩展的体系结构中,您将从线程中分离请求,以便该线程可用于处理另一个请求。稍后(例如,当数据“到达”“服务器推送”示例中)时,请求将附加到线程(可能是不同的线程)以继续处理。在Grizzly中,我理解这是使用基于事件的处理模型完成的,但我想你也可以使用基于协程的模型。
答案 2 :(得分:0)
尝试semaphors:
计数信号量。从概念上讲, 信号量保持一套许可证。 如有必要,每个acquire()都会阻塞 直到有许可证,然后 接受它。每个版本()添加一个 允许,可能释放一个 阻止收购者。但是,没有实际的 使用许可对象;信号量 只记下数字 可用并采取相应行动。