实时信息推送

13次阅读
没有评论

传统实现方式:前端轮询获取、websocket

前端轮询

在前端定时轮询获取后台服务数据,然后进行页面渲染

  • 优点:实现方式简单
  • 缺点:存在数据延迟; 频繁创建 / 销毁网络连接会增加性能开销和网络带宽

websocket

  • 优点:功能强大、完全实用
  • 缺点:笨重

SSE(Server-Sent Events)

SSE 是基于 HTTP 长链接的服务端主动推送技术

  • 技术定义: 基于 HTTP 长链接实现的服务端主动向客户端推送消息的技术
  • 技术原理: 依托 HTTP 1.1 的分块传输编码机制 (Transfer-Encodingchunked),允许服务器分批次向客户端发送数据
  • 核心优势: 复用长链接,避免客户端频繁创建 / 销毁连接,服务端数据变化时直接推送
// 后端代码
val clientsMap =mutableMap0f<String,SseEmitter>()
@GetMapping("/subscribe-data",produces = [MediaType.TEXT_EVENT_STREAM_VALUE])
fun subscribe(): SseEmitter {val emitter=SseEmitter(timeout:5*60*1000L)
   val clientId = RandomUtil.uuid()
   clientsMap[clientId]=emitter
   emitter.onCompletion {Logger.error("sse 结束")
      clientsMap.remove(clientId)
   }
   emitter.onTimeout {logger.error("sse 超时")
      clientsMap.remove(clientId)
   }
   emitter.onError { it: Throwable!
      logger.error("sse 异常")
      clientsMap.remove(clientId)
   }
   return emitter
}

// 前端代码
// 创建 EventSource 对象,建立 SSE 连接
const eventSource = new EventSource(`${baseUrl}/api/subscribe-data`);
// 连接成功
eventSource.onopen=()=>{console.log("连接成功。.success");
}
// 监听特定事件 - 游戏数据
eventSource.addEventListener('data_update',(event)=>{console.log('收到消息 data update:',event.data);
   // 更新页面
});

后端数据发生变化

// 在数据变化的地方调用发送方法
fun sendOne(clientId: String, sse: SseEmitter, eventName: String, data: Map<String,Any?>): Boolean {
   try {sse.send(SseEmitter.event().name(eventName).data(data))
      return true
   }catch(e:I0xception){logger.warn("连接已关闭,event_name={},data=}",eventName,data,e)
      clientsMap.remove(clientId)
   }catch(e:Exception){logger.error("推送消息失败,event_name={},data=}",eventName, data,e)
   }
   return false
}
// 推送给所有人
fun sendAll(eventName:String,data:Map<String,Any?>){for(item in this.clientsMap.entries){sendOne(item.key,item.value,eventName,data)
   }
}

正文完
 0
评论(没有评论)
验证码