RFC: https://www.rfc-editor.org/rfc/rfc2616
HTTP/1.0 默认是短连接,除非传 Connection: Keep-Alive 才是长连接
HTTP/1.1 默认长连接,除非传 Connection: close,才是短连接
Workerman 的不规范实现,可能会对完全遵守 RFC 工具造成影响,比如 ab 非长连接压测。
下面是可以直接测试的代码:(希望 Workerman 尽快引入 phpunit)
server.php:
<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
require __DIR__ . '/vendor/autoload.php';
$worker = new Worker('http://0.0.0.0:8080');
$worker->onMessage = function(TcpConnection $connection, Request $request)
{
// 下面两种都可以
// $connection->send("hello:" . $request->connection->id);
$connection->send(new Response(200, [], "hello:" . $request->connection->id));
};
// 运行worker
Worker::runAll();
test.php:
<?php
function test1_0_close()
{
echo 'HTTP 1.0 close test:', PHP_EOL;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://127.0.0.1:8080/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
var_dump($a = curl_exec($ch));
var_dump($b = curl_exec($ch));
curl_close($ch);
if ($a === $b)
{
echo 'HTTP/1.0 close test failed', PHP_EOL, PHP_EOL;
}
}
function test1_0_keep_alive()
{
echo 'HTTP 1.0 keep-alive test:', PHP_EOL;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://127.0.0.1:8080/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Connection: Keep-Alive',
]);
var_dump($a = curl_exec($ch));
var_dump($b = curl_exec($ch));
curl_close($ch);
if ($a !== $b)
{
echo 'HTTP/1.0 keep-alive test failed', PHP_EOL, PHP_EOL;
}
}
function test1_1_close()
{
echo 'HTTP 1.1 close test:', PHP_EOL;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://127.0.0.1:8080/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Connection: close',
]);
var_dump($a = curl_exec($ch));
var_dump($b = curl_exec($ch));
curl_close($ch);
if ($a === $b)
{
echo 'HTTP/1.1 close test failed', PHP_EOL, PHP_EOL;
}
}
function test1_1_keep_alive()
{
echo 'HTTP 1.1 keep-alive test:', PHP_EOL;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://127.0.0.1:8080/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
var_dump($a = curl_exec($ch));
var_dump($b = curl_exec($ch));
curl_close($ch);
if ($a !== $b)
{
echo 'HTTP/1.1 keep-alive test failed', PHP_EOL, PHP_EOL;
}
}
test1_0_close();
test1_0_keep_alive();
test1_1_close();
test1_1_keep_alive();
https://github.com/walkor/workerman/pull/857#issuecomment-1362375399
非常感谢你的建议
从语义上来讲,
应该只发送数据,不应该断开连接,如果是短连接压测应该使用
$connection->close(new Response())
。一个解决方案是实现一个独立的HttpServer
这样层次清晰明了,但是增加了一个类加大了workerman复杂性,其它意义不大,得不偿失。
总结
仅仅是创建了一个能支持http协议的容器,但是它不是完整的http服务器实现,是否关闭连接需要手动判断并调用。
关于自动化测试明年应该会加上。
👍 讲究!
正在写测试,因为事情比较多,也只能空了写一点空了写一点😭