SSE(Server-Sent Events)是一种基于 HTTP 协议的服务器推送技术,允许服务器主动向客户端(如浏览器)发送实时数据更新,而无需客户端重复发起请求。该技术通过建立持久化的单向通信通道,实现了高效的实时信息传输。
在坐席业务中,电话是联系客户的主要手段。系统支持点呼和批量外呼。批量外呼可同时拨打多个电话,接通后转接坐席。但当两种呼叫方式同时使用,且坐席忙于点呼时,批量外呼接通的电话需排队等待,可能导致客户放弃等待,从而增加呼损率。
在创建连接时,本地缓存连接对象,并将本地IP缓存到redis,key为坐席id
NIO 支持
系统容量评估
SSE只有在创建、发送消息时占用tomcat工作线程,可根据情况,适当调整 tomcat 工作线程,满足 SSE 新增的消耗
public class SseController {
//本地缓存,用于存储SseEmitter
private final static ConcurrentHashMap<Long, SseEmitter> EMITTERS = new ConcurrentHashMap<>();
public SseEmitter createSSE( Long userId) {
SseEmitter emitter = new SseEmitter(60_000L); // 60秒超时
// 连接关闭处理,移除SseEmitter
emitter.onCompletion(() -> EMITTERS.remove(userId));
emitter.onTimeout(() -> EMITTERS.remove(userId));
//本地缓存中存储SseEmitter
EMITTERS.put(userId, emitter);
// TODO redis中维护userId与当前实例IP映射
return emitter;
}
public ResponseEntity<String> sendMessage( Message message) {
// 本地缓存获取SseEmitter
Long userId = message.getUserId();
SseEmitter sseEmitter = EMITTERS.get(userId);
try {
// 发送消息
sseEmitter.send(SseEmitter.event().name("message").data(message));
} catch (IOException e) {
// 异常时销毁对象
sseEmitter.completeWithError(e);
// 移除本地缓存
EMITTERS.remove(userId);
}
return ResponseEntity.ok("ok");
}
}
<script>
// 自动创建SSE连接
window.onload = function() {
// 创建EventSource实例(替换为你的SSE端点)
const sse = new EventSource('https://domain/sse/stream?token=***');
// 连接成功回调
sse.onopen = () => {
//do business
};
// 接收消息处理, event.type=message
sse.onmessage = (event) => {
// do business
};
// 自定义事件处理(可选),例如以Close事件告知前端主动关闭连接
sse.addEventListener('Close', (e) => {
// do business
sse.close();
});
// 错误处理
// 后端通过complete事件主动关闭连接时,如果未通过代码主动关闭连接浏览器会自动重连
sse.onerror = () => {
readyState:
//连接已打开并准备进行通信,异常未断开连接。如后端主动推送error事件
if(sse.readyState === EventSource.OPEN){
sse.close();
}
// 连接尚未打开或异常关闭,如后端的complete事件,后端服务重启,nginx reload,网络异常等...
else if(sse.readyState === EventSource.CONNECTING) {
// do nothing,浏览器会自动重连,默认是3s重连一次,可修改
}
};
};
</script>
# 强制关闭Keep-Alive连接
proxy_set_header Connection "";
# 实时传输但增加后端压力
proxy_buffering off;
# 读取超时时间, 建立连接后1200s服务端未推送消息断开连接
proxy_read_timeout 1200;
# 发送超时时间
proxy_send_timeout 1200;
# 关闭缓存
proxy_cache off;
# 禁用分块传输
chunked_transfer_encoding off;
# 强制客户端不缓存
add_header Cache-Control no-cache;
# 正确使用HTTP/1.1协议
proxy_http_version 1.1;
SSE是一种基于HTTP协议的服务器推送技术,SpringMVC为之提供了完善的实现方案。浏览器原生支持SSE连接中断后自动重连,从而确保连接的可靠性。这一技术尤为适合应用于业务监控大盘、站内消息传递以及AI问答等众多业务场景。
Tono,信也科技后端研发专家
往期精彩内容指路
↙↙↙更多干货分享欢迎订阅【拍码场】