基于 Laravel Horizon 管理队列处理器进程和伸缩策略
在上篇教程中,我们已经介绍了如何基于负载监控和伸缩队列处理器,伸缩可以细分为水平伸缩和垂直伸缩,水平伸缩指的是新增/移除处理器进程/服务器,垂直伸缩指的是新增/移除服务器上的资源。
随着应用的增长,设计高效的伸缩策略变得越来越复杂,要伸缩每小时处理成千上万任务的多个队列,需要使用多种工具对系统进行持续监控。
为了简化这个工作,Laravel 提供了 Horizon 扩展包,它有一个仪表盘用于显示实时指标,以及一个内置的自动伸缩器,支持不同的伸缩策略。
注意:Horizon 目前仅支持 Redis 队列驱动。
启动和监控 Horizon 进程
使用 Horizon 后,不需要开启多个处理器进程,只需要启动 Horizon 即可:
php artisan horizon
你仍然可以使用 Supervisor 来管理 Horizon 进程,创建一个 /etc/supervisor/conf.d/horizon.conf
配置文件:
并基于它来启动和管理 Horizon 进程即可。
开启一个 Horizon 进程即可,无需通过
numprocs
配置多个进程,它会根据系统负载管理队列处理器进程的数量。
Horizon 的基本配置
我们可以通过配置文件 config/horizon.php
来配置 Horizon:
该配置的含义是启动 10 个 queue:work
进程,来消费 deployments
和 notifications
队列的任务:
通过 Supervisor 确保 Horizon 进程一直运行,Horizon 又会确保 10 个队列处理器进程一直运行,如果其中一个进程挂了,Horizon 会自动启动它。
你可以通过修改上述配置值来配置队列处理器进程:
还可以配置多个 Horizon Supervisor:
这样的话,Horizon 会启动 7 个处理器进程消费 deployments
队列任务,每个进程超时时间 300s,3 个处理器进程消费 notifications
队列任务,每个进程超时时间 60s。
简单伸缩策略
Horizon 目前提供了两种伸缩策略支持,通过 balance
配置项配置,一种是 simple
策略:
在这种策略下,Horizon 会启动 5 个处理器进程消费 deployments
队列,5 个处理器进程消费 notifications
队列。使用 simple
策略,Horizon 会为所有队列平均分配处理器进程。
如果不能均分,会分配给优先级更高的队列更多处理器进程:
deployments
队列将分配 3 个处理器进程,notifications
队列 2 个。
自动伸缩策略
另外一种是 auto
伸缩策略:
这个功能最强大,会根据队列的繁忙程度自动分配处理器进程,与此同时,需要配置 min_processes
和 max_processes
。
在上述配置中,Horizon 至少为每个队列分配 1 个处理器进程,总共是 10 个。如果 deployments
队列非常繁忙,而 notifications
是空的,则分配 9 个处理器给 deployments
,1 个给 notifications
。
Horizon 会根据每个队列的预期清空时间来决定要分配的处理器数量,因此,如果 deployments
中的任务需要花费更多时间处理,而 notifications
瞬间就可以完成。即使 notifications
队列有比 deployments
更多的任务,Horizon 仍然会为 deployments
队列分配更多处理器进程。
伸缩频率
默认情况下,Horizon 每 3s 添加或移除一个处理器进程。因此,要将进程池中的进程数量从 5 提升到 8,需要耗费 9s。
你可以通过调整 balanceMaxShift
和 balanceCooldown
配置项来修改这个伸缩频率:
这样一来,Horizon 每秒会新增或移除 3 个进程。
Horizon v5.0 之后才支持该功能。
避免内存泄露
和普通的队列处理器进程一样,Horizon 也是个常驻内存的 PHP 进程,需要确保在 Horizon 及其子进程运行完成后释放其占用的内存资源。
我们可以像普通处理器进程那样,每隔一段时间终止 Horizon 进程(会自动重启):
运行 horizon:terminate
会发送信号给所有关联的队列处理器进程,在运行完当前任务后退出。所有队列处理器进程退出后,Horizon 进程才会退出。这样一来,就可以避免内存泄露了。
No Comments