📋 前言

在现代Web应用中,实时状态更新是提升用户体验的关键因素之一。传统的轮询(Polling)方式虽然简单,但存在资源浪费、延迟高等问题。本文将介绍我们如何在 Online Image Upscaler Server-Sent Events (SSE) 技术实现实时状态推送,以及这种技术带来的显著优势。

🎯 什么是 SSE?

Server-Sent Events (SSE) 是一种基于 HTTP 的服务器推送技术,允许服务器主动向客户端推送数据。与 WebSocket 不同,SSE 是单向通信(服务器→客户端),但实现更简单,兼容性更好。

SSE vs 传统轮询 vs WebSocket

| 特性 | 传统轮询 | SSE | WebSocket |

|------|---------|-----|-----------|

实时性 | ❌ 延迟高(取决于轮询间隔) | ✅ 接近实时 | ✅ 实时 |

实现复杂度 | ✅ 简单 | ✅ 简单 | ❌ 复杂 |

资源消耗 | ❌ 高(频繁请求) | ✅ 低(长连接) | ✅ 低 |

浏览器支持 | ✅ 所有浏览器 | ✅ 现代浏览器 | ✅ 现代浏览器 |

自动重连 | ❌ 需要手动实现 | ✅ 浏览器自动重连 | ❌ 需要手动实现 |

HTTP协议 | ✅ 标准HTTP | ✅ 标准HTTP | ❌ 需要升级协议 |

✨ SSE 的核心优势

1. 实时性好,延迟低

传统轮询需要客户端定期发送请求,即使没有更新也会产生请求。SSE 建立长连接后,服务器可以在状态变化时立即推送,延迟通常在毫秒级。

实际效果:

  • 传统轮询(2秒间隔):平均延迟 1-2 秒

  • SSE 推送:延迟 < 100 毫秒

2. 资源消耗低

SSE 使用单个长连接,相比频繁的轮询请求,大大减少了:

  • 网络请求次数

  • 服务器处理负载

  • 带宽消耗

数据对比:

  • 轮询(2秒间隔,处理30秒):15 次 HTTP 请求

  • SSE:1 次 HTTP 请求 + 1 次推送

3. 实现简单,维护成本低

SSE 基于标准 HTTP 协议,不需要:

  • 额外的 WebSocket 服务器

  • 复杂的连接管理

  • 协议升级处理

4. 自动重连机制

浏览器原生支持 SSE 自动重连,当连接断开时会自动尝试重新连接,无需手动实现重连逻辑。

5. 安全性好

SSE 使用标准 HTTP 协议,可以:

  • 利用现有的认证机制

  • 通过 HTTPS 加密传输

  • 使用 CORS 控制跨域访问

🛠️ 实现方案

架构设计

在我们的 Online Image Upscaler 平台中,SSE 主要用于实时推送图片处理状态。整体架构如下:


用户上传图片

    ↓

创建处理任务(返回 historyId)

    ↓

前端建立 SSE 连接(/api/realtime/status?historyId=xxx)

    ↓

后端 AI 处理(Replicate API)

    ↓

Webhook 接收处理结果

    ↓

SSE 推送状态更新

    ↓

前端实时更新 UI

后端实现

1. SSE 连接管理器

我们实现了一个轻量级的 SSE 连接管理器,支持按 historyId 分组管理连接:


// lib/sse-manager.ts

class SSEManager {

  private connections = new Map<number, Set<SSEConnection>>()



  // 添加连接

  addConnection(historyId: number, connection: SSEConnection) {

    if (!this.connections.has(historyId)) {

      this.connections.set(historyId, new Set())

    }

    this.connections.get(historyId)!.add(connection)

  }



  // 广播消息到指定 historyId 的所有连接

  broadcast(historyId: number, data: unknown) {

    const conns = this.connections.get(historyId)

    if (!conns || conns.size === 0) return



    const message = `data: ${JSON.stringify(data)}\n\n`

    conns.forEach(connection => {

      try {

        connection.write(message)

      } catch (error) {

        // 连接已关闭,自动移除

        this.removeConnection(historyId, connection)

      }

    })

  }

}
2. SSE 端点实现

// app/api/realtime/status/route.ts

