从onConnect到onMessage时间间隔长达1秒,该如何排查并调整?

cqqjj1029

问题描述:
服务器在江苏,同一套服务端Workerman,我做了一份远程测试脚本,分别从我的笔记本(辽宁)和另外的云服务器(北京)上运行测试脚本,结果如下:
笔记本在辽宁家用宽带执行测试脚本访问江苏的服务器,从onConnect到onMessage间隔60毫秒;
华为云北京区执行测试脚本访问江苏的服务器,从onConnect到onMessage间隔1.04秒。

贴部分日志:
2021-05-27 19:18:08.3205: 60.16.8.76 connected to ApiV1.
[2021-05-27 19:18:08.3832(1622114288.3833)] 开始调用
……
2021-05-27 19:17:11.2423: 121.36.35.240 connected to ApiV1.
[2021-05-27 19:17:12.2813(1622114232.2814)] 开始调用

贴部分代码:

/**
 * 声明apiv1的worker进程
 */
$apiV1Worker = new Worker($config['workerAddress']['api_v1']);
// apiv1进程名字
$apiV1Worker->name = 'apiV1Worker';
// apiv1进程数
$apiV1Worker->count = $config['workerCount']['api_v1'];
// apiv1的回调类
$apiV1Callback = new ApiV1Callback();
// apiv1进程处理程序
$apiV1Worker->onWorkerStart = array($apiV1Callback, 'onWorkerStart');
$apiV1Worker->onConnect = array($apiV1Callback, 'onConnect');
$apiV1Worker->onMessage = array($apiV1Callback, 'onMessage');
$apiV1Worker->onClose = array($apiV1Callback, 'onClose');
class ApiV1 extends BaseCallback
{
    /**
     * onWorkerStart回调,子进程开启时执行,每个子进程都执行一次
     *
     * @author Aaron <chenqiang@h024.cn>
     *
     * @param [type] $worker
     */
    public function onWorkerStart($worker)
    {
        global $db, $http, $redis, $redisQueueClient, $log;
        $db = new SqlConnection(
            $this->config['db']['host'],
            $this->config['db']['port'],
            $this->config['db']['username'],
            $this->config['db']['password'],
            $this->config['db']['database']
        );
        // 进程内全局初始化异步httpClient
        $http = new HttpClient();
        // 进程内全局初始化redis连接
        $redis = new \Redis();
        $redis->connect(
            $this->config['redis']['host'],
            $this->config['redis']['port'],
            15
        );
        $redisQueueClient = new RedisQueueClient($this->config['redis']['url']);
        $log = new LogService();
    }

    /**
     * 当客户端与Workerman建立连接时(TCP三次握手完成后)触发的回调函数。每个连接只会触发一次onConnect回调
     *
     * @author Aaron <chenqiang@h024.cn>
     *
     * @param [type] $connection
     */
    public function onConnect($connection)
    {
        $ip = $connection->getRemoteIp();
        $time = ToolUtil::getMicroTimeStr();
        global $log;
        $log->record("{$time}: {$ip} connected to ApiV1.");
    }

