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

Javascript Event Listeners失效:聊天监控功能异常求助

问题:EventSource聊天监控页面突然失效

我维护的一个监控新评论的聊天数据库功能,正常运行两年后,近期所有带事件监听器的页面突然失效。

前端页面代码

<script>
var source = new EventSource('mychat.cfm');

source.addEventListener('message', function(e){
    document.body.innerHTML = e.data + document.body.innerHTML;
});

function select(id,style) {
    //set the question live and turn off any others
    document.querySelectorAll('div').forEach(function(item) {
        item.className = 'option';
    })
    var div = document.getElementById(id);
    div.classList.replace("option", style);
    console.log(div);
}
</script>

后端mychat.cfm代码

<cfcontent type="text/event-stream">
<script>
  function select(id,style) {
        var div = document.getElementById(id);
        div.classList.replace("option", style);
        //setTimeout(location.reload.bind(location), 300);
        return false;
    }
 </script>

<CFquery datasource="chat" name="topmesg" >
SELECT max(id) as topid FROM chats where  DATE_SUB(CURDATE(),INTERVAL 5 DAY) <= timestamp;
</CFquery>
<cfset topid=#topmesg.topid#-10>
<cfoutput>#topid#</cfoutput>

<cfsetting requesttimeout="800">

<cffunction name="sendData">
<cfoutput>data:<b>#author#</b>  |   #dateTimeFormat(Dateadd("h",1,mesg.timestamp), "ddd dd mmm - h:nn a")# <br> #mesg.message#</cfoutput>
<cfflush>
</cffunction>
<cfset fromDate = Now()>
<cfset toDate = DateAdd("n", 30 , Now())>
<cfloop from="#fromDate#" to="#toDate#" index="i" step="#CreateTimeSpan(0,0,0,1)#">
<cfoutput>#i#</cfoutput>
<CFquery datasource="chat" name="mesg" maxrows="10">
SELECT * FROM chats  where id > #topid#  order by id desc limit 0,11;
</CFquery>
<cfloop query="mesg">
    <cfset sendData()>
    <cfset topid=#id#>
</cfloop>
    <cfthread action="sleep" duration="1000"/>
<cfflush>
</cfloop>

当前运行环境

  • OS: Linux (4.14.252-131.483.amzn1.x86_64)
  • Java Version: 64bit 1.8.0_92 (Oracle Corporation) 64bit
  • Tomcat Version: Apache Tomcat/8.0.35
  • Lucee Version: 6.0.0.585

失效原因排查

  • SSE响应格式违规:mychat.cfm开头输出了<script>标签,SSE要求响应必须是纯文本事件流,任何额外HTML/JS代码都会破坏EventSource解析逻辑,导致连接异常终止。
  • 无效初始输出:<cfsetting>前直接输出的#topid#以及循环里的#i#时间戳,都不属于SSE规范的data:字段格式,会被判定为无效数据,触发连接错误。
  • Lucee版本兼容性问题:近期升级到Lucee 6.0.0.585,旧代码的输出缓冲、<cfflush>执行逻辑可能因版本变更出现异常,导致SSE流无法正确推送。
  • 查询逻辑冗余:查询中maxrows="10"和limit 0,11存在逻辑冲突,可能导致数据重复或漏查,同时<cfthread sleep>会额外消耗资源,影响连接稳定性。

解决办法

1. 清理SSE响应中的非规范内容

  • 删除mychat.cfm开头的<script>标签块,确保响应仅包含符合SSE格式的内容。
  • 移除初始的<cfoutput>#topid#</cfoutput>和循环内的<cfoutput>#i#</cfoutput>,避免无效数据干扰事件流解析。

2. 修正SSE事件流格式

SSE要求每个事件结尾必须有两个换行符,修改sendData函数:

<cffunction name="sendData">
    <cfoutput>data:<b>#author#</b>  |   #dateTimeFormat(Dateadd("h",1,mesg.timestamp), "ddd dd mmm - h:nn a")# <br> #mesg.message#</cfoutput>
    <cfoutput>#chr(10)##chr(10)#</cfoutput> <!-- SSE事件结束标记 -->
    <cfflush>
</cffunction>

3. 优化后端逻辑

  • 将<cfthread action="sleep" duration="1000"/>替换为<cfset sleep(1000)>,减少线程资源消耗。
  • 统一查询的分页逻辑,将maxrows="10"和limit 0,11改为limit 10,避免逻辑冲突:
    <CFquery datasource="chat" name="mesg">
    SELECT * FROM chats where id > #topid# order by id desc limit 10;
    </CFquery>
    

4. 验证环境配置

  • 确认Lucee的requesttimeout设置生效,避免长连接提前超时。
  • 检查Tomcat连接器配置,确保keep-alive功能开启,维持SSE所需的长连接。

5. 前端添加错误监听

增加错误捕获逻辑,方便排查连接问题,可选添加重连机制:

source.addEventListener('error', function(e) {
    console.error('EventSource连接错误:', e);
    if (e.readyState === EventSource.CLOSED) {
        // 5秒后尝试重连
        setTimeout(() => {
            source = new EventSource('mychat.cfm');
        }, 5000);
    }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 20:22:03