精通服务器推送事件(SSE)与 Python 和 Go 实现实时数据流 🚀

简介: 服务器推送事件(SSE)是HTML5规范的一部分,允许服务器通过HTTP向客户端实时推送更新。相比WebSocket,SSE更轻量、简单,适合单向通信场景,如实时股票更新或聊天消息。它基于HTTP协议,使用`EventSource` API实现客户端监听,支持自动重连和事件追踪。虽然存在单向通信与连接数限制,但其高效性使其成为许多轻量级实时应用的理想选择。文中提供了Python和Go语言的服务器实现示例,以及HTML/JavaScript的客户端代码,帮助开发者快速集成SSE功能,提升用户体验。

在当今的互动型 Web 应用程序中,实时数据更新在提升用户体验方面起着至关重要的作用。无论是实时股票更新、即时聊天消息,还是流式评论,实时数据流都是不可或缺的。在各种可用于实时通信的技术中,服务器推送事件(SSE)作为一种广泛使用且高效的解决方案脱颖而出。SSE 允许服务器通过 HTTP 向客户端推送实时更新,提供了一种轻量且高效的方式。

为什么选择服务器推送事件(SSE)? 🤔

服务器推送事件 是 HTML5 规范的一部分,专门设计用于将事件从服务器推送到客户端。其简单性、自动重连和事件追踪功能,使其非常适合需要持续数据流的场景。在单向数据流的情况下,SSE 尤其表现出色。

概述 📚

服务器推送事件(SSE)是一项技术,允许服务器向浏览器推送实时更新。它是 HTML5 规范的一部分,主要涉及:

  1. 通信协议:使用 HTTP。
  2. EventSource 对象:在浏览器端的 JavaScript 中可用。

虽然 SSE 和 WebSocket 都支持从服务器到客户端的实时通信,但它们有一些区别:

SSE WebSocket
基于 HTTP 基于 TCP
单向通信(从服务器到客户端) 双向通信(全双工)
轻量且简单 更复杂
内置重连和消息追踪功能 需要手动实现这些功能
支持文本或 Base64 编码并压缩的二进制数据 支持各种数据类型
支持自定义事件类型 不支持自定义事件类型
限制在 HTTP/1.1 或 HTTP/2 连接数上 连接数无限制

服务器实现 🌐

协议实现

基本上,浏览器发起一个 HTTP 请求,服务器返回 HTTP 状态及数据,并包含以下头信息:

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

SSE 指定事件流的 MIME 类型必须为 text/event-stream,浏览器不应缓存数据,并且连接应保持持久(keep-alive)。

消息格式

事件流是 UTF-8 编码的文本,或经过 Base64 编码并使用 gzip 压缩的二进制消息。每条消息由一行或多行字段组成,格式为 field-name: field-value。每个字段以 \n 结束。以冒号(:)开头的行是注释,浏览器会忽略这些行。每次推送可以由多个消息组成,消息之间用一个空行(\n\n)分隔。

关键字段包括:

  • event:指定事件类型。
  • id:事件 ID,用于浏览器跟踪最后接收到的事件,以便重连时使用。
  • retry:当连接失败时,浏览器等待重新连接的时间(以毫秒为单位)。
  • data:消息数据。

示例:Python 服务器实现 SSE

from flask import Flask, Response

app = Flask(__name__)

@app.route('/events')
def sse_handler():
    def generate():
        paragraph = [
            "Hello, this is an example of a continuous text output.",
            "It contains multiple sentences, each of which will be sent to the client as an event.",
            "This is to simulate the functionality of Server-Sent Events (SSE).",
            "We can use this method to push real-time updates.",
            "End of sample text, thank you!",
        ]

        for sentence in paragraph:
            yield f"data: {sentence}\n\n"
            import time
            time.sleep(1)

    return Response(generate(), mimetype='text/event-stream')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8081, debug=True)

示例:Go 服务器实现 SSE

package main

import (
    "fmt"
    "log"
    "net/http"
    "time"
)

func main() {
   
    http.HandleFunc("/events", sseHandler)

    fmt.Println("Starting server on :8080")
    if err := http.ListenAndServe(":8080", nil); err != nil {
   
       log.Fatalf("Server error: %v", err)
    }
}

func sseHandler(w http.ResponseWriter, r *http.Request) {
   
    flusher, ok := w.(http.Flusher)
    if !ok {
   
       http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
       return
    }

    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")

    paragraph := []string{
   
       "Hello, this is an example of a continuous text output.",
       "It contains multiple sentences, each of which will be sent to the client as an event.",
       "This is to simulate the functionality of Server-Sent Events (SSE).",
       "We can use this method to push real-time updates.",
       "End of sample text, thank you!",
    }

    for _, sentence := range paragraph {
   
       _, err := fmt.Fprintf(w, "data: %s\n\n", sentence)
       if err != nil {
   
          return
       }
       flusher.Flush()
       time.Sleep(1 * time.Second) // Wait 1 second before sending the next piece of text
    }
}

浏览器 API 🖥️

