Mojolicious+Hypnotoad:Worker超时关闭前如何通知客户端?
解决方案
针对Mojolicious + Hypnotoad环境下,Worker超时关闭前通知客户端的需求,可通过以下步骤实现:
核心思路
- 跟踪当前活跃的客户端连接(WebSocket/HTTP长连接)
- 利用
before_server_start钩子监听Worker的finish事件,在Worker退出前遍历活跃连接发送通知
代码实现
sub startup { my $self = shift; # 每个Worker独立维护活跃连接集合(多进程模型下无需跨进程同步) my $active_connections = {}; # 注册服务器启动前钩子,绑定Worker退出事件 $self->hook(before_server_start => sub { my ($server, $app) = @_; # Worker即将退出时触发finish事件 $server->on(finish => sub { my $server = shift; # 遍历所有活跃连接发送关闭通知 foreach my $tx (values %$active_connections) { next unless $tx->is_websocket || $tx->keep_alive; # WebSocket连接处理:发送通知后主动关闭 if ($tx->is_websocket) { $tx->send({ text => 'Worker因超时即将关闭,请重新连接。' }); $tx->finish; } # HTTP长连接(如SSE)处理:返回503并关闭连接 elsif (!$tx->res->code) { $tx->res->code(503); $tx->res->body('Worker因超时即将关闭,请稍后重试。'); $tx->res->headers->connection('close'); $tx->send; } } # 清空连接集合,避免内存泄漏 %$active_connections = (); }); }); # WebSocket示例路由 $self->routes->websocket('/api/ws')->to(cb => sub { my $c = shift; my $tx_id = $c->tx->id; # 将当前连接加入活跃集合 $active_connections->{$tx_id} = $c->tx; # 连接关闭时从集合移除 $c->tx->on(finish => sub { delete $active_connections->{$tx_id}; }); # 此处添加WebSocket业务逻辑... }); # SSE长连接示例路由 $self->routes->get('/api/sse')->to(cb => sub { my $c = shift; my $tx_id = $c->tx->id; # 设置SSE响应头 $c->res->headers->content_type('text/event-stream'); $c->res->headers->cache_control('no-cache'); $c->res->headers->connection('keep-alive'); # 将当前连接加入活跃集合 $active_connections->{$tx_id} = $c->tx; # 连接关闭时从集合移除 $c->tx->on(finish => sub { delete $active_connections->{$tx_id}; }); # 发送初始连接确认 $c->write("data: 连接已建立\n\n"); # 此处添加SSE业务逻辑... }); }
关键说明
- 多进程适配:Hypnotoad采用多进程模型,每个Worker独立维护
$active_connections,无需考虑跨进程数据同步问题。 - 事件时机:
finish事件在Worker进入优雅关闭阶段触发,此时仍可操作事件循环发送响应,避免了END块、析构函数或信号处理的时机问题。 - 连接清理:必须在连接关闭时从集合中移除对应
tx对象,防止内存泄漏。
为什么之前的方案无效?
- 控制器析构函数:仅在对象销毁时触发,Worker关闭时控制器可能已被回收,无法关联到活跃连接。
- END块:进程退出时执行,但此时Mojolicious事件循环已停止,无法发送响应。
- 信号处理:Hypnotoad会捕获STOP/QUIT信号并处理优雅关闭,自定义信号处理会干扰默认逻辑,且信号处理函数中无法安全操作事件循环。
内容的提问来源于stack exchange,提问作者Fausto B.
相关产品推荐
相关产品推荐

