如何在Mule 3.9.0中结合Http Listener与Jersey实现Server-Sent Events(SSE)并保持Socket连接不关闭?
在Mule 3.9.0中用Jersey实现Server-Sent Events(SSE)的解决方案
首先明确回答:完全可以在Mule 3.9.0版本中通过Jersey实现SSE,你遇到的连接被立即关闭的问题,主要是Mule Http Listener的默认超时配置和Jersey SSE特性未正确注册这两个核心原因导致的,下面是具体的解决步骤:
1. 调整Http Listener的连接超时配置
Mule的Http Listener默认有较短的connectionIdleTimeout(默认30秒左右),一旦连接空闲就会主动关闭,这和SSE需要长期保持连接的需求冲突。你需要在http:listener-config里显式设置更长的超时时间,或者设为0表示永不超时:
<http:listener-config name="HttpListenerConfig" host="0.0.0.0" basePath="/myservice" port="8090" connectionIdleTimeout="0" />
注意:设为0在生产环境要谨慎,建议根据业务场景设置一个合理的长超时(比如3600000毫秒=1小时),避免资源泄漏。
2. 确保Jersey SSE特性正确注册
你的当前配置里没有注册Jersey的SseFeature,这会导致SSE响应的头部和流处理逻辑不生效,Mule无法识别SSE的长连接需求。需要修改jersey:resources配置,添加SseFeature的注册:
<flow name="NotificationServiceFlow"> <http:listener config-ref="HttpListenerConfig" path="/sse/*" allowedMethods="GET" parseRequest="false" responseStreamingMode="ALWAYS"> </http:listener> <jersey:resources> <jersey:feature> <spring-object bean="org.glassfish.jersey.media.sse.SseFeature"/> </jersey:feature> <component> <spring-object bean="NotificationResource"/> </component> </jersey:resources> </flow>
或者你也可以在NotificationResource所在的Spring配置里,创建一个包含SseFeature的ResourceConfig bean,然后直接引用这个bean到jersey:resources中:
<bean id="sseResourceConfig" class="org.glassfish.jersey.server.ResourceConfig"> <constructor-arg> <list> <value>com.yourpackage.NotificationResource</value> <value>org.glassfish.jersey.media.sse.SseFeature</value> </list> </constructor-arg> </bean> <!-- 然后在flow里替换为: --> <jersey:resources ref="sseResourceConfig"/>
3. 优化Jersey资源的实现细节
你的NotificationResource实现基本没问题,但可以添加一个关闭监听器避免内存泄漏:
@GET @Produces(SseFeature.SERVER_SENT_EVENTS) public EventOutput subscribe() { final EventOutput eventOutput = new EventOutput(); broadcaster.add(eventOutput); // 添加关闭监听器,移除失效的eventOutput eventOutput.setCloseListener(new EventOutput.CloseListener() { @Override public void onClose(EventOutput eventOutput) { broadcaster.remove(eventOutput); } }); return eventOutput; }
4. 测试连接是否保持打开
可以用curl命令测试:
curl -N http://localhost:8090/myservice/sse/notifications
如果连接保持打开,没有立即断开,就说明配置生效了。此时调用broadcast方法发送消息,curl应该能实时收到。
常见问题排查
- 如果还是关闭连接,检查Mule的日志,看是否有超时或错误信息
- 确认没有其他Mule拦截器或过滤器主动关闭连接
- 确保Jersey的版本和Mule 3.9.0兼容(Mule 3.9.0默认集成的Jersey版本是2.25.1,建议使用对应版本的
jersey-media-sse依赖)
内容的提问来源于stack exchange,提问作者William
相关产品推荐
相关产品推荐

