后端定时过期方案选型

最近有个需求:让智能机器人在用户 1 hour 内无活跃消息后,自动关闭当前用户会话,避免无效的上下文对用户的下次提问造成干扰。这里只涉及到后端强制过期清空上下文,前端是否需要有变化/通知基于业务场景去设计就好。我主要是想到了如下三种方案并分析了一下它们的优劣。

定时任务扫表更新状态

分析

创建一个定时任务,每个小时跑一次,每次游标分批捞出会话表中 50 条活跃的会话,check一下该会话关联的 最新消息是否在 1 hour 内,没有的话就把会话状态设置为失效。

优点

  • 每小时执行,天然具有重试逻辑,并且每次执行会过滤掉已经失效的会话
  • 异步执行,在原代码中不存在耦合逻辑,改造量小

缺点

  • 会加重数据库读负担,但是在主从分离的场景下,优先读从库,并且考虑到当前场景的新增会话体量较小,系统负载可接受
  • 需要控制分布式场景下单实例执行,考虑当前公司有比较成熟的分布式任务框架,市面上也有类似 Quartz 这种分布式任务框架,可以直接使用
  • 会话过期逻辑相对复杂,需要保证编码质量,考虑分批游标的方式减轻内存/CPU压力

Redis key 过期事件监听

分析

新创建会话时设置一个 key = conversationId 的 redis key,expiration time = 1hour,每次有会话关联的消息更新/新增时需要重置其关联的会话 redis key 的 expiration time = 1 hour

优点

  • 没有很重地会话失效逻辑,收到 key 过期事件就将对应的会话失效
  • 不会加重数据库负担

缺点

  • 代码中需要在 insert 会话、create/update 消息处耦合 redis 逻辑,改造量大
  • 频繁更新 redis 性能较差
  • Redis 过期事件是在服务器删除 key 时发出的,不是 key 过期就会直接发出;Redis 惰性删除 + 过期删除的机制会导致时效性差,删除 key 的时机不一定是 key 过期的时机
  • 过期事件监听丢失无法重试

RocketMQ 延迟消息推送

分析

新创建会话时延迟 1 hour 发送一条消息,消费者 1hour 后收到消息会校验该会话的状态,每次有会话关联的消息更新/新增时需要再发送一条其关联的会话的相同延迟消息

优点

  • 消息有重试机制,稳定性较高
  • 不会加重数据库负担

缺点

  • 代码中需要在 insert 会话、create/update 消息处耦合 MQ 逻辑,改造量大
  • 每次 insert 会话、create/update 消息都需要发送 MQ,消息冗余
  • 接收到消息的会话过期逻辑比较复杂,需要校验状态,也需要做消息幂等处理
  • 会有许多和最终关闭会话无关的消息发送出来

最终选型

最终选型为 定时任务扫表更新状态
因为其天然具有重试逻辑,并且不会在原有代码中耦合逻辑,改造成本比较小,此外还没有过多无效消息被发出来。

