服务器往浏览器推消息(SSE)应用

1,SSE 和 WebSocket 对比

SSE(服务器发送事件)
SSE是一种基于HTTP的单向通信机制,用于服务器向客户端推送数据。它的工作原理如下:

建立连接:客户端通过发送HTTP请求与服务器建立连接。在请求中,客户端指定了接收事件的终点(Endpoint)。
保持连接:服务器接收到连接请求后,保持连接打开,并定期发送事件数据给客户端。
事件流:服务器使用 “Content-Type: text/event-stream” 头部标识SSE连接,并使用特定格式的数据(事件流)发送给客户端。
客户端处理事件:客户端通过JavaScript的 EventSource 接口监听SSE连接,一旦接收到事件,就可以处理数据并更新页面。
SSE的特点和适用场景:

单向通信:SSE是从服务器到客户端的单向通信模型,只能由服务器推送数据给客户端。
实时更新:SSE适用于需要实时更新数据的应用场景,如股票行情、新闻推送等。
简单易用:使用SSE相对简单,无需额外的库或框架支持,可以直接使用浏览器的原生API进行开发。

WebSocket
WebSocket是一种全双工的通信协议,它通过在客户端和服务器之间建立持久连接,实现双向通信。WebSocket的工作原理如下:

握手阶段:客户端向服务器发送WebSocket握手请求,服务器返回握手响应。在这个阶段,客户端和服务器协商选择协议和版本。
建立连接:握手成功后,客户端和服务器之间建立持久连接,可以进行双向数据传输。
双向通信:一旦连接建立,客户端和服务器都可以主动发送消息给对方。数据可以以文本或二进制格式进行传输。
断开连接:当任一方决定关闭连接时,可以发送关闭帧来终止连接。
WebSocket的特点和适用场景:

双向通信:WebSocket支持双向通信,客户端和服务器可以互相发送消息。
实时互动:WebSocket适用于实时互动的应用场景,如聊天应用、协作编辑等。
复杂性和灵活性:相对于SSE,WebSocket更为灵活,可以处理更复杂的通信需求。它允许自定义消息格式、心跳检测、连接状态管理等。
 

2,具体代码实现

2.1 后端

    @GetMapping(value = "/stock",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter streamStockPrice() {
        SseEmitter emitter = new SseEmitter();
        // 模拟生成实时股票价格并推送给客户端
        Random random = new Random();
        new Thread(() -> {
            try {
                while (true) {
                    // 生成随机的股票价格
                    double price = 100 + random.nextDouble() * 10;
                    // 构造股票价格的消息
                    String message = String.format("%.2f", price);
                    // 发送消息给客户端
                    emitter.send(SseEmitter.event().data(message));
                    // 休眠1秒钟
                    Thread.sleep(1000);
                }
            } catch (Exception e) {
                emitter.completeWithError(e);
            }
        }).start();
        return emitter;
    }

2.2 前端

    $("#btn12").click(function (){
        const eventSource = new EventSource('http://localhost:8080/test/test/stock');
        eventSource.onmessage = function (event) {
            showMsg(event.data)
        }
    })

 2.3 最终效果

SSE 演示

3,传统部署方式

nginx部署

4,k8s部署方式

待研究

5,问题

问题 1:采用 nginx 部署时,页面刷新很慢,实际上服务器已经发了很多数据过来。

此问题待研究解决。

解决方法:

nginx 做相关配置

配置如下

         location /codeTest {
            proxy_pass http://127.0.0.1:18080/test;

            # proxy_http_version设置代理使用的HTTP协议版本为1.1。
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            # SSE 连接时的超时时间
            proxy_read_timeout 86400s;

            # 取消缓冲
            proxy_buffering off;
            # 关闭代理缓存
            proxy_cache off;
            # 禁用分块传输编码
            #chunked_transfer_encoding off
        }

/codeTest是你希望使用的路径,你可以根据需要进行修改。 proxy_pass指定了后端服务器的地址,你需要将其替换为实际的后端服务器地址。
proxy_http_version设置代理使用的HTTP协议版本为1.1。
proxy_set_header设置一些必要的头部信息,如连接方式、真实客户端IP等。
proxy_read_timeout 指令来设置 SSE 连接的超时时间。默认情况下,Nginx 会在 60 秒后关闭空闲的连接,这对于 SSE 来说是不合适的,所以我们将超时时间设置为一天(86400 秒)。这样,客户端和服务器之间的连接可以持续保持打开状态。
proxy_buffering off 指令来确保数据可以实时传输,而不需要等待缓冲区满。在SSE请求中禁用缓冲,以便正确处理SSE流式数据。
proxy_cache 对于 SSE(Server-Sent Events)连接,通常不建议启用 Nginx 的代理缓存(proxy_cache)。因为 SSE 是一种长连接技术,它通过保持持久连接来实时推送数据给客户端,而代理缓存会将响应数据缓存起来并在后续请求中返回缓存的响应,这与 SSE 的工作方式相违背。如果启用代理缓存,Nginx 可能会缓存 SSE 的数据,并在后续的连接中返回相同的缓存数据,这样会导致客户端收到重复的消息,破坏了 SSE 的实时性和准确性。
chunked_transfer_encoding 参数可以根据你的需求决定是否关闭。在 SSE 中,通常不需要禁用分块传输编码,因为它允许将数据以数据块的形式逐步传输,与 SSE 的流式数据特性相符合。
proxy_pass 指令正确反向代理到你的 SSE 应用程序的地址和端口,以使连接正确工作。

问题 2:连接一段时候,自动断开

解决方法参考如下文章

Springboot调整接口响应返回时长(解决响应超时问题)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
05-25
PHP SSE (Server-Sent Events) 是一种在 Web 浏览器服务器之间实现实时通信的技术。它基于 HTTP 协议,可以在客户端浏览器服务器之间建立持久化的连接,从而允许服务器实时向客户端送数据。 使用 SSE 技术可以轻松地创建实时更新的 Web 应用程序,例如:实时股票报价、在线聊天、实时送新闻等。 在 PHP 中实现 SSE 技术,可以使用 EventSource 对象来处理从服务器送的事件。在服务器端,可以使用 header() 函数设置响应头,以便浏览器了解服务器发送的数据类型是 text/event-stream,并且设置连接保持时间。 以下是一个简单的 PHP SSE 示例: ``` <?php header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); while (true) { // 从数据库或其他数据源获取最新的数据 $data = get_latest_data(); // 发送事件 echo "data: " . json_encode($data) . "\n\n"; // 刷新输出缓冲区 ob_flush(); flush(); // 等待一段时间再发送下一个事件 sleep(1); } ?> ``` 在客户端,可以使用 JavaScript 来监听服务器发送的事件,例如: ``` var source = new EventSource('sse.php'); source.onmessage = function(event) { var data = JSON.parse(event.data); // 处理从服务器接收到的数据 }; ``` 需要注意的是,SSE 技术虽然可以实现实时通信,但它并不是 WebSocket 技术的替代品。WebSocket 技术还提供了双向通信的能力,并且在性能和可扩展性方面也更优秀。因此,在选择实现实时通信功能时,应该根据具体的需求和应用场景选择合适的技术。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值