我有一个 Spring Web MVC 应用程序,它有一个 SOAP 中的 Web 方法,称为calculateWebMethod。
由于并发请求的数量导致服务器过载,我的团队决定让 Web 方法调用公共静态同步方法
CalculateTask
以使请求在单个线程中运行,并将过载放入队列中。
所以基本上我们有这样的场景:
public class CalculateBean {
public static synchronized long CalculateTask(params...) {
long result = null;
... code to calculate
return result;
}
}
@WebMethod(operationName="calculateWebMethod", action="calculateWebMethod")
public calculateWebMethodResponse calculateWebMethod(
@WebParam(name="param1") String param1,
@WebParam(name="param2") String param2,
...
) {
...
long webMethodResult = CalculateBean.CalculateTask(...params);
return webMethodResult;
}
问题是队列太长,无法在可接受的时间内处理所有请求,但是将所有内容都放在多个线程中会使服务器过载,是否可以限制执行的线程数
CalculateTask
以设置10或n个并发设置执行时间的限制并使过载进入队列?
当发出多个请求时,
webmethod
将在并行线程中执行,首先您必须从静态方法中删除syncronized
。
现在的问题是服务器资源有限,无法处理大量并发请求。
假设只允许 10 个并发请求,当一个请求到来时,如果有 10 个正在进行的请求,那么应该定义预期的行为(无论它返回错误还是请求排队。如果是第二种方式,那么调用者可能会读取超时异常)。
基于预期的行为,有很多不同的解决方案,甚至您可以实现自己的解决方案或现有的解决方案。从技术上讲,这称为“速率限制”。 Bucket4j 是您可以使用的一种实现。 这是您自己可以实现的一种简单解决方案(并不完美,您可以通过学习和使用我们在 java 并发包中内置的同步器来使其完美)
Semaphore semaphore = new Semaphore(10)
的类中引入一个字段
webmethod
然后在Web方法中使用这种逻辑
if (semaphore.tryAcquire())
{
try
{
// your call to calculate task and return the result
}
finally
{
semaphore.release();
}
}
else
{
//handle or throw error , this is the 11th call while 10 ongoing requests are there
}