export async function GET(request: NextRequest) {

  const historyId = parseInt(searchParams.get('historyId') || '0')



  // 验证用户权限

  // ...权限验证逻辑...



  // 创建 SSE 响应流

  const stream = new ReadableStream({

    start(controller) {

      // 发送初始连接消息

      controller.enqueue(encoder.encode(

        'data: {"type":"connected","historyId":' + historyId + '}\n\n'

      ))



      // 创建连接对象并注册

      const connection = {

        write: (data: string) => {

          controller.enqueue(encoder.encode(data))

        },

        close: () => {

          controller.close()

        }

      }



      sseManager.addConnection(historyId, connection)



      // 定期发送心跳(保持连接活跃)

      const heartbeatInterval = setInterval(() => {

        controller.enqueue(encoder.encode(': heartbeat\n\n'))

      }, 30000) // 每30秒

    }

  })



  return new Response(stream, {

    headers: {

      'Content-Type': 'text/event-stream',

      'Cache-Control': 'no-cache, no-transform',

      'Connection': 'keep-alive',

    }

  })

}
3. Webhook 推送

当 AI 处理完成时,通过 Webhook 接收结果,然后通过 SSE 推送:


// app/api/replicate/webhook/route.ts

export async function POST(request: NextRequest) {

  // 处理 Replicate Webhook 数据

  // ...



  // 更新数据库

  await prisma.processingHistory.update({

    where: { id: processingHistory.id },

    data: { status: 'COMPLETED', ... }

  })



  // 🔥 SSE 实时通知:广播处理完成消息

  sseManager.broadcast(processingHistory.id, {

    type: 'completed',

    historyId: processingHistory.id,

    status: 'completed',

    message: 'Processing completed',

    timestamp: new Date().toISOString(),

  })

}

前端实现

1. 建立 SSE 连接

// hooks/useImageProcessor.ts

const eventSource = new EventSource(

  `/api/realtime/status?historyId=${historyId}&anonymousId=${anonymousId}`

)



// 连接成功

eventSource.onopen = () => {

  console.log('SSE connection established')

  // 取消轮询,使用 SSE 作为主要通知方式

}



// 接收消息

eventSource.onmessage = (event) => {

  const data = JSON.parse(event.data)



  if (data.type === 'completed') {

    // 立即查询数据库获取完整结果

    fetch(`/api/dashboard/history/${historyId}`)

      .then(res => res.json())

      .then(result => {

        // 更新 UI

        updateImageStatus(result)

      })



    // 关闭 SSE 连接

    eventSource.close()

  }

}



// 错误处理(自动重连)

eventSource.onerror = (error) => {

  console.warn('SSE connection error, falling back to polling')

  // 回退到轮询机制

}
2. 混合策略:SSE + 轮询

为了确保可靠性,我们采用了 SSE + 轮询混合策略

  • 主要方式:SSE 实时推送(低延迟)

  • 后备方案:轮询(30秒间隔,确保 SSE 失败时仍能获取状态)

这样既保证了实时性,又确保了可靠性。

🎨 在 Online Image Upscaler 中的应用场景

场景描述

Online Image Upscalerhttps://onlineimageupscaler.com)是一个专业的在线 AI 图片处理平台,提供以下服务:

  • 🎨 AI 智能图片放大:2x-10x 无损放大

  • 🖼️ 照片修复:老照片修复、去模糊、锐化

  • 🎨 照片上色:黑白照片智能上色

  • 📝 文字增强:模糊文字清晰化

为什么需要实时状态推送?

图片处理是一个异步过程,通常需要 10-60 秒完成。在传统方案中,用户需要:

  • 不断刷新页面查看状态

  • 或者等待页面自动轮询(浪费资源)

使用 SSE 后:

  • ✅ 用户上传图片后,可以继续浏览其他内容

  • ✅ 处理完成后,立即收到通知

  • ✅ 无需频繁轮询,节省服务器资源

  • ✅ 体验流畅,接近原生应用

实际效果

用户体验提升:

  • 处理完成通知延迟:从平均 1-2 秒降低到 < 100 毫秒

  • 服务器请求减少:约 85% 的轮询请求被 SSE 替代

  • 用户满意度:实时反馈让用户感觉更专业、更可靠

技术指标:

  • SSE 连接成功率:> 95%

  • 平均推送延迟:< 100 毫秒

  • 服务器资源节省:约 80%

📊 性能对比

传统轮询方案


用户上传图片

    ↓

每 2 秒轮询一次状态

    ↓

30 秒处理时间 = 15 次 HTTP 请求

    ↓

平均延迟:1-2 秒

