SSE服务端推送技术

百度上有很多关于 SSE 的概念描述,详细了解可以自行查阅。

简单总结 SSE是基于 HTTP 协议的服务端推送技术,其中并不是传统意义上的 HTTP 请求 / 响应模型,SSE 可保持一次请求长久连接,但也不是 WebSocket 双工通信模型;SSE 只是支持服务端主动推送到客户端,可以理解成 单项长连接;

应用场景:GPT 问答后会逐步给出回复,下面会通过 node + react 简单模拟一下,先看效果;

SSE特点总结

  • 基于 HTTP 协议
  • 单工长连接
  • 内置断线重连机制
  • 连接数量 HTTP1.1 / 6个 HTTP2 / 可协商(默认100)

代码实践

node端基于KOA2

const router = require('koa-router')()
const { PassThrough } = require("stream");

router.get('/', async (ctx, next) => {  
  /**配置 HTTP 相关请求方式 */
  ctx.request.socket.setTimeout(0);  
  ctx.req.socket.setNoDelay(true);  
  ctx.req.socket.setKeepAlive(true); 
  /**设置 SSE 请求头 */
  ctx.set({  
    "Content-Type": "text/event-stream",  
    "Cache-Control": "no-cache",  
    "Connection": "keep-alive",  
  });  

  const stream = new PassThrough();  

  ctx.status = 200;  
  ctx.body = stream;  

  const content = "简单总结 SSE是基于 HTTP 协议的服务端推送技术,其中并不是传统意义上的 HTTP 请求 / 响应模型,SSE 可保持一次请求长久连接,但也不是 WebSockets 双工通信模型;SSE 只是支持服务端主动推送到客户端,可以理解成 单项长连接;";  

  // 将内容分割成多个事件消息  
  const messages = content.split(''); // 每个字符作为一个消息  

  const sendMessage = () => {  
    if (messages.length > 0) {  
      const message = messages.shift(); // 获取并移除第一个消息  
      stream.write(`data: ${message}\n\n`); // 发送消息,包括换行符  
      setTimeout(sendMessage, 100); // 延迟后发送下一个消息  
    } else {  
      stream.end(); // 没有更多消息时结束流  
    }  
  };  

  sendMessage(); // 开始发送消息  

  stream.on("close", () => {  
    console.log("已关闭");  
  });  
});

在上面代码中

ctx.request.socket.setTimeout(0); 设置请求的超时时间 ,0 表示不会超时

ctx.req.socket.setNoDelay(true); 禁用 Nagle 算法,TCP 默认会合并小的数据包,以减少空间中数据包的数量,但SSE的特点就是只要有数据会要快速返回,因此禁用此算法;

ctx.req.socket.setKeepAlive(true); 启用 TCP 的 keep-alive 机制。当 TCP 连接的一方检测到长时间没有活动时,可以发送一个 keep-alive 探测包给对方,以确认连接是否仍然有效;

客户端基于react

import React, { useState } from "react"
import styled, { keyframes } from "styled-components"

const blinkAnimation = keyframes`
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
`;
const CursorContent = styled.span`
  display: inline-block;
  line-height: 20px;
  width: 2px;
  height: 20px;
  background: #000;
  animation: ${blinkAnimation} 0.5s linear infinite;
`
const TextContainer = styled.div`

`

const Home:React.FC<any> = ()=>{
  const handleClick = ()=>{
    const eventSource = new EventSource('/api/') /*此处需要配置react反向代理*/

    // 监听消息事件
    eventSource.onmessage  = (event:any) => {
      // const result = JSON.parse(event)
      console.log(event);
      setContent((state)=>{
        return state+event.data
      })
    }

    eventSource.onopen = () => {
      console.log("SSE 连接成功,状态${eventSource.readyState}<br />")
    }

    eventSource.onerror = () => {
      console.log("SSE 连接错误,状态${eventSource.readyState}<br />")
      eventSource.close();
    }
  }
  const [content,setContent] = useState("")

  return (
    <div>
      <button onClick={()=>handleClick()}>什么是SSE</button>
      <TextContainer>
        {content}
        <CursorContent></CursorContent>
      </TextContainer>
    </div>
  )
}

export default Home
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