gpt4 book ai didi

java - Spring 长轮询

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:54:16 28 4
gpt4 key购买 nike

我们有一个有点独特的案例,我们需要与外部 API 接口(interface),这需要我们长时间轮询他们的端点以获取他们所谓的实时事件。

问题是我们可能有多达 80,000 人/设备在任何给定时间访问此端点,监听事件,每台设备/人 1 个连接。

当客户端从我们的 Spring 服务发出请求以对事件进行长轮询时,我们的服务会依次对外部 API 进行异步调用以对事件进行长轮询。外部 API 定义了最小长轮询超时,可以设置为 180 秒。

所以在这里我们遇到了一个带有队列的线程池无法工作的情况,因为如果我们有一个类似(5 分钟,10 最大,10 个队列)的线程池,那么正在处理的 10 个线程可能会占用在当前 10 个中的一个完成之前,聚光灯和队列中的 10 个将不会有机会。

我们需要为其提供服务或使其失败(我们将在其后放置负载均衡器等),但我们不想让客户端在没有实际轮询发生的情况下挂起。

我们一直在研究为此使用 DeferredResult,并从 Controller 返回它。

有些东西是

@RequestMapping(value = "test/deferredResult", method = RequestMethod.GET)
DeferredResult<ResponseEntity> testDeferredResult() {
final DeferredResult<ResponseEntity> deferredResult = new DeferredResult<ResponseEntity>();
CompletableFuture.supplyAsync(() -> testService.test()).whenCompleteAsync((result, throwable) -> deferredResult.setResult(result));
return deferredResult;
}

我在质疑我是否在正确的道路上,我是否应该为 CompletableFuture.supplyAsync() 方法提供一个执行器和什么样的执行器(和配置)以最好地完成我们的任务.

我已经阅读了各种文章、帖子等,我想看看是否有人有任何可能对我们的具体情况有所帮助的知识。

最佳答案

如果您使用阻塞 IO,您所描述的问题听起来不像是可以很好解决的问题。所以您走在正确的道路上,因为 DeferredResult 允许您使用任何线程生成结果,而不会阻塞 servlet 容器线程。

关于在上游调用长池 API,您还需要一个 NIO 解决方案。如果使用 Netty 客户端,则可以使用单个线程管理数千个套接字。当Netty中的NIO选择器检测到数据时,会得到一个 channel 回调,最终委托(delegate)给Netty工作线程池中的一个线程,调用deferredResult.setResult。如果您不执行阻塞 IO,工作池的大小通常根据 CPU 内核的数量来确定,否则您可能需要更多线程。

仍然存在许多挑战。

  • 您可能需要不止一台服务器(或网络接口(interface)),因为只有 65K 个端口。
  • Java 中的套接字没有写入超时,因此如果客户端拒绝从套接字读取数据,并且您发送的数据多于套接字缓冲区,您将阻塞 Netty 工作线程,然后一切都会停止( 逆转懒猴攻击)。这是大型异步设置中的一个经典问题,也是使用 Hystrix(Netflix 出品)等框架的原因之一。

关于java - Spring 长轮询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41877678/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com