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

Jersey Java服务器SSE连接始终处于Pending状态问题求助

解决Jersey 2.28 SSE连接Pending及SseEventSink字段未填充问题

看起来你遇到的SSE连接pending问题,和你发现的SseEventSink核心字段(requestScope、requestContext等)未填充直接相关——这大概率是请求上下文没有正确绑定到SSE处理流程导致的。结合Jersey 2.28的特性,给你几个针对性的排查和解决方向:

  • 检查请求上下文的绑定范围
    Jersey的SseEventSink完全依赖请求作用域(RequestScope)来初始化核心字段。如果你的service.subscribe(id, sink, sse)逻辑是在原请求线程外执行(比如异步线程池),就会导致上下文丢失,字段无法填充。
    解决办法:确保订阅逻辑在原请求线程中初始化,或者手动将请求上下文绑定到异步线程。如果是Jersey原生环境,可以用RequestScope API强制绑定:

    import org.glassfish.jersey.process.internal.RequestScope;
    import org.glassfish.jersey.process.internal.RequestScopeProvider;
    
    // 在资源方法中获取请求作用域
    RequestScope requestScope = RequestScopeProvider.getInstance().getRequestScope();
    // 用runInScope包裹异步逻辑
    requestScope.runInScope(Collections.emptyMap(), () -> {
        service.subscribe(id, sink, sse);
    });
    
  • 验证SSE依赖与容器配置的完整性
    虽然你引入了jersey-media-sse,但要确认是否搭配了正确的容器适配依赖,且开启了异步支持:

    1. Maven依赖要确保包含容器核心包:
      <dependency>
          <groupId>org.glassfish.jersey.media</groupId>
          <artifactId>jersey-media-sse</artifactId>
          <version>2.28</version>
      </dependency>
      <dependency>
          <groupId>org.glassfish.jersey.containers</groupId>
          <artifactId>jersey-container-servlet-core</artifactId>
          <version>2.28</version>
      </dependency>
      
    2. 在Jersey的Application类中注册SseFeature并开启异步:
      @ApplicationPath("/")
      public class SseApplication extends ResourceConfig {
          public SseApplication() {
              register(SseFeature.class);
              property(ServerProperties.ASYNC_SERVICE_ENABLED, true);
          }
      }
      
    3. Servlet容器(如Tomcat)的web.xml中要开启Servlet异步支持:
      <servlet>
          <servlet-name>JerseySseServlet</servlet-name>
          <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
          <init-param>
              <param-name>javax.ws.rs.Application</param-name>
              <param-value>com.yourpackage.SseApplication</param-value>
          </init-param>
          <async-supported>true</async-supported>
      </servlet>
      
  • 调整资源方法的执行顺序
    你当前是先执行订阅再发送初始消息,建议调换顺序:先发送初始消息确认上下文可用,再执行订阅逻辑。这样能更早发现上下文缺失的问题:

    @GET @Path("{id}") @Produces(MediaType.SERVER_SENT_EVENTS)
    public void orderUpdates(@PathParam("id") String id, @Context SseEventSink sink, @Context Sse sse, @Context Request request) {
        // 先打印请求上下文,确认是否有效
        System.out.println("当前请求上下文:" + request);
        // 先发送初始消息
        OutboundSseEvent initialMessage = sse.newEventBuilder().comment("Connection initiated").build();
        sink.send(initialMessage);
        // 再执行订阅
        service.subscribe(id, sink, sse);
    }
    

    如果打印的request为空,说明资源类没有被Jersey正确扫描,或者自定义拦截器/过滤器破坏了上下文传递。

  • 避免阻塞原请求线程
    如果service.subscribe是阻塞方法,会占用原请求线程导致SSE连接无法完成初始化。要确保订阅逻辑是异步非阻塞的,比如用Jersey的AsyncResponse或者自定义线程池处理后续事件推送。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:19:22