You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JAX-RS中是否应复用SseEventSink或保持其开启?

JAX-RS SSE端点最佳实践解答

关于EventSink共享的问题

  • 绝对不能跨客户端共享EventSink实例:每个SseEventSink都绑定到单个客户端的HTTP长连接,生命周期和客户端连接完全绑定。如果多个线程(不同客户端)共用同一个EventSink,会导致消息发送到错误的客户端,同时SseEventSink本身并非线程安全,多线程操作会引发并发问题。
  • 你类中注入的@Context SseEventSink eventSink是无效的,因为SseEventSink是请求作用域的,只能在请求方法中通过参数注入,类级别的注入无法获取到有效的实例。

关于try-with-resources的处理

  • 如果需要保持长连接持续推送消息,必须移除try (SseEventSink sink = eventSink)代码块。try-with-resources会在代码块执行完毕后自动关闭EventSink,也就是关闭客户端的HTTP连接,这意味着客户端只能收到一次消息就断开了,不符合SSE长连接推送的需求。
  • 正确的做法是保留eventSink的引用(比如存入一个线程安全的集合),在需要推送消息时调用它的send方法,直到客户端主动断开连接或者服务端决定关闭连接时,再手动调用eventSink.close()。

关于EventSink创建的性能问题

  • SseEventSink属于轻量级对象,它只是对底层HTTP输出流的包装,并非重量级资源。每次客户端请求创建一个实例是SSE的标准设计模式,不存在性能问题,无需担心频繁创建带来的开销。
  • 你需要维护一个SseEventSink的线程安全集合(比如CopyOnWriteArrayList),在客户端连接时将eventSink加入集合,连接关闭时(通过eventSink的onClose回调)从集合中移除,这样就能实现向所有在线客户端推送消息。

优化后的示例代码

@Path("/")
@ApplicationScoped
public class RestRepo {

    @Context
    private Sse sse;

    // 用线程安全的集合维护所有活跃的EventSink
    private final List<SseEventSink> activeSinks = new CopyOnWriteArrayList<>();

    @GET
    @Path("/sse")
    @Produces(MediaType.SERVER_SENT_EVENTS)
    public void registerClient(final @Context SseEventSink eventSink) {
        // 将新的EventSink加入集合
        activeSinks.add(eventSink);
        
        // 注册连接关闭回调,从集合中移除失效的sink
        eventSink.onClose(() -> activeSinks.remove(eventSink));
        
        // 发送初始连接确认消息
        eventSink.send(sse.newEvent("已连接到SSE服务"));
    }

    // 向所有在线客户端广播消息的方法
    public void broadcastMessage(String message) {
        SseEvent event = sse.newEventBuilder()
                            .data(message)
                            .build();
        for (SseEventSink sink : activeSinks) {
            // 异步发送消息,避免阻塞主线程
            sink.send(event, asyncResult -> {
                if (asyncResult.failed()) {
                    // 发送失败,移除失效的sink
                    activeSinks.remove(sink);
                }
            });
        }
    }
}

内容的提问来源于stack exchange,提问作者nimo23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 06:32:50