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

SSE连接持续触发onerror问题排查与修复咨询

问题修复方案

根据你提供的代码和问题描述,功能正常但客户端持续触发onerror,可以从以下几个方向排查修复:

1. 服务端响应头配置缺失(核心问题)

SSE对响应头有严格要求,你的Java代码中未设置必要的响应头,这是触发客户端错误的常见原因。修改服务端代码,为SseEmitter添加以下响应头:

public SseEmitter askStream(String prompt, Long cid) {
    final SseEmitter emitter = new SseEmitter(120000L);
    // 配置SSE必须的响应头
    emitter.setContentType("text/event-stream;charset=UTF-8");
    emitter.setHeader("Cache-Control", "no-cache");
    emitter.setHeader("Connection", "keep-alive");
    // 如果存在跨域请求,添加CORS头(根据实际场景调整)
    emitter.setHeader("Access-Control-Allow-Origin", "*"); 
    emitter.setHeader("Access-Control-Allow-Headers", "x-access-token,x-request-id");

    if (StringUtils.isBlank(prompt.trim())) {
        throw GlobalException.PARAM_VERIFY_EXCEPTION;
    }
    Long vipExpireTime = RequestContext.getVipExpireTime();
    if (vipExpireTime == null || vipExpireTime <= System.currentTimeMillis()) {
        freeUserChat(emitter, prompt, cid);
    } else {
        askStreamImpl(emitter, prompt, cid);
    }
    return emitter;
}

2. 服务端消息格式校验

确保服务端发送的消息符合SSE规范:每个消息必须以data: 开头,以两个换行符结尾。推荐使用SseEmitter.event()方法构造消息,避免手动拼接出错:

// 在freeUserChat或askStreamImpl中发送消息时
emitter.send(SseEmitter.event().data("推送的内容"));

3. 客户端错误处理逻辑优化

当前客户端一触发错误就直接关闭连接,可能误判正常的连接关闭(比如服务端主动结束推送)。同时,标准SSE没有onclose事件,你监听的onclose不会触发,导致无法正确识别连接结束状态,修改客户端代码:

export function doSseChatAsk(params: ChatAsk, onSseMessage: (msg: string) => void,) {
  let eventSource: EventSourcePolyfill;
  const accessToken = localStorage.getItem("x-access-token");
  var queryString = Object.keys(params).map(key => key + '=' + params[key as keyof ChatAsk]).join('&');
  eventSource = new EventSourcePolyfill('/ai/stream/chat/ask?' + queryString, {
    headers: {
      'x-access-token': accessToken ?? "",
      'x-request-id': uuid(),
    }
  });

  eventSource.onopen = () => {
    console.log("SSE连接已建立");
  }

  eventSource.onerror = (error) => {
    console.log("onerror", error);
    // 仅在连接异常时关闭,避免重复关闭已正常结束的连接
    if (eventSource && eventSource.readyState !== EventSource.CLOSED) {
      eventSource.close();
    }
  }

  eventSource.onmessage = e => {
    // 忽略心跳空消息(如果服务端配置了心跳)
    if (e.data.trim()) {
      onSseMessage(e.data);
    }
  };

  eventSource.addEventListener('complete', () => {
    console.log('数据传输完成');
    eventSource.close();
  });
  
  // 监听标准close事件,替换原有的onclose
  eventSource.addEventListener('close', () => {
    console.log('连接已关闭');
  });
}

4. 超时与心跳优化

服务端设置的超时时间为120秒,若推送时间超过该时长会触发超时断开。可以通过添加心跳包避免:

在服务端askStream方法中添加定时心跳任务:

ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
// 每隔30秒发送一个空心跳包
scheduler.scheduleAtFixedRate(() -> {
    try {
        if (!emitter.isCompleted() && !emitter.isFailed()) {
            emitter.send(SseEmitter.event().data(""));
        } else {
            scheduler.shutdown();
        }
    } catch (IOException e) {
        scheduler.shutdown();
    }
}, 30, 30, TimeUnit.SECONDS);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 05:02:08