一、引言

在现代Web应用程序中,实时数据传输和实时通信变得越来越重要。为了实现这种实时通信,多种技术应运而生,如WebSocket、长轮询和Server-Sent Events(SSE)。在本文中,我们将重点探讨Server-Sent Events,一种基于HTTP的实时通信协议。

二、技术背景

Server-Sent Events(SSE)它提供了一种从服务器实时发送不断更新发送事件到客户端的技术。SSE主要解决了客户端与服务器之间的单向实时通信需求(例如ChatGpt回答的流式输出),相较于WebSocket(双向实时),它更加轻量级且易于实现。 SSE是基于HTTP协议实现的所以更适用于服务器持续的向客户端发送文本数据的场景。

三、底层原理

SSE基于HTTP协议,采用了HTTP长连接的方式。客户端正常http请求服务器,通过JavaScript的EventSource对象监听服务器发送的事件,并在收到更新时触发对应的事件处理器。服务器在响应头中设置Content-Type: text/event-stream,表示该响应为事件流。

四、请求流程

  • 客户端通过创建EventSource对象与服务器建立长连接。
  • 客户端通过thhp正常请求服务器。
  • 服务器在响应头中设置Content-Type: text/event-stream
  • 服务器按照特定格式不断发送事件数据。
  • 客户端监听服务器发送的事件,并在收到更新时触发对应的事件处理器。

五、实际应用

SSE适用于以下场景:

  • 实时通知和警报:如实时股票行情、新闻推送等。
  • 聊天应用:虽然WebSocket更适用于双向通信,但在某些场景下,SSE可以用于实现简单的聊天应用。
  • 服务器监控:实时获取服务器运行状态、日志等信息。

六、类 ChatGpt聊天框实时流输出(结合springMvc)

JS代码:

//设置EventSoure监听的url,监听处理事件,此处我的代码是把新增内容追加到聊天最后  
const eventSource = new EventSource(serverUrl);
    eventSource.onmessage = function (event) {
        const response = JSON.parse(event.data).data;

        // 显示服务器的返回并追加到最后
        messageContainer.innerHTML += `<p><strong>GPT:</strong><br /> ${response}</>`;
        messageContainer.scrollTop = messageContainer.scrollHeight;
    };   


   async function submitMessage(event) {
        event.preventDefault();

        //获取用户聊天框输入
        var message = userInput.value.trim();
        if (!message) return;
       
        userInput.value = '';
        // Display user's message
        messageContainer.innerHTML += `<p><strong>You:</strong><br /> ${message}</p>`;
        messageContainer.scrollTop = messageContainer.scrollHeight;

        //发起请求
        sendMessageToBackend(message);
    }


 async function sendMessageToBackend(message) {
        // 使用你的后台地址代替
        const apiUrl = 'url';
        const requestOptions = {
            method: 'POST',
            headers: {'Content-Type': 'application/json', 'Accept': '*'},
            body: JSON.stringify({message})
        };
        try {
            await fetch(apiUrl, requestOptions);
        } catch (error) {
            console.error('Error:', error);
        }
    }

JAVA服务器代码:

//一、创建controller 使用你自己定义的url
    @RequestMapping(value = "/chat-sse")
    public ResponseBodyEmitter chatSse(@RequestBody String params) throws IOException {
        SseEmitter sseEmitter = new SseEmitter();
        String message = JSONObject.parseObject(params).getString("message");
        gptClient.getGPTMessageSse(message, sseEmitter);

        //实际sseEmitter已经返回,新线程10秒之后发送test给客户端
        new Thread("testThread") {
            @Override
            public void run() {
                try {
                    Thread.sleep(10000);
                    sseEmitter.send("test");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("间隔10秒后发送实时数据给客户端");
            }
        }.start();
        return sseEmitter;
    }

六、总结

SSE作为一种基于HTTP的实时通信协议,具有轻量

级和易于实现的优点。它通过服务器主动向客户端发送更新事件,有效降低了服务器负载和网络资源消耗。在实际应用中,SSE已经在实时通知、聊天应用和服务器监控等场景中得到广泛应用。

然而,SSE也存在一定的局限性。首先,它只支持单向通信,即服务器向客户端发送数据。对于需要双向实时通信的场景,WebSocket可能是更好的选择。其次,SSE在跨域通信时可能遇到一些限制,需要进行额外的配置。最后,由于SSE依赖于HTTP长连接,如果连接数量过多,可能会导致服务器资源不足。