<think>好的,我现在需要回答用户关于如何从后端持续向前端传递进度更新的问题。用户希望了解技术选型和具体实现方案。首先,我得回忆一下常见的实时通信技术,比如WebSocket、Server-Sent Events(SSE)、长轮询等。然后,考虑每种技术的优缺点和适用场景。 接下来,用户提到的是进度更新,这可能是在处理长时间任务时,比如文件上传、数据处理等。这种情况下,后端需要实时推送进度信息到前端,而不是前端频繁轮询。所以,WebSocket和SSE可能更合适,因为它们支持服务端主动推送。 然后,我需要考虑具体实现方案。比如,使用WebSocket的话,可能需要用到Socket.io或者Spring WebFlux。如果是SSE,前端可以用EventSource API,后端可能需要保持连接打开,并定期发送数据。还有长轮询,虽然效率不如前两者,但在某些情况下可能更简单。 另外,用户可能还关心技术选型的因素,比如兼容性、复杂度、是否需要双向通信。例如,SSE是单向的,适合服务端向客户端推送,而WebSocket是双向的。如果只需要单向,SSE可能更简单,但兼容性方面需要注意,比如IE不支持SSE。 然后,我需要结合引用内容。引用[3]提到了异步函数和事件队列,这可能和事件驱动的通信机制有关,比如使用事件循环处理推送。引用[4]提到了非结构化数据存储,不过可能和当前问题关联不大,但或许在进度更新中需要存储进度信息,比如使用数据库记录状态,不过这可能属于额外扩展部分。 现在,具体实现步骤可能包括:后端建立任务并生成唯一ID,前端通过该ID订阅进度,后端使用选定的技术(如SSE或WebSocket)推送更新。还需要考虑如何在后端处理任务状态,比如使用缓存或数据库存储进度,并定时或按事件触发更新。 还要注意安全性,比如验证前端请求,确保只有授权用户能获取进度。另外,处理连接中断后的重连机制,以及如何清理过期的进度数据。 最后,生成相关问题,比如比较不同技术的优劣,如何处理断线重连,或者如何结合具体框架(如Spring Boot或Node.js)实现。</think>### 实现后端持续向前端发送进度更新的方法 #### 技术选型 1. **WebSocket** - 双向实时通信协议,适用于需要高频、低延迟的场景(如实时聊天)。 - **实现库**:Socket.io(Node.js)、Spring WebSocket(Java)、Django Channels(Python)。 - **优点**:全双工通信,支持服务端主动推送。 - **缺点**:需要额外维护连接状态,复杂度较高[^3]。 2. **Server-Sent Events (SSE)** - 基于 HTTP 的单向通信协议,适合服务端向客户端推送文本数据。 - **实现方式**:前端通过 `EventSource` API 监听,后端通过 HTTP 流持续发送数据。 - **优点**:简单轻量,兼容性较好(除 IE),天然支持断线重连[^4]。 - **缺点**:仅支持文本格式,不支持双向通信。 3. **长轮询(Long Polling)** - 前端发送请求后,后端保持连接直到有数据更新或超时。 - **实现方式**:通过 Ajax 或 Fetch API 递归调用。 - **优点**:兼容所有浏览器,实现简单。 - **缺点**:高频请求可能增加服务器负载。 #### 具体实现方案(以 SSE 为例) 1. **后端逻辑** - 创建任务时生成唯一任务 ID,并启动异步处理(如线程池或协程)。 - 使用缓存(如 Redis)或数据库存储任务进度。 ```python # Python Flask 示例 from flask import Response, Flask import time app = Flask(__name__) @app.route('/progress/<task_id>') def progress_stream(task_id): def generate(): progress = 0 while progress < 100: progress = get_progress_from_cache(task_id) # 从缓存获取进度 yield f"data: {progress}\n\n" time.sleep(1) return Response(generate(), mimetype='text/event-stream') ``` 2. **前端逻辑** - 通过 `EventSource` 监听进度,并更新 UI。 ```javascript const eventSource = new EventSource('/progress/123'); eventSource.onmessage = (e) => { const progress = parseInt(e.data); document.getElementById('progress-bar').style.width = `${progress}%`; if (progress === 100) eventSource.close(); }; ``` 3. **扩展优化** - **任务状态存储**:使用 Redis 记录进度,避免服务重启后数据丢失[^4]。 - **异常处理**:添加心跳机制检测连接状态,超时后自动重连[^3]。 - **安全性**:通过 Token 或 Session 验证任务 ID 归属,防止未授权访问[^1]。 #### 注意事项 - **协议选择**:若仅需单向推送,优先选择 SSE;若需双向交互(如实时控制),使用 WebSocket。 - **性能瓶颈**:高并发场景下,SSE 和 WebSocket 需结合异步框架(如 Node.js 或 Tornado)提升吞吐量[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

互联网民工蒋大钊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值