在客户端,JavaScript 的 EventSource API 允许你创建一个 EventSource 对象,监听服务器发送的事件。一旦连接建立,服务器可以通过具有 text/event-stream 内容类型的 HTTP 响应向浏览器发送事件消息。浏览器可以通过监听 EventSource 对象的 onmessageonopenonerror 事件来处理这些消息。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SSE Example 🌟</title>
</head>
<body>
    <h1>Server-Sent Events Example 🚀</h1>
    <div id="messages"></div>
    <script>
        window.onload = function() {
    
            if (typeof(EventSource) !== "undefined") {
    
                const eventSource = new EventSource('/events');

                eventSource.onmessage = function(event) {
    
                    const newElement = document.createElement("p");
                    newElement.textContent = "Message: " + event.data;

                    document.getElementById("messages").appendChild(newElement);
                };

                eventSource.onerror = function(event) {
    
                    console.error("Error occurred: ", event);
                    const newElement = document.createElement("p");
                    newElement.textContent = "An error occurred while connecting to the event source.";
                    document.getElementById("messages").appendChild(newElement);
                    eventSource.close(); 
                };
            } else {
    
                document.getElementById("messages").textContent = "Sorry, your browser does not support server-sent events...";
            }
        };
    </script>
</body>
</html>

结论 🏁

SSE 是一种基于 HTTP 协议的轻量级实时通信技术。它在服务器驱动的事件、自动重连和向客户端推送更新方面表现出色。然而,SSE 也有一些局限性,如单向通信、连接数限制和仅限于 GET 请求。它非常适合像实时股票更新、日志推送和聊天房间中的实时用户计数等场景。

对于需要高并发、高吞吐量和低延迟的场景,WebSocket 可能是更好的选择。相反,SSE 更适合简单、轻量的推送场景。在选择实时更新解决方案时,请根据应用程序的具体需求和背景做出选择。

通过遵循提供的实现细节和示例,你将能够将 SSE 集成到你的项目中,并模拟类似 ChatGPT 的数据流,提升用户体验。 🚀🔥

相关文章
|
7月前
|
人工智能 JavaScript API
零基础构建MCP服务器:TypeScript/Python双语言实战指南
作为一名深耕技术领域多年的博主摘星,我深刻感受到了MCP(Model Context Protocol)协议在AI生态系统中的革命性意义。MCP作为Anthropic推出的开放标准,正在重新定义AI应用与外部系统的交互方式,它不仅解决了传统API集成的复杂性问题,更为开发者提供了一个统一、安全、高效的连接框架。在过去几个月的实践中,我发现许多开发者对MCP的概念理解透彻,但在实际动手构建MCP服务器时却遇到了各种技术壁垒。从环境配置的细节问题到SDK API的深度理解,从第一个Hello World程序的调试到生产环境的部署优化,每一个环节都可能成为初学者的绊脚石。因此,我决定撰写这篇全面的实
1793 67
零基础构建MCP服务器:TypeScript/Python双语言实战指南
|
10月前
|
JavaScript 前端开发 Java
通义灵码 Rules 库合集来了,覆盖Java、TypeScript、Python、Go、JavaScript 等
通义灵码新上的外挂 Project Rules 获得了开发者的一致好评:最小成本适配我的开发风格、相当把团队经验沉淀下来,是个很好功能……
1655 103
|
6月前
|
人工智能 自然语言处理 安全
Python构建MCP服务器:从工具封装到AI集成的全流程实践
MCP协议为AI提供标准化工具调用接口,助力模型高效操作现实世界。
1235 1
|
10月前
|
Python
使用Python实现multipart/form-data文件接收的http服务器
至此,使用Python实现一个可以接收 'multipart/form-data' 文件的HTTP服务器的步骤就讲解完毕了。希望通过我的讲解,你可以更好地理解其中的逻辑,另外,你也可以尝试在实际项目中运用这方面的知识。
485 69
|
7月前
|
人工智能 负载均衡 监控
使用 Go 和 Gin 实现高可用负载均衡代理服务器
本文基于Go语言和Gin框架,实现了一个企业级负载均衡代理服务器,支持动态路由、健康检查、会话保持等功能。具备高可用性与高性能,单节点支持100k+ QPS,延迟达亚毫秒级,并提供完整的压力测试方案与优化建议。
240 7
|
9月前
|
人工智能 安全 Shell
Jupyter MCP服务器部署实战:AI模型与Python环境无缝集成教程
Jupyter MCP服务器基于模型上下文协议(MCP),实现大型语言模型与Jupyter环境的无缝集成。它通过标准化接口,让AI模型安全访问和操作Jupyter核心组件,如内核、文件系统和终端。本文深入解析其技术架构、功能特性及部署方法。MCP服务器解决了传统AI模型缺乏实时上下文感知的问题,支持代码执行、变量状态获取、文件管理等功能,提升编程效率。同时,严格的权限控制确保了安全性。作为智能化交互工具,Jupyter MCP为动态计算环境与AI模型之间搭建了高效桥梁。
652 2
Jupyter MCP服务器部署实战:AI模型与Python环境无缝集成教程
|
7月前
|
JSON 前端开发 Go
Go语言实战:创建一个简单的 HTTP 服务器
本篇是《Go语言101实战》系列之一,讲解如何使用Go构建基础HTTP服务器。涵盖Go语言并发优势、HTTP服务搭建、路由处理、日志记录及测试方法,助你掌握高性能Web服务开发核心技能。
|
7月前
|
安全 Linux 网络安全
Python极速搭建局域网文件共享服务器:一行命令实现HTTPS安全传输
本文介绍如何利用Python的http.server模块,通过一行命令快速搭建支持HTTPS的安全文件下载服务器,无需第三方工具,3分钟部署,保障局域网文件共享的隐私与安全。
1797 0
|
7月前
|
Go
如何在Go语言的HTTP请求中设置使用代理服务器
当使用特定的代理时,在某些情况下可能需要认证信息,认证信息可以在代理URL中提供,格式通常是:
537 0