相关疑难解决方法(0)

Servlet-3异步上下文,如何进行异步写操作?

问题描述

Servlet-3.0 API允许分离请求/响应上下文并在以后回复它.

但是,如果我尝试编写大量数据,例如:

AsyncContext ac = getWaitingContext() ;
ServletOutputStream out = ac.getResponse().getOutputStream();
out.print(some_big_data);
out.flush()
Run Code Online (Sandbox Code Playgroud)

对于Tomcat 7和Jetty 8,它实际上可能会阻塞 - 并且它确实阻塞了琐碎的测试用例.教程建议创建一个可以处理这种设置的线程池 - 这通常是对传统10K架构的反作用.

但是,如果我有10,000个打开的连接和一个让我们说10个线程的线程池,那么即使1%的具有低速连接或仅阻塞连接的客户端阻塞线程池并完全阻止彗星响应或减慢其速度也足够了显著.

预期的做法是获得"写就绪"通知或I/O完成通知,而不是继续推送数据.

如何使用Servlet-3.0 API完成,即如何获得:

  • I/O操作的异步完成通知.
  • 通过写入就绪通知获取非阻塞I/O.

如果Servlet-3.0 API不支持,那么是否有任何特定于Web Server的API(如Jetty Continuation或Tomcat CometEvent)允许真正异步处理此类事件而无需使用线程池伪造异步I/O.

有人知道吗?

如果这不可能,您可以参考文档确认吗?

示例代码中的问题演示

我附上了模拟事件流的代码.

笔记:

  • 它使用ServletOutputStream该抛出IOException来检测断开连接的客户端
  • 它发送keep-alive消息以确保客户端仍在那里
  • 我创建了一个线程池来"模拟"异步操作.

在这样的例子中,我明确定义了大小为1的线程池来显示问题:

  • 启动一个应用程序
  • 从两个终端运行curl http://localhost:8080/path/to/app(两次)
  • 现在发送数据 curd -d m=message http://localhost:8080/path/to/app
  • 两个客户都收到了数据
  • 现在暂停其中一个客户端(Ctrl + Z)并再次发送消息 curd -d m=message http://localhost:8080/path/to/app
  • 观察到另一个非挂起的客户端没有收到任何信息,或者在传输消息后停止接收保持活动请求,因为其他线程被阻止.

我想在不使用线程池的情况下解决这样的问题,因为使用1000-5000个开放连接,我可以非常快地耗尽线程池.

下面的示例代码.


import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import …
Run Code Online (Sandbox Code Playgroud)

java comet servlet-3.0

50
推荐指数
2
解决办法
3万
查看次数

标签 统计

comet ×1

java ×1

servlet-3.0 ×1