我简化了下代码,大致如下:
define('MAX_REQUEST', 5000);
$worker = new Worker('http://0.0.0.0:端口');
$worker->onWorkerStart = function($worker)
{
global $mqtt;
$mqtt = new Workerman\Mqtt\Client($url, $options);
$mqtt->onConnect = function($mqtt) {
};
$mqtt->connect();
};
$worker->onMessage = function(TcpConnection $connection, $args)
{
global $mqtt;
// 已经处理请求数
static $request_count = 0;
$data = $args->post();
// 此处报错
$mqtt->publish($topic, json_encode($data));
$connection->send('Status Code: 200 OK');
// 如果请求数达到5000
if(++$request_count >= MAX_REQUEST)
{
$mqtt->close();
Worker::stopAll();
}
};
Worker::runAll();
业务大概是:需要一个http服务端用来接收http的请求,拿到数据经过处理以后,在用mqtt进行推送。服务端启动时不会报错,但是当进程达到设定好的5000次执行关闭并重新开启的时候,由于mqtt还没连接上,就收到http请求并且执行mqtt->publish()了,导致mqtt报错,No connection to broker,请问大佬,有什么方法可以避免这个问题吗?
收到5000请求就退出这个逻辑感觉没什么必要。
如果想保留现有5000请求退出逻辑,就要做一个内存缓存,当mqtt没连接成功时,收到的请求放到内存缓存起来。当mqtt连接上后将缓存的数据发给mqtt。
伪代码类似
我觉得$mqttConnected === false时,将 $connection->send放到$mqtt->onConnect 或者onError/onClose里,new Workerman\Mqtt\Client加上超时时间。这样基本上可以做到http响应和mqtt服务响应同步。
$connection->send内容也是根据mqtt状态不同而不同
大佬,我后来把5000请求去掉了,最近项目运行时遇到个问题,还是mqtt的,debug如下:
-> Send PINGREQ package
-- Error: Connection closed4
-- Connection closed
-- Reconnect after 1 seconds
-- Error: No connection to broker5
-- Tcp connection established
是心跳没收到回复然后把链接关掉了?但是重连以后,又报错没连上broker,漏发消息了,还请大佬帮忙分析解决下,感谢
可能是服务端没回应心跳连接断开了。publish有失败回调,失败的消息放到全局数组里,等$mqtt->onConnect触发时再依次发送。
感谢大佬~