下面由workerman使用教學專欄來介紹workerman實現非同步任務的方法,希望對需要的朋友有幫助!
1、問題
#遇到一個問題,php是單線程,無法實作多線程。現在我需要使用一個場景是多個連結使用一個線程,也就是在一個連接進程,再開進程來處理
#2、解決方案
workerman如何實現異步任務。 workerman可以幫我解決問題, 給予文件一個答案
問:
如何非同步處理繁重的業務,避免主業務被長時間阻塞。例如我要給1000用戶發送郵件,這個過程很慢,可能要阻塞數秒,這個過程中因為主流程被阻塞,會影響後續的請求,如何將這樣的繁重任務交給其它進程異步處理。
答案:
可以在本機或者其它伺服器甚至伺服器叢集預先建立一些任務進程處理繁重的業務,任務進程數可以開多一些,例如cpu的10倍,然後調用方利用AsyncTcpConnection將資料非同步傳送給這些任務進程非同步處理,非同步得到處理結果
任務進程服務端
use Workerman\Worker; require_once __DIR__ . '/Workerman/Autoloader.php'; // task worker,使用Text协议 $task_worker = new Worker('Text://0.0.0.0:12345'); // task进程数可以根据需要多开一些 $task_worker->count = 100; $task_worker->name = 'TaskWorker'; //只有php7才支持task->reusePort,可以让每个task进程均衡的接收任务 //$task->reusePort = true; $task_worker->onMessage = function($connection, $task_data) { // 假设发来的是json数据 $task_data = json_decode($task_data, true); // 根据task_data处理相应的任务逻辑.... 得到结果,这里省略.... $task_result = ...... // 发送结果 $connection->send(json_encode($task_result)); }; Worker::runAll();
#在workerman中呼叫
use Workerman\Worker; use \Workerman\Connection\AsyncTcpConnection; require_once __DIR__ . '/Workerman/Autoloader.php'; // websocket服务 $worker = new Worker('websocket://0.0.0.0:8080'); $worker->onMessage = function($ws_connection, $message) { // 与远程task服务建立异步连接,ip为远程task服务的ip,如果是本机就是127.0.0.1,如果是集群就是lvs的ip $task_connection = new AsyncTcpConnection('Text://127.0.0.1:12345'); // 任务及参数数据 $task_data = array( 'function' => 'send_mail', 'args' => array('from'=>'xxx', 'to'=>'xxx', 'contents'=>'xxx'), ); // 发送数据 $task_connection->send(json_encode($task_data)); // 异步获得结果 $task_connection->onMessage = function($task_connection, $task_result)use($ws_connection) { // 结果 var_dump($task_result); // 获得结果后记得关闭异步连接 $task_connection->close(); // 通知对应的websocket客户端任务完成 $ws_connection->send('task complete'); }; // 执行异步连接 $task_connection->connect(); } Worker::runAll();
這樣,繁重的任務交給本機或者其它伺服器的進程去做,任務完成後會異步收到結果,業務進程就不會阻塞了。
更多Workerman相關技術文章,請造訪Workerman教學欄位進行學習!
以上是workerman如何實現非同步任務(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!