按給的文檔里的 $loop 使用 Worker::getEventLoop(); 獲取,然后使用 Client? 實例的 end() 后,沒有任何反應(yīng),但改為使用 React\EventLoop\Factory::create() 獲取到的 $loop 再按 react 的文檔里調(diào)用 $loop->run() 才正常,on('response') 和 on('error') 才能正確收到數(shù)據(jù)。
另外為什么不改進下 AsyncTcpConnection 直接支持 http 協(xié)議呢?
哦,我知道原因了,因為發(fā)請求是在收到 beanstalk 隊列后請求的,發(fā)送請求后 beanstalkd 立即? reserve 了等待新隊列消息,這時候進程阻塞了,所以不執(zhí)行 http 的請求了。。。看來這個 reserve 也得使用異步的方式來做才行。
我已經(jīng)基于 AsyncTcpConnection 實現(xiàn)了一個全異步的協(xié)程式 Beanstalkd 客戶端,目前測試可以正常運行,在 reserve 階段不會阻塞 Worker 進程,等完善之后發(fā)布源碼到 Github。
大概使用示例(以下代碼在 onWorkerStart 中):
$client = new \MyTestBeanstalkdClient($config, $config);
$client->start(function() use ($client) {
$ret = yield $client->connect();
echo 'after connect';
var_dump($ret);
$ret = yield $client->listTubes();
echo 'after listtubes';
var_dump($ret);
while (true) {
$ret = yield $client->reserve();
$lines = explode("\r\n", $ret);
list($status, $jobId, $length) = explode(" ", $lines);
array_shift($lines);
$data = join('', $lines);
echo "get job: $jobId\n";
echo "get data: $data";
$ret = yield $client->delete($jobId);
echo $ret;
}
});
之前的用法,是普通的 socket 連接,當(dāng) reserve 時,Worker 進程會阻塞,導(dǎo)致其它異步請求無法發(fā)送,而且使用 status 命令也無法檢查進程狀態(tài),顯示為 busy。
?
改用這種異步協(xié)程方式后,reserve 狀態(tài)下,工作進程就完全是 idle 狀態(tài),其它異步請求也完全沒有任何影響,并且是全同步式寫法,不會難理解。
這個目前暫停了,因為用純原生的 PHP 代碼去實現(xiàn)協(xié)程碰到了各種問題,比如協(xié)程嵌套,協(xié)程之間的各種協(xié)調(diào),處理起來非常麻煩,上面演示的是單層協(xié)程,但考慮到實現(xiàn) start() 內(nèi)部還可能出現(xiàn)其它程序的協(xié)程、客戶端內(nèi)部也可能出現(xiàn)斷線重連等各種需要考慮協(xié)程配合的場景,我還沒想到較好的辦法來做這個,所以目前暫停了。