2026/1/5 11:25:29
网站建设
项目流程
网站建设和使用现状,wordpress收不到注册邮件,自己做的网站能放到阿里云上,深圳龙岗区优化防控措施FastAdmin框架SSE实时消息推送实现教程
一、前言#xff1a;什么是SSE#xff1f; SSE#xff08;Server-Sent Events#xff0c;服务器发送事件#xff09;是一种基于HTTP的服务器向客户端单向推送实时数据的技术#xff0c;与WebSocket的双向通信不同#xff0c;SSE更…FastAdmin框架SSE实时消息推送实现教程一、前言什么是SSESSEServer-Sent Events服务器发送事件是一种基于HTTP的服务器向客户端单向推送实时数据的技术与WebSocket的双向通信不同SSE更适用于服务器向客户端主动推送、客户端仅接收的场景如实时通知、消息提醒、数据监控等。本教程基于FastAdminTP5.1内核实现SSE推送包含完整的后端接口、前端页面及交互逻辑可直接复用并根据业务扩展。二、核心实现逻辑总览SSE实现需满足两个核心条件后端按SSE标准格式输出数据并维持长连接前端通过EventSource对象监听服务器推送事件。整体流程如下后端创建SSE接口配置长连接响应头、禁用缓存循环推送格式化数据前端设计消息展示与控制界面开启/停止按钮JS通过EventSource建立连接监听服务器事件处理消息渲染与连接状态管理。三、后端实现控制器SSE接口开发在FastAdmin的前端控制器如application/index/controller/Index.php中添加SSE核心方法与测试页面方法代码分步骤拆解如下。3.1 完整控制器代码?phpnamespaceapp\index\controller;useapp\common\controller\Frontend;classIndexextendsFrontend{/** * 前台 SSE 消息推送接口 * 支持匿名访问也可根据业务要求强制登录 */publicfunctionsse(){// 1. 清理并禁用输出缓存确保消息实时性if(ob_get_level()0){ob_end_clean();}// 关闭PHP执行超时维持长连接set_time_limit(0);// 2. 设置SSE核心响应头FastAdmin/TP5.1通用header(Content-Type: text/event-stream);// SSE专属MIME类型header(Cache-Control: no-cache);// 禁止缓存header(Connection: keep-alive);// 保持长连接header(X-Accel-Buffering: no);// 禁用Nginx缓冲生产必加header(Access-Control-Allow-Origin: *);// 跨域支持生产替换为具体域名header(Access-Control-Allow-Methods: GET);header(Access-Control-Allow-Headers: Content-Type);// 3. 发送初始化事件告知客户端连接成功echoevent: sse_init\ndata: .json_encode([statussuccess,msg连接成功],JSON_UNESCAPED_UNICODE).\n\n;flush();// 4. 循环推送消息核心逻辑$count0;$maxCount50;// 最大推送次数避免无限循环while(true){// 检测客户端断开连接或达到最大次数终止循环if(connection_aborted()||$count$maxCount){break;}// 模拟业务数据可替换为数据库/Redis/MQ查询$data[id$count1,titleFastAdmin实时通知,content新消息.date(Y-m-d H:i:s),timedate(H:i:s),url/index/sse/detail];// 按SSE标准格式输出event指定事件名data为消息体echoevent: my_event\ndata: .json_encode($data,JSON_UNESCAPED_UNICODE).\n\n;// 强制刷新缓冲区确保消息立即推送flush();// 控制推送频率每2秒1条可根据业务调整sleep(2);$count;}// 5. 清理资源ob_clean();return;}/** * SSE测试页面渲染方法 */publicfunctiontest(){return$this-view-fetch();}}3.2 代码分步拆解说明步骤1缓存与超时配置确保实时性// 清理已存在的输出缓存if(ob_get_level()0){ob_end_clean();}// 关闭PHP执行超时SSE需长连接默认超时会断开set_time_limit(0);关键说明FastAdmin默认可能开启输出缓冲需清理缓冲确保消息即时推送set_time_limit(0)取消PHP执行时间限制避免长连接被强制中断。步骤2SSE核心响应头必配项header(Content-Type: text/event-stream);// 告诉浏览器这是SSE流header(Cache-Control: no-cache);// 禁止浏览器缓存推送内容header(Connection: keep-alive);// 启用HTTP长连接header(X-Accel-Buffering: no);// 禁用Nginx代理缓冲生产环境必须加否则消息会延迟header(Access-Control-Allow-Origin: *);// 跨域配置开发环境用*生产替换为你的域名如https://xxx.com关键说明X-Accel-Buffering: no是生产环境核心配置Nginx默认会缓冲输出内容导致消息无法实时推送必须禁用。步骤3发送连接初始化事件echoevent: sse_init\ndata: .json_encode([statussuccess,msg连接成功],JSON_UNESCAPED_UNICODE).\n\n;flush();SSE标准格式规则event: 事件名自定义事件标识前端需通过对应事件名监听data: 数据内容消息主体建议用JSON格式结尾必须用\n\n两个换行标识一条消息结束flush()强制刷新输出缓冲区确保消息立即发送到客户端。步骤4循环推送业务消息$count0;$maxCount50;// 限制最大推送次数避免服务器资源浪费while(true){// 退出条件客户端断开连接 或 达到最大推送次数if(connection_aborted()||$count$maxCount){break;}// 1. 业务逻辑查询数据库/Redis/MQ获取真实数据此处为模拟$data[id$count1,titleFastAdmin实时通知,content新消息.date(Y-m-d H:i:s),timedate(H:i:s),url/index/sse/detail// 消息详情页地址];// 2. 按SSE格式输出消息事件名my_event前端对应监听echoevent: my_event\ndata: .json_encode($data,JSON_UNESCAPED_UNICODE).\n\n;flush();// 3. 控制推送频率每2秒1条可根据业务调整sleep(2);$count;}关键说明connection_aborted()用于检测客户端是否主动断开连接如关闭页面避免服务器空循环实际开发中需将模拟数据替换为真实业务查询如查询未读消息表。四、前端实现页面与交互逻辑前端包含两部分页面结构HTML和交互逻辑JS需放在FastAdmin对应的视图与JS目录中。4.1 前端页面HTML路径application/index/view/index/test.html用于展示控制按钮和实时消息。!-- 引入FastAdmin公共资源无需修改 --!-- 前台页面内容 --divclasscontainerh2我的实时消息/h2!-- 新增拆分开启/停止两个独立按钮 --divstylemargin:10px 0;display:flex;gap:10px;buttonidsse-start-btnclasslayui-btn layui-btn-normalstylepadding:6px 15px;开启实时通知/buttonbuttonidsse-stop-btnclasslayui-btn layui-btn-dangerstylepadding:6px 15px;opacity:0.5;cursor:not-allowed;停止实时通知/buttonspanidsse-statusstylemargin-left:10px;color:#999;align-self:center;未连接/span/div!-- 消息展示区域 --dividmsg-containerstylewidth:100%;max-width:600px;height:400px;border:1px solid #eee;padding:10px;overflow-y:auto;margin-top:20px;/div/div页面核心元素说明sse-start-btn开启SSE连接按钮sse-stop-btn停止SSE连接按钮默认禁用sse-status显示连接状态未连接/已连接/已停止msg-container实时消息渲染容器。4.2 交互逻辑JS路径public/assets/js/frontend/index.js核心是通过EventSource与后端建立连接处理消息与状态。4.2.1 完整JS代码define([jquery,bootstrap,frontend,form,template],function($,undefined,Frontend,Form,Template){varController{test:function(){// SSE核心变量 leteventSourcenull;// EventSource实例SSE连接核心letisSSEConnectedfalse;// 连接状态标记letisManuallyStoppedfalse;// 手动停止标记区分手动停止和异常断开// 核心方法 /** * 关闭SSE连接 * param {boolean} forceStop - 是否为手动停止 */functioncloseSSE(forceStopfalse){if(eventSource){eventSource.close();// 关闭连接eventSourcenull;isSSEConnectedfalse;if(forceStop){isManuallyStoppedtrue;// 标记为手动停止避免自动重连}updateSSEUI();// 更新按钮与状态UI}}/** * 初始化SSE连接 */functioninitSSE(){// 避免重复连接已连接 或 手动停止后不允许重复初始化if(isSSEConnected||isManuallyStopped)return;closeSSE();// 确保之前的连接已关闭isManuallyStoppedfalse;// 后端SSE接口地址需与控制器路由一致constsseUrl/index/index/sse;try{// 1. 创建EventSource实例建立连接eventSourcenewEventSource(sseUrl);isSSEConnectedtrue;updateSSEUI();// 初始化后立即更新UI// 2. 监听后端连接成功事件对应后端的sse_init事件eventSource.addEventListener(sse_init,function(e){constresJSON.parse(e.data);console.log(SSE连接成功,res);$(#sse-status).text(已连接实时接收消息).css(color,#009688);});// 3. 监听后端业务消息事件对应后端的my_event事件核心eventSource.addEventListener(my_event,function(e){constdataJSON.parse(e.data);// 解析后端推送的JSON数据console.log(收到业务消息,data);renderMsg(data);// 渲染消息到页面});// 4. 监听连接错误异常断开时触发eventSource.onerrorfunction(err){console.error(SSE连接错误,err);isSSEConnectedfalse;updateSSEUI();// 非手动停止的异常断开3秒后自动重连if(!isManuallyStopped){closeSSE();setTimeout(initSSE,3000);}};}catch(err){console.error(初始化SSE失败,err);// 非手动停止的失败5秒后重试if(!isManuallyStopped){setTimeout(initSSE,5000);}}}/** * 渲染消息到页面 * param {object} data - 后端推送的消息数据 */functionrenderMsg(data){constmsgContainer$(#msg-container)[0];// 创建消息DOM元素使用layui风格样式constmsgItemdocument.createElement(div);msgItem.stylepadding: 8px; margin: 5px 0; background: #f9f9f9; border-radius: 4px;;// 消息内容拼接可根据需求修改样式msgItem.innerHTMLdivstrong${data.title}/strong small stylecolor: #999;${data.time}/small/div div stylemargin-top: 5px;${data.content}/div div stylemargin-top: 5px;a href${data.url} stylecolor: #009688;查看详情/a/div;// 添加到消息容器并自动滚动到底部msgContainer.appendChild(msgItem);msgContainer.scrollTopmsgContainer.scrollHeight;}/** * 更新UI状态按钮禁用/启用 状态文字 */functionupdateSSEUI(){const$startBtn$(#sse-start-btn);const$stopBtn$(#sse-stop-btn);const$status$(#sse-status);if(isSSEConnected!isManuallyStopped){// 已连接状态禁用开启按钮启用停止按钮$startBtn.prop(disabled,true).css({opacity:0.5,cursor:not-allowed});$stopBtn.prop(disabled,false).css({opacity:1,cursor:pointer});$status.text(已连接实时接收消息).css(color,#009688);}else{// 未连接/已停止状态启用开启按钮禁用停止按钮$startBtn.prop(disabled,false).css({opacity:1,cursor:pointer});$stopBtn.prop(disabled,true).css({opacity:0.5,cursor:not-allowed});if(isManuallyStopped){$status.text(已停止需重新开启).css(color,#FF5722);}else{$status.text(未连接点击开启通知).css(color,#999);}}}// 事件绑定 $(function(){// 开启SSE连接按钮点击事件$(#sse-start-btn).off(click).on(click,function(){if(!isSSEConnected!isManuallyStopped){initSSE();}});// 停止SSE连接按钮点击事件$(#sse-stop-btn).off(click).on(click,function(){closeSSE(true);// 传入true标记为手动停止});});// 页面关闭时清理 // 页面刷新/关闭前主动断开SSE连接释放服务器资源$(window).on(beforeunload,function(){closeSSE();});},};returnController;});4.2.2 JS核心逻辑拆解1. 核心变量定义leteventSourcenull;// EventSource实例SSE连接的核心对象letisSSEConnectedfalse;// 标记是否处于连接状态letisManuallyStoppedfalse;// 标记是否为用户手动停止避免异常重连2. 连接管理方法initSSE()初始化连接创建EventSource实例监听后端3类事件连接成功、业务消息、连接错误closeSSE()关闭连接更新状态标记避免异常重连updateSSEUI()根据连接状态同步按钮禁用/启用状态和状态文字提升用户体验。3. 消息渲染逻辑renderMsg()方法负责将后端推送的JSON数据转化为页面DOM元素核心功能创建符合Layui风格的消息卡片拼接消息标题、内容、时间和详情链接添加消息到容器后自动滚动到底部确保用户看到最新消息。五、部署与测试5.1 路由配置FastAdmin直接不写了按路径去访问在route/route.php中添加前端访问路由确保页面和接口可访问// SSE测试页面路由Route::get(index/test,index/index/test);// SSE推送接口路由Route::get(index/sse,index/index/sse);5.2 测试步骤启动FastAdmin项目访问测试页面http://你的域名/index/test点击「开启实时通知」按钮状态变为「已连接实时接收消息」消息容器中每2秒会新增一条实时消息控制台可查看调试日志点击「停止实时通知」按钮连接断开状态变为「已停止需重新开启」若关闭页面再重新打开会自动恢复连接异常断开后3秒自动重连。5.3 生产环境注意事项跨域配置将控制器中Access-Control-Allow-Origin: *替换为你的前端域名如https://admin.xxx.com避免跨域安全风险Nginx配置确保Nginx禁用缓冲可在站点配置中添加proxy_buffering off;与后端X-Accel-Buffering: no配合使用连接限制SSE基于HTTP长连接需根据服务器配置调整最大并发连接数如Nginx的worker_connections业务优化将模拟数据替换为Redis/消息队列查询避免数据库频繁查询可根据用户ID过滤消息需结合登录状态在接口中添加用户认证推送次数根据业务需求调整$maxCount最大推送次数或移除次数限制需确保有可靠的退出条件。六、常见问题排查问题现象排查方向点击开启按钮无反应控制台无日志1. 检查JS路径是否正确引入2. 确认sseUrl与路由配置一致3. 查看浏览器控制台「网络」面板是否有SSE接口请求消息延迟推送或批量推送1. 确认后端添加X-Accel-Buffering: no响应头2. 检查Nginx是否配置proxy_buffering off;3. 确保代码中每次输出后调用flush()连接频繁断开自动重连无效1. 检查服务器是否开启防火墙/安全组限制2. 确认PHPset_time_limit(0)已配置3. 查看服务器日志是否有内存溢出或进程被杀情况跨域错误1. 检查后端跨域响应头是否配置2. 确保前端域名与Access-Control-Allow-Origin一致3. 确认请求方法为GETSSE仅支持GET注意在这里用apache会有个坑你得去把apache的缓存啊啥的给关掉不然就会出现以下问题会等很久它全部一起输出七、总结本教程基于FastAdmin实现了轻量级的SSE实时推送功能核心优势在于无需引入额外组件基于HTTP协议实现开发成本低适用于消息通知、数据监控等单向推送场景。如需双向通信如聊天功能可考虑WebSocket技术而SSE则是单向推送场景的最优选择之一。可根据实际业务需求扩展以下功能用户登录态校验、消息已读/未读标记、自定义消息类型如系统通知、订单提醒、消息过滤与分页等。注文档部分内容可能由 AI 生成