当前位置: 首页 > news >正文

SSE实践(1)

GetProgress 方法深度解析

一、方法概述

GetProgress是一个基于Server-Sent Events (SSE)技术实现的实时进度推送接口,是整个任务进度跟踪系统的核心组件。

核心职责

  • 建立客户端与服务端的长连接
  • 实时监控任务进度变化
  • 增量推送进度更新给前端
  • 任务完成后自动断开连接

二、技术原理

SSE 协议简介

Server-Sent Events是一种单向实时通信协议:

特性说明
通信方向服务端 → 客户端(单向)
连接方式基于 HTTP 的长连接
数据格式data: {JSON}\n\n
自动重连客户端自动尝试重连
兼容性现代浏览器均支持

与传统轮询的对比

对比项轮询 (Polling)SSE
请求方式客户端主动轮询服务端主动推送
连接状态短连接,频繁建立长连接,持续保持
实时性取决于轮询间隔实时推送
资源消耗较高(重复建立连接)较低(复用连接)

三、核心实现解析

3.1 参数校验与错误处理

[HttpGet("{taskId}/progress")]publicasyncTaskGetProgress(stringtaskId){// 任务存在性校验if(!_taskService.TaskExists(taskId)){Response.StatusCode=404;awaitResponse.WriteAsync("任务不存在");return;}// ...}

设计要点

  • 采用快速失败策略,避免无效的长连接占用资源
  • 直接操作Response对象返回错误,无需经过 MVC 管道

3.2 SSE 响应头配置

Response.Headers["Content-Type"]="text/event-stream";Response.Headers["Cache-Control"]="no-cache";Response.Headers["Connection"]="keep-alive";

响应头说明

响应头作用
Content-Typetext/event-stream标识 SSE 流格式
Cache-Controlno-cache禁用缓存,保证实时性
Connectionkeep-alive维持长连接状态

3.3 核心循环逻辑

varlastProgress=-1;varcompleted=false;while(!completed){// 获取最新任务状态vartask=_taskService.GetTask(taskId);if(task==null)break;// 增量推送:仅在进度变化时发送if(task.Progress!=lastProgress){lastProgress=task.Progress;vardata=new{TaskId=task.TaskId,Progress=task.Progress,Status=task.Status,Message=task.Message,Result=task.Result};varjson=System.Text.Json.JsonSerializer.Serialize(data);awaitResponse.WriteAsync($"data:{json}\n\n");awaitResponse.Body.FlushAsync();}// 任务完成检测if(task.Status=="completed"||task.Status=="failed"){completed=true;break;}// 500ms 轮询间隔awaitTask.Delay(500);}

执行流程
┌─────────────────────────────────────────────────────────────┐
│ GetProgress 主循环 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 获取任务信息 │───→│ 进度变化检测 │───→│ 增量推送更新 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │ │
│ ↓ ↓ ↓ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 任务完成检测 │←───│ 延迟500ms │←───│ 刷新响应流 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │
│ ↓ │
│ ┌──────────────┐ │
│ │ 退出循环 │ │
│ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

3.4 SSE 数据格式

推送的数据结构

字段类型说明
TaskIdstring任务唯一标识
Progressint进度百分比 (0-100)
Statusstring任务状态
Messagestring进度描述信息
Resultstring任务结果(完成时)

状态枚举

状态值含义
pending任务已创建,等待执行
processing任务正在执行中
completed任务执行完成
failed任务执行失败

实际推送示例

思考过程

GetProgress 方法解读

方法概述

这是一个 SSE (Server-Sent Events) 实时进度推送接口 ,是整个进度跟踪系统的核心方法,允许服务器主动向客户端推送任务进度更新。

技术原理

Server-Sent Events (SSE) 是一种单向的实时通信协议:

  • 客户端发起一次 HTTP 请求建立长连接
  • 服务器通过该连接持续推送事件
  • 无需客户端反复轮询,效率更高

核心流程

代码逐段解析 1. 参数校验与错误处理

  • 首先检查任务是否存在
  • 不存在则直接返回 404 错误 2. SSE 响应头设置
    响应头 作用 Content-Type: text/event-stream 告知客户端这是 SSE 流 Cache-Control: no-cache 禁止缓存,确保实时性 Connection: keep-alive 保持长连接
  1. 核心循环逻辑
    工作流程:

步骤 操作 说明 1 获取任务信息 从 TaskProgressService 获取当前任务状态 2 检测进度变化 只有进度改变时才推送(避免无效推送) 3 构建并发送 SSE 事件 序列化任务数据为 JSON 4 检查任务状态 任务完成或失败时退出循环 5 延迟等待 每 500ms 检查一次
4. SSE 数据格式
推送的数据格式:

与前端的交互

前端使用 EventSource 连接:

设计亮点

特性 实现方式 优势 增量推送 只在进度变化时推送 减少网络流量 长连接复用 使用 SSE 协议 比轮询更高效 自动断开 任务完成后退出循环 避免资源浪费 低延迟 500ms 检查间隔 平衡性能与实时性

总结

GetProgress 方法是一个 基于 SSE 的实时进度推送端点 ,通过长连接和增量更新机制,实现了高效的服务端主动推送,是前端进度条实时更新的核心技术支撑。

四、前端消费方式

4.1 EventSource 连接

consteventSource=newEventSource('/api/tasks/{taskId}/progress');eventSource.onmessage=(event)=>{constdata=JSON.parse(event.data);updateProgress(data.Progress,data.Message);};eventSource.onerror=()=>{console.error('SSE 连接失败');eventSource.close();};

4.2 生命周期管理

// 组件挂载时建立连接onMounted(()=>{eventSource=newEventSource(url);});// 组件卸载时关闭连接onUnmounted(()=>{eventSource?.close();});

五、设计亮点与架构考量

5.1 增量推送策略

问题:如果每次循环都推送数据,会造成大量无效网络传输。

解决方案:通过lastProgress变量记录上次推送的进度值,仅在进度变化时才发送数据。

if(task.Progress!=lastProgress){lastProgress=task.Progress;// 推送更新...}

5.2 优雅的连接管理

自动断开机制

if(task.Status=="completed"||task.Status=="failed"){completed=true;break;}

优势

  • 任务完成后自动释放资源
  • 避免僵尸连接占用服务器资源
  • 客户端收到最终状态后可安全关闭连接

5.3 性能优化

优化点实现方式效果
减少推送频率500ms 检查间隔平衡实时性与性能
增量更新仅推送变化数据减少网络流量
对象池复用TaskProgressService单例减少对象创建开销

5.4 线程安全考虑

由于TaskProgressService是单例服务,多个请求可能同时访问同一任务数据:

// TaskProgressService 中的更新方法publicvoidUpdateTask(stringtaskId,intprogress,stringstatus,stringmessage){if(_tasks.TryGetValue(taskId,outvartask)){task.Progress=progress;task.Status=status;task.Message=message;}}

六、应用场景与扩展

6.1 适用场景

场景说明
文件上传进度实时显示上传百分比
数据处理进度批量任务执行进度展示
报表生成进度复杂报表生成状态追踪
长时间任务监控CI/CD 流水线状态监控

6.2 扩展方向

1. 多任务订阅

  • 支持客户端订阅多个任务
  • 使用EventSourceevent字段区分任务

2. 心跳机制

  • 添加定期心跳包检测连接状态
  • 异常断开时自动重连

3. 历史进度查询

  • 保存任务进度历史
  • 支持进度回放功能

4. 权限控制

  • 增加任务访问权限校验
  • 支持任务隔离

七、总结

GetProgress方法通过 SSE 技术实现了高效的实时进度推送:

核心优势

  1. 低延迟:服务端主动推送,无需客户端轮询
  2. 高效率:增量更新策略,减少网络流量
  3. 高可靠:任务完成自动断开,避免资源泄漏
  4. 易集成:标准 SSE 协议,前端实现简单

技术价值

该方法展示了如何在 ASP.NET Core 中实现轻量级实时通信,为耗时操作提供直观的进度反馈,提升用户体验。


http://www.cnnetsun.cn/news/2592511.html

相关文章:

  • 如何搭建第一个AI智能体?零代码Coze完整教程
  • LangChain与LangGraph实战对比:如何为LLM应用选择正确框架
  • 腿式机器人混合控制:ILC与扭矩库的实践优化
  • C51开发中SFR与SBIT的正确声明与使用
  • C16x微控制器软件模拟I2C通信实现指南
  • 在Vitis Unified IDE里玩转图像处理:用官方Vision库5分钟搭建一个霍夫变换HLS工程
  • 基于注意力机制GAN的单图像SVBRDF恢复:从单张照片重建逼真材质
  • 自定义 ROS 2 机器人部署至 Gazebo Ionic 仿真环境(第一部分):ros_gz_bridge 消息桥接与多机器人管理
  • 基于MCP协议与Google Slides API实现AI对话到幻灯片自动化生成
  • 影刀RPA店群自动化多环境治理:开发测试生产三态隔离与数据脱敏
  • 量子计算加持:AI Agent的算力革命何时到来?
  • 2026效果好服务优GEO服务商甄选:口碑佳值得合作机构测评
  • 3D 视觉检测技术:结构光、ToF 与双目立体视觉选型实战
  • Mysql--基础知识点--113--innodb一张表最多适合2100万条数据的原因
  • 为什么你的Lovable工具总被设计师拒用?揭秘87%团队忽略的3个情感化设计断点
  • C++知识点复习(面向面试7)
  • 别再手动配OPC UA了!用Node-RED的opcua节点,5分钟搞定工业数据采集
  • 告别闪烁!用STM32F030的HAL I2C驱动CH455G实现稳定数码管显示
  • 零基础学网络安全,最大的误区不是笨,是学错了顺序
  • Python分布式锁实现:构建高并发环境下的资源保护机制
  • Rust内存管理模式:深入理解所有权系统
  • C语言联合体与枚举详解
  • 【OpenCV零基础保姆级入门】一篇吃透计算机视觉预处理!全套实战代码,适配YOLO/深度学习
  • AI写的毕业论文初稿双率超标?怎么选靠谱的降重降AI工具
  • 大模型AI校招核心考点解析:从Transformer到工程实践,助你拿下Offer!
  • Docker部署Nginx实战:宿主机端口映射详解与避坑指南
  • 私教服务 | 一场差点吵起来的测试环境搭建咨询,暴露了90%测试人的认知盲区
  • OPC中国是谁?智能体来了旗下开源共创社区全面介绍​
  • 别再混淆了!SAP库存转移全解析:MIGO 301/303 vs. UB STO到底怎么选?
  • 为什么企业都在做智能体战略?OPD 一人部门是最低成本路线