如何延长Wildfly中Server-Sent Events(SSE)连接的超时时间
解决Wildfly中SSE连接超时导致ClosedChannelException的问题
一、调整Undertow全局连接超时配置
Wildfly默认的Undertow读写超时约1分钟,会自动断开空闲的SSE连接。你可以修改standalone.xml或domain.xml中的Undertow子系统配置,延长超时时间:
找到Undertow子系统下的HTTP监听器配置,修改read-timeout、write-timeout和socket-timeout参数(单位:毫秒),比如设置为1小时:
<subsystem xmlns="urn:jboss:domain:undertow:12.0"> <server name="default-server"> <http-listener name="default" socket-binding="http" read-timeout="3600000" write-timeout="3600000" socket-timeout="3600000"/> <!-- 其他原有配置 --> </server> </subsystem>
注意:全局调整会影响所有HTTP请求,若普通REST请求不需要这么长的超时,建议使用下面的局部配置方案。
二、针对SSE端点单独配置超时
如果不想全局修改服务器参数,可以在Undertow配置中为SSE路径单独设置超时:
<subsystem xmlns="urn:jboss:domain:undertow:12.0"> <server name="default-server"> <host name="default-host" alias="localhost"> <location name="/你的应用上下文/publish" handler="welcome-content"> <http-options read-timeout="3600000" write-timeout="3600000"/> </location> </host> </server> </subsystem>
替换/你的应用上下文/publish为你的SSE端点实际上下文路径。
另外,也可以在JAX-RS端点上使用@Suspend注解指定超时(部分Wildfly版本支持):
@GET @Path("publish/{token}") @Produces(SERVER_SENT_EVENTS) @Suspend(timeout = 3600000) // 设置1小时超时 public void sseProcessed(@PathParam("token") final String token, @Context final SseEventSink sink) { sseClientRegistry.add(Integer.parseInt(token), sink); }
三、发送心跳事件维持连接(无需修改服务器配置)
如果不想调整服务器超时参数,可通过定期发送心跳事件保持连接活跃。在你的sseClientRegistry中添加定时任务,每隔一段时间向所有活跃的SseEventSink发送空注释事件:
// 示例:每隔5分钟发送一次心跳 ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); scheduler.scheduleAtFixedRate(() -> { sseClientRegistry.getAllSinks().forEach(sink -> { if (!sink.isClosed()) { sink.send(sse.newEventBuilder().comment("ping").build()); } }); }, 0, 300, TimeUnit.SECONDS);
这种方式能避免连接因空闲被断开,同时不影响其他请求的默认超时设置,适合需要维持大量SSE连接的场景。
内容的提问来源于stack exchange,提问作者Johan Steenkamp
相关产品推荐
相关产品推荐

