关于celery的worker运行过程中卡住的问题

本文介绍了Celery中解决worker挂起的两种方法:一是使用CELERYD_FORCE配置避免死锁;二是利用time_limit参数设定任务执行超时时间,通过生成新进程并杀死挂起进程的方式来处理。此外还提到了如何配置确保任务超时未被确认时能够重新分配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Celery 

Solution for hanging workers 

两种解决方式:

1. 如果确认是因为当前worker的并发是prefork(多进程),并且可能是由于死锁原因造成!

    那么可以使用 CELERYD_FORCE = True ,这样可以有效防止死锁。即使不是这个原因造成的,也尽量加上。

    注意:这种处理方式在4.0之后的版本不支持了,使用时需检查版本,也可采用下面的方式

2. 第二种解决方式适用于大多数进程hanging的情况,可以使用time_limit参数,设定任务的执行超时时间,当超过这个时间的话,就先生成新的进程,并通过信号将hanging的进程杀死。

    另外,如果配置中使用了act_late的参数数,需要配合broker_transport_options = {'visiblity_timeout': 10 *60 }使用,这样,在task经过超时时间之后如果还没被ack, 就会被发送到其他worker去执行。如果没设置ack_late,代表对执行结果并不关心,这个参数也就没必要设置了

很有用的一片博客链接:http://blog.youkuaiyun.com/woshiaotian/article/details/36422781

在这段代码中,当群组成员人数较多时,确实会因为多次遍历和发送消息导致性能下降,并影响用户体验。以下是几种可以优化此场景的方式: --- ### **1. 批量处理数据** 避免逐条操作用户数据,改为批量查询、处理以及发送通知。 例如,在 `foreach` 中逐一调用 `$this->setExtMsg()` 可能效率较低。可以通过一次性构造所有需要发送的消息内容并集中提交给消息队列或异步任务系统进行分发。 #### 改进思路: 将所有的 openid 和对应的数据先收集起来,最后统一传递到一个批次化的方法内完成下发流程。 修改后的伪代码示例: ```php $allMessages = []; foreach ($post_tt as $post_item) { $post_openid = $post_item['openid']; $messageData = [ 'openid' => $post_openid, 'title' => '群聊消息', 'content' => $post_info['sd_name'] . ' 的群聊消息', 'name' => $data['Content'], 'url' => $_W['siteroot'] . '/app/' . $this->createMobileUrl('pvmsg', ['cid' => $data['cid']]) ]; $allMessages[] = $messageData; // 汇总待发送信息至数组中暂存 } $this->batchSendMsg($allMessages); // 调用新的批量化接口推送消息 ``` 其中新函数定义类似这样: ```php private function batchSendMsg(array $messages): void { foreach ($messages as $msg) { $this->send_msg( $msg['openid'], $GLOBALS['_GPC']['setting']['tozhi_tx'], ['first'=>$msg['title'],'keyword1'=>$msg['content']], $msg['url'] ); } } ``` 通过减少单次循环内的复杂度提升整体执行速度同时改善资源消耗状况。 --- ### **2. 异步任务机制** 利用后台作业服务(如 RabbitMQ 或者 Redis + Celery),把每次对用户的提醒请求放入队列里等待进一步处理而不是直接同步阻塞主线程直到每一步结束为止。 优点包括但不限于:降低主服务器负载压力;允许前端快速响应无需关心后续步骤是否成功与否等优势明显优于传统的直连模式。 简单做法如下所示: - 安装第三方支持库比如 [Workerman](https://www.workerman.net/) 等框架搭建独立进程池专门负责消费来自数据库记录的任务指令集; - 修改原程序逻辑只管往存储介质插入必要的关键字段而不再参与实际的通知环节交给专业工具去搞定就好啦! 像这样改动原有部分即可满足需求了哦~ ```php use Workerman\Worker; // 后台监听端口开启持续运行状态... require_once __DIR__ . '/Workerman/Autoloader.php'; $task_worker = new Worker("tcp://0.0.0.0:8765"); $task_worker->onMessage = function($connection, $data){ extract(unserialize($data)); try{ sendSingleNotification($openId,...); }catch(\Exception $e){ echo "Error:".$e;} }; if(!defined('GLOBAL_START')){ Worker::runAll(); } function notifyUserAsync(string $serializedTaskDetails):void{ socket_write(fsockopen('localhost',8765),$serializedTaskDetails); }; ``` 然后原来的业务就可以简化成仅仅投递事件过去就行了哈~再也不怕超时或者卡住了~ --- ### **3. 缓存策略引入** 对于一些高频访问但是变化不大甚至完全不变的结果可以直接存放到内存型缓存组件比如说 Memcached / Redis 当前环境之中以便复用结果加快读取频率从而节省大量 IO 时间成本开支费用支出浪费现象的发生概率大大降低了呢!!! 举个例子来讲吧假如说我们的某些基础配置项总是会被反复引用那么完全可以预先加载进来然后保存下来供其他地方随时查阅使用就好了呀嘿嘿😊 --- **总结建议结合实际情况选取合适方案实施改造工作**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值