四、Swoole 基础学习笔记 - 启动一个 Swoole HTTP 服务器
4、Swoole 基础学习笔记 - 启动一个 Swoole HTTP 服务器
hi,我是温新,一名PHPer
文章基于 Swoole 5.0 版本编写。
学习目标:学习 Swoole Http Server 及相关知识。
说明:本篇文章结合官方文档编写及参考网络资料编写,虽非全部原创,但也是结合了自己的理解,若转载请附带本文 URL,编写不易,持续编写更不易,谢谢!
经过上一篇文章的洗刷后,我们再来看看 Swoole 的另一个功能——HTTP服务器,跑一个 HTTP 服务器来环境来缓解一下气氛。
Swoole 内置实现了一个简单的 HttpServer 类,相当于 php-fmp,其优势在于高性能,将代码载入内存,后续无需解释执行。由于 Http\Server
对 HTTP
协议的支持并不完整,建议仅作为应用服务器,用于处理动态请求,并且在前端增加 Nginx
作为代理。在实际生产环境中,在前端增加一层 Nginx,一些静态文件(css/js)等交给 Nginx,而 PHP 文件则交给 Swoole 来处理。
Swoole http 是如何处理请求的
来看看流程图,如下:
1、Http/Server 在协议解析部分使用的是 Http 协议;
2、http 协议请求会被封装中 Swoole\Http\Request 对象中,如请求参数,要从这里获取;
3、所有的 http 响应都要通过 Swoole\Http\Response 对象进程封装和发送。
学习了这些,再来看看运行 http server。
先把 Web 服务器运行起来
他用 swoole 创建一个异步非阻塞多进程的 Http 服务器。
<?php
// 2-swoole-http.php
// 实例化 http server 对象
$http = new Swoole\Http\Server('0.0.0.0', 9501);
// 监听网络请求
$http->on('Request', function ($request, $response) {
// 处理/响应请求
$response->header('Content-Type', 'text/html; charset=utf-8');
$response->end('<h1>Hello Swoole. #' . rand(1000, 9999) . '</h1>');
});
// 启动 http server
$http->start();
解读一下代码,通过 Swoole\Http\Server
传递两个参数,实例化出一个 http 对象,然后监听 Request
,其回调函数接收两个参数,Swoole\Http\Request(请求)
和 Swoole\Http\Response (响应)
。如下是官方说明:
HTTP
服务器只需要关注请求响应即可,所以只需要监听一个onRequest
事件。当有新的HTTP
请求进入就会触发此事件。事件回调函数有2
个参数,一个是$request
对象,包含了请求的相关信息,如GET/POST
请求的数据。另外一个是
response
对象,对request
的响应可以通过操作response
对象来完成。$response->end()
方法表示输出一段HTML
内容,并结束此请求。
现在请求服务,并在浏览器中输入 localhost:9501
就可以看到页面信息了。
运行 Swoole Http 还远远不够
http 协议有两个动作:请求
和响应
,Swoole Http Server 也是如此。服务器运行起来后,该如何处理这两个动作?下面继续学习。
Swoole/Http/Request
作用:负责处理 http 请求的相关信息。
既然知道了 request 是处理请求相关的,那么它有哪些内容?现在把 $request
打印出来看看,它是什么:
// 省略其他内容
$http->on('Request', function ($request, $response) {
print_r($request);
// ...
});
// ...
通过打印的结果,可以看到它是一个 Swoole\Http\Request Object
对象,这个对象中包含了很多信息,有 header、server、cookie、get、post、files 等,
Swoole\Http\Request Object
(
[fd] => 1
[streamId] => 0
[header] => Array
(
[host] => localhost:9501
[connection] => keep-alive
[sec-ch-ua] => "Google Chrome";v="107", "Chromium";v="107", "Not=A?Brand";v="24"
[sec-ch-ua-mobile] => ?0
[user-agent] => Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36
[sec-ch-ua-platform] => "Linux"
[accept] => image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
[sec-fetch-site] => same-origin
[sec-fetch-mode] => no-cors
[sec-fetch-dest] => image
[referer] => http://localhost:9501/
[accept-encoding] => gzip, deflate, br
[accept-language] => zh-CN,zh;q=0.9
)
[server] => Array
(
[request_method] => GET
[request_uri] => /favicon.ico
[path_info] => /favicon.ico
[request_time] => 1669652656
[request_time_float] => 1669652656.2447
[server_protocol] => HTTP/1.1
[server_port] => 9501
[remote_port] => 56526
[remote_addr] => 127.0.0.1
[master_time] => 1669652656
)
[cookie] =>
[get] =>
[files] =>
[post] =>
[tmpfiles] =>
)
想想以前接收 get 请求参数是使用 $_GET
,而在 Swoole 中,这些超全局变量全部失效。以下是官方说明:
协程使得原有的异步逻辑同步化,但是在协程的切换是隐式发生的,所以在协程切换的前后不能保证全局变量以及
static
变量的一致性。在
PHP-FPM
下可以通过全局变量获取到请求的参数,服务器的参数等,在Swoole
内,无法 通过$_GET/$_POST/$_REQUEST/$_SESSION/$_COOKIE/$_SERVER
等$_
开头的变量获取到任何属性参数。
在 Swoole 中,可以使用如下方式处理请求:
$_GET = $request->get;
$_POST = $request->post;
$_HEADER = $request->header;
$_SERVER = $request->server;
$_COOKIE = $request->cookie;
$_FILES = $request->files;
$_CONTENT = $request->rawContent;
$request->getData;
转换一个方式就很好理解了,这种方式不用多说,相信 PHPer 都已经非常熟悉了,下面了解一下注意事项,然后动手试试吧。
- 1、Swoole Http/Server 可以接收
application/x-www-form-urlencoded
和form-data
数据,解析后数据会放在$request
对象中。若是application/json
数据,需要通过getContent()
方法来接收; - 2、Post 上传文件时,需要设置临时文件位置且需要设置包的大小,文件最大尺寸受到
package_max_length
限制,不上传大文件进行处理。当$request
对象销毁时,会自动删除上传的临时文件。
Swoole/Http/Response
**作用:负责响应 http 请求。**响应信息包含:响应头信息、响应状态等,没有列出的方法请参考官方文档。
Swoole\Http\Response->header(string $key, string $value, bool $format = true);
Swoole\Http\Response->cookie(string $key, string $value = '', int $expire = 0 , string $path = '/', string $domain = '', bool $secure = false , bool $httponly = false, string $samesite = '', string $priority = '');
Swoole\Http\Response->status(int $http_status_code, string $reason): bool
压测 Swoole Http Server
了解了这么多,现在来看我们这服务进行压测看看,结果如下:
$ab -n 1000 -c 100 http://localhost:9501/
Server Software: swoole-http-server
Server Hostname: localhost
Server Port: 9501
Document Path: /
Document Length: 28 bytes
Concurrency Level: 100
Time taken for tests: 0.030 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 191000 bytes
HTML transferred: 28000 bytes
Requests per second: 33518.80 [#/sec] (mean)
Time per request: 2.983 [ms] (mean)
Time per request: 0.030 [ms] (mean, across all concurrent requests)
Transfer rate: 6252.04 [Kbytes/sec] received
本篇文章到此结束,我是温新,我们下一篇文章见。