资源消耗:

  • HTTP 请求:15 次

  • 服务器处理:15 次数据库查询

  • 带宽:15 次响应传输

SSE 方案


用户上传图片

    ↓

建立 1 次 SSE 连接

    ↓

处理完成后立即推送

    ↓

平均延迟:< 100 毫秒

资源消耗:

  • HTTP 请求:1 次(建立连接)

  • 服务器处理:1 次推送

  • 带宽:1 次推送数据

性能提升:

  • 请求次数减少:93%

  • 延迟降低:90%

  • 服务器负载减少:约 80%

🔧 关键技术细节

1. 连接管理

  • 按 historyId 分组:每个处理任务可以有多个客户端连接(多标签页场景)

  • 自动清理:连接断开时自动移除,防止内存泄漏

  • 心跳机制:每 30 秒发送心跳,保持连接活跃

2. 权限控制

  • 用户验证:确保用户只能订阅自己的处理任务

  • 匿名用户支持:通过 anonymousId 支持未登录用户

  • 安全隔离:不同用户的数据完全隔离

3. 错误处理

  • 自动重连:浏览器自动重连机制

  • 降级策略:SSE 失败时自动回退到轮询

  • 超时处理:连接超时自动清理

4. 性能优化

  • 按需推送:只在状态变化时推送

  • 批量管理:支持多个连接同时管理

  • 资源清理:及时清理断开的连接

💡 最佳实践建议

1. 选择合适的场景

SSE 适合以下场景:

  • ✅ 服务器到客户端的单向数据推送

  • ✅ 实时状态更新(如处理进度、通知)

  • ✅ 需要低延迟的场景

不适合的场景:

  • ❌ 需要双向通信(使用 WebSocket)

  • ❌ 只需要一次性数据(使用普通 HTTP 请求)

2. 实现降级方案

始终提供轮询作为后备方案,确保在 SSE 不可用时系统仍能正常工作。

3. 控制连接数量

  • 限制每个用户的连接数

  • 及时清理断开的连接

  • 监控连接统计信息

4. 安全性考虑

  • 验证用户权限

  • 使用 HTTPS 加密

  • 防止跨站请求伪造(CSRF)

🚀 体验我们的实现

如果您想体验 SSE 技术在实际应用中的效果,欢迎访问:

🌐 Online Image Upscaler:https://onlineimageupscaler.com

在我们的平台上,您可以:

  1. 上传图片进行 AI 处理

  2. 实时查看处理状态更新(无需刷新页面)

  3. 立即收到处理完成通知

  4. 体验流畅的实时反馈

平台特色功能

  • 🎨 多种处理模式:图片放大、照片修复、照片上色、图片锐化、去模糊、文字增强

  • ⚡ 快速处理:云端 AI 加速,秒级完成

  • 🔒 隐私保护:处理完成后自动删除,保护用户数据

  • 💰 免费使用:基础功能完全免费,无需注册即可使用

  • 📱 多格式支持:支持 JPG、PNG、WebP 等主流格式

📚 技术总结

SSE 技术为我们提供了一个简单、高效、可靠的实时推送解决方案。在 Online Image Upscaler 平台中,SSE 不仅提升了用户体验,还显著降低了服务器资源消耗。

核心优势回顾:

  1. ✅ 实时性好:延迟 < 100 毫秒

  2. ✅ 资源消耗低:相比轮询减少 80% 以上请求

  3. ✅ 实现简单:基于标准 HTTP,无需额外服务器

  4. ✅ 自动重连:浏览器原生支持

  5. ✅ 安全性高:利用现有 HTTP 安全机制

如果您正在开发需要实时状态推送的应用,SSE 是一个值得考虑的优秀选择。


关于 Online Image Upscaler

Online Image Upscaler(https://onlineimageupscaler.com)是一个专业的在线 AI 图片处理平台,致力于为用户提供高质量、快速、安全的图片处理服务。我们采用先进的技术栈,包括 Next.js、TypeScript、Prisma 等,确保平台的稳定性和性能。

访问我们的平台: https://onlineimageupscaler.com

技术栈:

  • 前端:Next.js 15 + React 19 + TypeScript

  • 后端:Next.js API Routes + Prisma ORM

  • 实时通信:Server-Sent Events (SSE)

  • AI 处理:Replicate API

  • 存储:Cloudflare R2 + CDN


本文档由 Online Image Upscaler 技术团队编写,分享我们在 SSE 技术应用中的实践经验。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