    /**
     * 当客户端通过连接发来数据时(Workerman收到数据时)触发的回调函数
     *
     * @author Aaron <chenqiang@h024.cn>
     *
     * @param [type] $connection
     * @param [type] $data
     */
    public function onMessage($connection, $request)
    {
        // 请求数量计数,达到一定量后要在结尾重启进程
        static $request_count;
        $apiService = new ApiService();
        $logInfo = $apiService->oldPreStart($request);
        $logInfo['log_prefix'] = $connection->getRemoteIp() . ' ' . $logInfo['log_prefix'];
        // 如果在方法内不重新声明global,将被当做局部变量
        global $http, $redisQueueClient, $log;
        $returnCode = new ReturnCodeUtil();
        // 定义一个专门用于记录错误的logger正常情况时的logger默认就是main_logger
        $errorLogger = 'error_logger';
        // 请求url中的路径部分,
        $path = $request->path();
        // 根据path判断需要执行的响应
        switch ($path) {
2253 2 0
2个回答

智佳思远

辽宁家用宽带访问江苏的服务器没问题的话,
那感觉是 华为云北京区到江苏的服务器网络卡顿吧。
ping 下看下延迟多久

  • cqqjj1029 2021-05-28

    华为云北京ping江苏主机稳定在35ms,且几乎不丢包。而且,在江苏主机上,还有另外一组别人用C写的http服务,而这组用C写的http,无论对于辽宁的请求还是华为云北京的请求,响应时间都很稳定,这就很奇怪,我也不知道该怎么排查这里面的各个细节。

  • 智佳思远 2021-05-28

    客户端记录下时间,看下客户端从连接到发数据时间间隔

  • cqqjj1029 2021-05-29

    @2604:php的curl_exec方法该如何跟踪连接时间和发送数据时间间隔?不太了解,我们做的都是http协议。

  • cqqjj1029 2021-05-29

    @2604:
    curl_getinfo返回值(两个starttransfer_time明显不一样,客户端脚本在同一台机器上,curl请求是复用的,两个http服务器在同一个网关内,但是不同的物理服务器,CPU和内存都同样强大,会不会是我对workerman主机的哪里配置不太对?linux内核部分是按照workerman文档做的):
    【workerman提供的http服务】
    Array
    (
    [url] => http://api.51aicall.com:8084/api/v1/asr/recognition?account=L71BSJQK&appkey=0bb73a96-5478-4d4e-9933-6684895caae0&ts=1622253129&sign=7180e6c57dd20a63565b48f7941a3114
    [content_type] => text/html;charset=utf-8
    [http_code] => 200
    [header_size] => 122
    [request_size] => 290
    [filetime] => -1
    [ssl_verify_result] => 0
    [redirect_count] => 0
    [total_time] => 1.619209
    [namelookup_time] => 0.028273
    [connect_time] => 0.063434
    [pretransfer_time] => 0.063452
    [size_upload] => 16070
    [size_download] => 144
    [speed_download] => 88
    [speed_upload] => 9924
    [download_content_length] => 144
    [upload_content_length] => 16070
    [starttransfer_time] => 1.063512
    [redirect_time] => 0
    [redirect_url] =>
    [primary_ip] => 36.154.171.230
    [certinfo] => Array
    (
    )

    [primary_port] => 8084
    [local_ip] => 192.168.0.134
    [local_port] => 47932

    )

    【C手写的http服务】
    Array
    (
    [url] => http://api.51aicall.com:9010/asr?account=KQFFICGG&corp_key=5a0cd430-4466-40b9-8a56-1381e62dd591&ts=1622253245&sign=3461033688bc26e7e43b09d12fc8d853&type=1
    [content_type] => text/html; charset=ISO-8859-1
    [http_code] => 200
    [header_size] => 147
    [request_size] => 280
    [filetime] => -1
    [ssl_verify_result] => 0
    [redirect_count] => 0
    [total_time] => 0.654652
    [namelookup_time] => 0.01219
    [connect_time] => 0.048642
    [pretransfer_time] => 0.048659
    [size_upload] => 16070
    [size_download] => 101
    [speed_download] => 154
    [speed_upload] => 24547
    [download_content_length] => 101
    [upload_content_length] => 16070
    [starttransfer_time] => 0.085582
    [redirect_time] => 0
    [redirect_url] =>
    [primary_ip] => 36.154.171.230
    [certinfo] => Array
    (
    )

    [primary_port] => 9010
    [local_ip] => 192.168.0.134
    [local_port] => 55332

    )

cqqjj1029

各种方式测试,终于找到了原因,自己回答一下:
问题并不是workerman的,而是用php写的模拟客户端脚本。

Except:100-continue, 网上一查,是HTTP 1.1协议里当请求方的请求包大于1024字节,会先发送 该句请求头,以期确认服务器具备大于1024字节数据包处理能力,然后才发送剩余数据,而我们的发送方的请求包必然大于1024字节,故而crul先发送该询问,等待服务器超时(默认1秒)后才开始发送剩余数据,所幸curl考虑到该协议各服务器支持不是很规范,所以当curl等待超时后没有直接放弃传输,而是继续传输,综合出现了上述情况
————————————————
版权声明:本文为CSDN博主「straka」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/atp1992/article/details/80783262

我做的是语音转文字接口,需要上传的是音频文件,自然都大于1024,所以这个客户端都是要先和服务器连接一下,然后等服务器回应或回应超时(1秒)后再发送数据。

解决办法(客户端加上这句话):
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));

  • 暂无评论
年代过于久远,无法发表回答
🔝