问题描述:
服务器在江苏,同一套服务端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) {
辽宁家用宽带访问江苏的服务器没问题的话,
那感觉是 华为云北京区到江苏的服务器网络卡顿吧。
ping 下看下延迟多久
华为云北京ping江苏主机稳定在35ms,且几乎不丢包。而且,在江苏主机上,还有另外一组别人用C写的http服务,而这组用C写的http,无论对于辽宁的请求还是华为云北京的请求,响应时间都很稳定,这就很奇怪,我也不知道该怎么排查这里面的各个细节。
客户端记录下时间,看下客户端从连接到发数据时间间隔
@2604:php的curl_exec方法该如何跟踪连接时间和发送数据时间间隔?不太了解,我们做的都是http协议。
@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
(
)
)
【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
(
)
)
各种方式测试,终于找到了原因,自己回答一下:
问题并不是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:'));