在 Spring Web 方法中限制并发线程

Limit concurrent Threads in Spring Web Method

提问人:Cesar Lopes 提问时间:9/16/2023 最后编辑:Cesar Lopes 更新时间:9/16/2023 访问量:61

问:

我有一个Spring Web MVC应用程序,它在SOAP中有一个名为calculateWebMethod的Web方法。

由于并发请求的数量,服务器过载,我的团队决定将 Web 方法调用为公共静态同步方法,以使请求在单个 Thread 中运行,并且重载进入队列。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;
}

问题是队列太长,无法在可接受的时间内处理所有请求,但将所有内容都留在多个线程中会使服务器过载,是否可以限制执行 10 个或 n 个并发的线程数设置此执行时间限制并使重载进入队列?CalculateTask

Java Spring-MVC 线程池 已同步

评论

0赞 Sagar 9/16/2023
“设置此执行时间限制”执行时间意味着何时首次加载spring应用程序或参数化或其他方式?
1赞 Sagar 9/16/2023
如果考虑编译时间,FixedThreadpool 或 Semaphores 应该可以工作
0赞 Cesar Lopes 9/16/2023
这意味着池中的线程数应该是可更改的,而无需重新启动应用程序。谢谢,要看看 FixedThreadpool 和信号量

答:

2赞 hunter 9/16/2023 #1

当发出多个请求时,这将在并行线程中执行,首先您必须删除表单静态方法。 现在的问题是,由于服务器中的资源有限,无法处理大量的并发请求。 假设只允许 10 个并发请求,当请求出现时,如果存在 10 个正在进行的请求,则应定义预期的行为(天气它返回错误或请求排队。 如果是第二种方式,那么可能是调用方读取超时异常)。webmethodsyncronized

根据预期行为,有很多不同的解决方案,甚至可以实现自己的解决方案或现有解决方案。从技术上讲,这被称为 “速率限制” 。bucket4j 是您可以使用的一种实现。 这是一种你自己可以实现的简单方法(不完美,你可以通过学习和使用我们在 Java 并发包中内置的同步器来使其完美)

  1. 在控制器类中引入一个字段,或者任何具有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 
}

 


  
2赞 Usman Mutawakil 9/16/2023 #2

我相信你需要的是一个线程池。它们就是为此目的而建造的。您可以配置池中的线程数,并让池处理执行对计算器 Bean 的调用。您可以在 Google 上搜索的类是 ExecutorService 或 ThreadPoolExecutor。下面是 pseudo/Kotlin/Java 中的一个示例。如果您不需要实时响应,这将很好地工作。您可以让客户端代码发起请求,在单独的调用中查找结果,但我不知道您的业务需求。

执行人服务

定义线程池、池中的线程数和其他一些基础知识。

private val executorService: ExecutorService = ThreadPoolExecutor(
    1, 1, 0L, TimeUnit.MILLISECONDS,
    LinkedBlockingQueue<Runnable>()
)

现在,在控制器或 Web 请求处理程序中,告诉执行程序执行您的计算器 Bean 代码。它会将所有这些调用发送到池队列,并且您定义的受约束线程将处理它们。

处理请求

    @WebMethod(operationName="calculateWebMethod", action="calculateWebMethod")
public calculateWebMethodResponse calculateWebMethod(
@WebParam(name="param1") String param1,
@WebParam(name="param2") String param2,
...
) {
    executorService.execute {
        long webMethodResult = CalculateBean.CalculateTask(...params);
        return webMethodResult;
    }
}