一起看看Swoole HTTP

广告:宝塔服务器面板,一键全能部署及管理,送你10850元礼包,点我领取~~~

一起看看Swoole HTTP

目标

了解swoole的http_server的使用了解swoole的tcp服务开发实际项目中问题如粘包处理、代理热更新、用户验证等。swoole与现有框架结合

风格

偏基础重代码

环境

PHP版本:Swoole版本:https://github.com/swoole/swoole-srczphp开发框架:https://github.com/shenzhe/zphp

HTTP Server

静态文件处理动态请求与框架结合
# 查看SWOOLE版本$ php -r 'echo SWOOLE_VERSION;'4.3.1
登录后复制

推荐(免费):swoole

基础概念

HTTP报文

关于HTTP请求报文的组成结构

HTTP请求报文结构

POST /search HTTP/1.1  Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-silverlight, application/x-shockwave-flash, */*  Referer: http://www.google.cn/  Accept-Language: zh-cn  Accept-Encoding: gzip, deflate  User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)  Host: www.google.cn Connection: Keep-Alive  Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g; NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-FxlRugatx63JLv7CWMD6UB_O_r  hl=zh-CN&source=hp&q=domety
登录后复制

关于HTTP响应报文的组成结构

HTTP响应报文结构

HTTP/1.1 200 OKDate: Mon, 23 May 2005 22:38:34 GMTContent-Type: text/html; charset=UTF-8Content-Encoding: UTF-8Content-Length: 138Last-Modified: Wed, 08 Jan 2003 23:11:55 GMTServer: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)ETag: "3f80f-1b6-3e1cb03b"Accept-Ranges: bytesConnection: close
登录后复制

创建HTTP服务器

Swoole在1.7.7版本后内置HTTP服务器,可创建一个异步非阻塞多进程的HTTP服务器。Swoole的HTTP服务器对HTTP协议支持的并不完整,建议仅作为应用服务器,并在前端增加Nginx作为代理。

因为Swoole是在CLI命令行中执行的,在传统的NGINX+FastCGI模式下很多rootshell是无法执行的,而使用Swoole服务器就能很好的控制rsyncgitsvn等。

使用Swoole的API,构建HTTP服务器需要4个步骤

创建Server对象设置运行时参数注册事件回调函数启动服务器
# 创建应用$ mkdir test && cd test# 创建并编辑服务器文件$ vim server.php
登录后复制
<?php//创建HTTP服务器对象$host = "0.0.0.0";$port = 9501;$server = new swoole_http_server($host, $port);var_dump($server);//设置服务器运行参数$configs = [];$configs["worker_num"] = 2;//设置Worker工作进程数量$configs["daemonize"] = 0;//设置是否已后台守护进程运行$server->set($configs);//注册监听客户端HTTP请求回调事件$server->on("request", function(swoole_http_request $request, swoole_http_response $response) use($server){    var_dump($request);    var_dump($response);        //获取客户端文件描述符    $fd = $request->fd;    if(!empty($fd)){        //获取连接信息        $clientinfo = $server->getClientInfo($fd);        var_dump($clientinfo);        //获取收包时间        var_dump($clientinfo["last_time"]);    }    //响应客户端HTTP请求    $response->write("success");//向客户端写入响应数据    $response->end();//浏览器中输出结果});//启动服务器$server->start();
登录后复制
# 使用PHP-CLI运行服务器脚本$ php server.php# 使用CURL向HTTP服务器发送请求测试$ curl 127.0.0.1:9501
登录后复制

使用注意

echovar_dumpprint_r的内容是在服务器中输出的浏览器中输出需要使用$rp->end(string $contents)end()方法只能调用一次。如果需要多次先客户端发送消息可使用$rp->write(string $content)方法完整的HTTP协议请求会被解析并封装在swoole_http_request对象中所有的HTTP协议响应会通过swoole_http_response对象进行封装并发送

HTTP服务器的本质

由于swoole_http_server是基于swoole_server的,所以swoole_server下的方法在swoole_http_server中都可以使用,只是swoole_http_server只能被客户端唤起。简单来说,swoole_http_server是基于swoole_server加上HTTP协议,再加上requestresponse类库去实现请求数据和获取数据。与PHP-FPM不同的是,Web服务器收到请求后会传递给Swoole的HTTP服务器,直接返回请求。

swoole_http_server

Http\Server

Swoole\HTTP\Server继承自Server,是一个HTTP服务器实现,支持同步与有异步两种模式。无论是同步模式还是异步模式,HTTP服务器都可以维持大量的TCP客户端连接,同步与异步仅仅提现在对请求的处理方式。

同步模式

同步模式等同于Nginx+PHP-FPM/Apache,需要设置大量Worker工作进程来完成并发请求处理,Worker工作进程可以使用同步阻塞IO,编程方式与普通的PHP的Web程序完全一致。与PHP-FPM/Apache不同的是,客户端连接并不会独占进程,服务器依然可以应对大量并发连接。

异步模式

异步模式下整个HTTP服务器是异步非阻塞的,服务器可以应答大规模的并发连接和并发请求,编程方式需要完全使用异步API,如MySQL、Redis、HTTP客户端、file_get_contentssleep等阻塞IO操作必须切换为异步方式,如异步Client、Event、Timer等API。

查看HTTP服务器实例对象

var_dump($server);
登录后复制
object(Swoole\Connection\Iterator)#2 (0) {  ["host"]=>string(7) "0.0.0.0"  ["port"]=>int(9501)  ["type"]=>int(1)  ["mode"]=>int(2)  ["ports"]=>  array(1) {    [0]=>    object(Swoole\Server\Port)#3 (16) {      ["onConnect":"Swoole\Server\Port":private]=>NULL      ["onReceive":"Swoole\Server\Port":private]=>NULL      ["onClose":"Swoole\Server\Port":private]=>NULL      ["onPacket":"Swoole\Server\Port":private]=>NULL      ["onBufferFull":"Swoole\Server\Port":private]=>NULL      ["onBufferEmpty":"Swoole\Server\Port":private]=>NULL      ["onRequest":"Swoole\Server\Port":private]=>NULL      ["onHandShake":"Swoole\Server\Port":private]=>NULL      ["onOpen":"Swoole\Server\Port":private]=>NULL      ["onMessage":"Swoole\Server\Port":private]=>NULL      ["host"]=>string(7) "0.0.0.0"      ["port"]=>int(9501)      ["type"]=>int(1)      ["sock"]=>int(4)      ["setting"]=>NULL      ["connections"]=>object(Swoole\Connection\Iterator)#4 (0) {      }    }  }  ["master_pid"]=>int(0)  ["manager_pid"]=>int(0)  ["worker_id"]=>int(-1)  ["taskworker"]=>bool(false)  ["worker_pid"]=>int(0)  ["onRequest":"Swoole\Http\Server":private]=>NULL  ["onHandshake":"Swoole\Http\Server":private]=>NULL}
登录后复制配置选项文件上传upload_tmp_dir

HTTP服务器支持大文件上传,但由于Swoole底层的限制,文件内容是存放在内存中的,因此如果并发上传大量文件可能会导致内存占用量过大的问题。

可以修改upload_tmp_dir选项用于配置上传文件的临时目录,需要注意是目录文件夹的名称最大长度不得超过220个字节。

$configs = [];$configs["upload_tmp_dir"] = "/data/uploads/";$server->set($configs);
登录后复制POST解析http_parse_post

可通过修改http_parse_post配置项用来设置表单POST提交后是否解析,若设置为true则表示会自动将Content-Type内容类型为x-www-urlencode的请求包体解析到 POST 数组,若设置为false则表示将会关闭 POST解析。

$configs = [];$configs["http_parse_post"] = true;$server->set($configs);
登录后复制

POST尺寸 package_max_length

默认情况下,表单上传或POST提交2MB的数据的限制,可通过修改package_max_length选项调整POST尺寸大小。

POST /search HTTP/1.1  Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-silverlight, application/x-shockwave-flash, */*  Referer: http://www.google.cn/  Accept-Language: zh-cn  Accept-Encoding: gzip, deflate  User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)  Host: www.google.cn Connection: Keep-Alive  Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g; NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-FxlRugatx63JLv7CWMD6UB_O_r  hl=zh-CN&source=hp&q=domety0
登录后复制解析Cookiehttp_parse_cookie

通过修改http_parse_cookie配置项可以开启或关闭Cookie解析,关闭后将会在Header头信息学中保留未经处理的原始Cookies信息。

POST /search HTTP/1.1  Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-silverlight, application/x-shockwave-flash, */*  Referer: http://www.google.cn/  Accept-Language: zh-cn  Accept-Encoding: gzip, deflate  User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)  Host: www.google.cn Connection: Keep-Alive  Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g; NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-FxlRugatx63JLv7CWMD6UB_O_r  hl=zh-CN&source=hp&q=domety1
登录后复制文件压缩http_compression

http_compression适用于Swoole4.1.0+版本,用于启用或关闭对HTTP信息的压缩,默认为开启状态。

由于http-chunk不支持分段独立压缩,因此默认已强制关闭了压缩功能。

POST /search HTTP/1.1  Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-silverlight, application/x-shockwave-flash, */*  Referer: http://www.google.cn/  Accept-Language: zh-cn  Accept-Encoding: gzip, deflate  User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)  Host: www.google.cn Connection: Keep-Alive  Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g; NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-FxlRugatx63JLv7CWMD6UB_O_r  hl=zh-CN&source=hp&q=domety2
登录后复制

目前HTTP支持gzipbr(需google brotli库支持)、deflate三种压缩格式,Swoole底层会根据客户端浏览器传入的Accept-Encoding头信息自动选择压缩方式。

压缩级别http_compression_level

http_compression_level选项用于配置压缩的级别,压缩级别越高压缩后体积越小,同时也会越占用CPU。

POST /search HTTP/1.1  Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-silverlight, application/x-shockwave-flash, */*  Referer: http://www.google.cn/  Accept-Language: zh-cn  Accept-Encoding: gzip, deflate  User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)  Host: www.google.cn Connection: Keep-Alive  Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g; NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-FxlRugatx63JLv7CWMD6UB_O_r  hl=zh-CN&source=hp&q=domety3
登录后复制静态根目录document_root

document_root选项适用于Swoole1.9.17+版本,用于配置静态文件的根目录,该功能由于较为简易不推荐在公网环境下直接使用,常于enable_static_handler选项配合使用。

如果设置document_rootenable_static_handler = true后,Swoole底层收到HTTP请求时会先判断document_root的路径下是否存在某静态文件,如果存在会直接发送内容给客户端,并不再调用onRequest函数。

这里需要注意的时,在使用静态文件处理特性时,应当将动态PHP代码于静态文件进行隔离,静态文件应存放到特定的目录下。

POST /search HTTP/1.1  Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-silverlight, application/x-shockwave-flash, */*  Referer: http://www.google.cn/  Accept-Language: zh-cn  Accept-Encoding: gzip, deflate  User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)  Host: www.google.cn Connection: Keep-Alive  Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g; NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-FxlRugatx63JLv7CWMD6UB_O_r  hl=zh-CN&source=hp&q=domety4
登录后复制静态处理 enable_static_handler

enable_static_handler选项用于开启或关闭静态文件请求处理功能,常配合document_root选项使用。

POST /search HTTP/1.1  Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-silverlight, application/x-shockwave-flash, */*  Referer: http://www.google.cn/  Accept-Language: zh-cn  Accept-Encoding: gzip, deflate  User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)  Host: www.google.cn Connection: Keep-Alive  Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g; NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-FxlRugatx63JLv7CWMD6UB_O_r  hl=zh-CN&source=hp&q=domety5
登录后复制静态处理器路径static_handler_locations

static_handler_location选项适用于Swoole4.4.0+版本,用于设置静态处理器的路径,类型为数组,默认不启用。

静态处理器类似于Nginx的location指令,可以指定一个或多个路径为静态路径。只有URL在指定路径下才会启用静态问而建处理器,否则会视为动态请求。location选项必须以/开头并支持多级路径,如/app/images

当启用static_handler_locations选项后,如果请求对应的文件不存在,将直接会返回404错误。

POST /search HTTP/1.1  Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-silverlight, application/x-shockwave-flash, */*  Referer: http://www.google.cn/  Accept-Language: zh-cn  Accept-Encoding: gzip, deflate  User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)  Host: www.google.cn Connection: Keep-Alive  Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g; NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-FxlRugatx63JLv7CWMD6UB_O_r  hl=zh-CN&source=hp&q=domety6
登录后复制设置代理

由于swoole_http_server对HTTP协议支持的并不完整,建议仅仅作为应用服务器,并在前端增加Nginx作为反向代理。

操作前需要修改服务器的运行参数,设置enable_static_handletrue后,底层收到HTTP请求会像判断document_root路径下是否存在目标文件,若存在则会直接发送文件给客户端,不再触发onRequest回调。

设置服务器运行时环境
POST /search HTTP/1.1  Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-silverlight, application/x-shockwave-flash, */*  Referer: http://www.google.cn/  Accept-Language: zh-cn  Accept-Encoding: gzip, deflate  User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)  Host: www.google.cn Connection: Keep-Alive  Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g; NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-FxlRugatx63JLv7CWMD6UB_O_r  hl=zh-CN&source=hp&q=domety7
登录后复制
POST /search HTTP/1.1  Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-silverlight, application/x-shockwave-flash, */*  Referer: http://www.google.cn/  Accept-Language: zh-cn  Accept-Encoding: gzip, deflate  User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)  Host: www.google.cn Connection: Keep-Alive  Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g; NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-FxlRugatx63JLv7CWMD6UB_O_r  hl=zh-CN&source=hp&q=domety8
登录后复制设置Nginx反向代理配置

例如:设置Nginx反向代理127.0.0.1:9501

POST /search HTTP/1.1  Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-silverlight, application/x-shockwave-flash, */*  Referer: http://www.google.cn/  Accept-Language: zh-cn  Accept-Encoding: gzip, deflate  User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)  Host: www.google.cn Connection: Keep-Alive  Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g; NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-FxlRugatx63JLv7CWMD6UB_O_r  hl=zh-CN&source=hp&q=domety9
登录后复制
HTTP/1.1 200 OKDate: Mon, 23 May 2005 22:38:34 GMTContent-Type: text/html; charset=UTF-8Content-Encoding: UTF-8Content-Length: 138Last-Modified: Wed, 08 Jan 2003 23:11:55 GMTServer: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)ETag: "3f80f-1b6-3e1cb03b"Accept-Ranges: bytesConnection: close0
登录后复制

Nginx+Swoole的组合中Nginx反向代理的配置

HTTP/1.1 200 OKDate: Mon, 23 May 2005 22:38:34 GMTContent-Type: text/html; charset=UTF-8Content-Encoding: UTF-8Content-Length: 138Last-Modified: Wed, 08 Jan 2003 23:11:55 GMTServer: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)ETag: "3f80f-1b6-3e1cb03b"Accept-Ranges: bytesConnection: close1
登录后复制请求对象

swoole_http_request请求对象保存了HTTP客户端请求的相关信息,包括GETPOSTCOOKIEHeader等,请求对象$request销毁时会自动删除上传的临时文件,不要使用&符号引用$request请求对象。

HTTP/1.1 200 OKDate: Mon, 23 May 2005 22:38:34 GMTContent-Type: text/html; charset=UTF-8Content-Encoding: UTF-8Content-Length: 138Last-Modified: Wed, 08 Jan 2003 23:11:55 GMTServer: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)ETag: "3f80f-1b6-3e1cb03b"Accept-Ranges: bytesConnection: close2
登录后复制Http\Request->$header

HTTP请求的头部信息,类型为数组,所有的键名均为小写。

HTTP/1.1 200 OKDate: Mon, 23 May 2005 22:38:34 GMTContent-Type: text/html; charset=UTF-8Content-Encoding: UTF-8Content-Length: 138Last-Modified: Wed, 08 Jan 2003 23:11:55 GMTServer: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)ETag: "3f80f-1b6-3e1cb03b"Accept-Ranges: bytesConnection: close3
登录后复制Http\Request->$server

HTTP请求相关的服务器信息,相当于PHP的$_SERVER全局数组,包含了HTTP请求的方法、URL路径、客户端IP等信息。服务器信息为关联数组,数组中的键名全部小写,并且与PHP的$_SERVER数组保持一致。

HTTP/1.1 200 OKDate: Mon, 23 May 2005 22:38:34 GMTContent-Type: text/html; charset=UTF-8Content-Encoding: UTF-8Content-Length: 138Last-Modified: Wed, 08 Jan 2003 23:11:55 GMTServer: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)ETag: "3f80f-1b6-3e1cb03b"Accept-Ranges: bytesConnection: close4
登录后复制

请求路径

当Google的Chrome浏览器访问服务器是会产生两次请求,这是因为Chrome会自动请求一次favicon.ico文件,所以服务器会收到两个HTTP请求,通过打印$request->server["request_uri"]可以查看到请求URL路径。如果需要屏蔽掉对favicon.ico的请求,可采用以下方式。

HTTP/1.1 200 OKDate: Mon, 23 May 2005 22:38:34 GMTContent-Type: text/html; charset=UTF-8Content-Encoding: UTF-8Content-Length: 138Last-Modified: Wed, 08 Jan 2003 23:11:55 GMTServer: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)ETag: "3f80f-1b6-3e1cb03b"Accept-Ranges: bytesConnection: close5
登录后复制

收包时间

request_time请求时间是在Worker工作进程中设置的,在SWOOLE_PROCESS多进程模式下存在dispatch分发的过程,因此可能会与实际收包时间存在偏差,尤其当请求量超过服务器处理能力时,有可能滞后于实际收包时间。

可通过Server->getClientInfo()方法获取last_time以获取 准确的收包时间。

HTTP/1.1 200 OKDate: Mon, 23 May 2005 22:38:34 GMTContent-Type: text/html; charset=UTF-8Content-Encoding: UTF-8Content-Length: 138Last-Modified: Wed, 08 Jan 2003 23:11:55 GMTServer: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)ETag: "3f80f-1b6-3e1cb03b"Accept-Ranges: bytesConnection: close6
登录后复制

客户端信息

Server->getClientInfo()用于获取连接的客户端信息

HTTP/1.1 200 OKDate: Mon, 23 May 2005 22:38:34 GMTContent-Type: text/html; charset=UTF-8Content-Encoding: UTF-8Content-Length: 138Last-Modified: Wed, 08 Jan 2003 23:11:55 GMTServer: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)ETag: "3f80f-1b6-3e1cb03b"Accept-Ranges: bytesConnection: close7
登录后复制int $fd 表示客户端连接文件描述符int $extraData 表示扩展信息是保留参数目前无任何效果bool $ignoreError 表示是否忽略错误,若设置为true表示即使连接关闭也会返回连接信息。

如果传入的$fd客户端连接文件描述符存在则返回一个数组,若不存在或已关闭则返回false

HTTP/1.1 200 OKDate: Mon, 23 May 2005 22:38:34 GMTContent-Type: text/html; charset=UTF-8Content-Encoding: UTF-8Content-Length: 138Last-Modified: Wed, 08 Jan 2003 23:11:55 GMTServer: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)ETag: "3f80f-1b6-3e1cb03b"Accept-Ranges: bytesConnection: close8
登录后复制Http\Request->$get

HTTP请求的GET参数,相当于PHP中的$_GET,格式为键值对的关联数组。为防止HASH攻击,GET参数最大不允许超过128个。

HTTP/1.1 200 OKDate: Mon, 23 May 2005 22:38:34 GMTContent-Type: text/html; charset=UTF-8Content-Encoding: UTF-8Content-Length: 138Last-Modified: Wed, 08 Jan 2003 23:11:55 GMTServer: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)ETag: "3f80f-1b6-3e1cb03b"Accept-Ranges: bytesConnection: close9
登录后复制

HTTP的GET请求只有一个HTTP Header头,Swowole底层使用固定大小的内存缓冲区为8K,而且不可修改。如果请求不是正确的HTTP请求,将会出现错误,底层会抛出错误。

# 创建应用$ mkdir test && cd test# 创建并编辑服务器文件$ vim server.php0
登录后复制Http\Request->$post

HTTP请求携带POST参数,格式为键值对的关联数组,POSTHeader加起来的尺寸不得超过package_max_length的设置,否则会认为是恶意请求,另外POST参数的个数不得超过128个。

# 创建应用$ mkdir test && cd test# 创建并编辑服务器文件$ vim server.php1
登录后复制

由于POST文件上传时最大尺寸收到package_max_length配置项目的限制,默认为2MB,可以调用swoole_server->set传入新值修改尺寸。

由于Swoole底层是全内存的,因此如果设置过大可能会导致大量并发请求,将服务器资源耗尽。

设置计算方法:最大内存占用 = 最大并发请求数量 * package_max_length

当使用CURL发送POST请求时服务器端会超时

CURL在发送较大的POST请求时会首先发送一个100-continue的请求,当收到服务器的回应才会发送实际的POST数据。然后swoole_http_server并不支持100-continue,因此会导致CURL请求超时。解决的办法时关闭CURL的100-continue。

# 创建应用$ mkdir test && cd test# 创建并编辑服务器文件$ vim server.php2
登录后复制Http\Request->$cookie

HTTP请求携带的COOKIE信息,格式为键值对的关联数组。

Http\Request->$files

HTTP请求携带的文件上传信息,类型为以form表单名称为key键名的二维数组,与PHP原生的$_FILES相同,最大文件尺寸不得超过package_max_length中设置的值,不要使用Swoole\Http\Server处理大文件上传。

# 创建应用$ mkdir test && cd test# 创建并编辑服务器文件$ vim server.php3
登录后复制
# 创建应用$ mkdir test && cd test# 创建并编辑服务器文件$ vim server.php4
登录后复制name表示浏览器上传时传入的文件名称type表示浏览器上传时的MIME类型tmp_name 表示浏览器上传的临时文件,文件名默认以/tmp/swoole.upfile开头。size表示上传文件的尺寸

Swoole1.9.10+版本支持is_uploaded_filemove_uploaded_file函数。当HTTP请求对象$request对象销毁时,会自动删除上传的临时文件。

Http\Request->rawContent()

rawContent表示获取原始的POST包体,用于非application/x-www-form-urlencode格式的HTTP的POST请求。等同于原生PHP的fopen("php://input"),有时服务器不需要解析HTTP的POST请求参数。

Swoole1.7.18+版本增加了http_parse_post配置用于关闭或开启POST数据解析。

# 创建应用$ mkdir test && cd test# 创建并编辑服务器文件$ vim server.php5
登录后复制Http\Request->getData()

getData()方法用于获取完整的HTTP请求报文,包括 Http Header和`HTTP Body消息体。

# 创建应用$ mkdir test && cd test# 创建并编辑服务器文件$ vim server.php6
登录后复制

getData需要Swoole1.10.3或Swoole2.1.2或更高的版本。

响应对象

swoole_http_response响应对象是进程隔离的,不能跨越进程或对象。如果是当前进程中,想使用fd文件描述符保存response响应对象、存储上下文,可使用PHP全局数组变量来保存。

swoole_http_response响应对象,通过调用此对象的方法实现HTTP响应的发送,当响应对象销毁时,如果没有调用end发送HTTP响应,底层会自动执行end方法。不要使用&符号引用$response对象。

# 创建应用$ mkdir test && cd test# 创建并编辑服务器文件$ vim server.php7
登录后复制

HTTP服务器Response响应对象,通过调过此对象的方法,实现HTTP响应发送。当Response对象销毁时,如果未调用则直接调用end方法,不要使用&符号引用$response对象。

Http\Response->header
# 创建应用$ mkdir test && cd test# 创建并编辑服务器文件$ vim server.php8
登录后复制

header方法用于设置HTTP响应的Header头信息,如果设置失败返回false,设置成功则无返回值。

string $key 表示HTTP头的Keystring $value 表示HTTP头的Valuebool $ucwords 表示是否需要对Key进行HTTP约定格式化,默认true会自动格式化。
# 创建应用$ mkdir test && cd test# 创建并编辑服务器文件$ vim server.php9
登录后复制

跨域处理

<?php//创建HTTP服务器对象$host = "0.0.0.0";$port = 9501;$server = new swoole_http_server($host, $port);var_dump($server);//设置服务器运行参数$configs = [];$configs["worker_num"] = 2;//设置Worker工作进程数量$configs["daemonize"] = 0;//设置是否已后台守护进程运行$server->set($configs);//注册监听客户端HTTP请求回调事件$server->on("request", function(swoole_http_request $request, swoole_http_response $response) use($server){    var_dump($request);    var_dump($response);        //获取客户端文件描述符    $fd = $request->fd;    if(!empty($fd)){        //获取连接信息        $clientinfo = $server->getClientInfo($fd);        var_dump($clientinfo);        //获取收包时间        var_dump($clientinfo["last_time"]);    }    //响应客户端HTTP请求    $response->write("success");//向客户端写入响应数据    $response->end();//浏览器中输出结果});//启动服务器$server->start();0
登录后复制Http\Response->cookie

cookie方法用来设置HTTP响应的Cookie信息,方法参数与原生PHP的setcookie函数完全一致。

<?php//创建HTTP服务器对象$host = "0.0.0.0";$port = 9501;$server = new swoole_http_server($host, $port);var_dump($server);//设置服务器运行参数$configs = [];$configs["worker_num"] = 2;//设置Worker工作进程数量$configs["daemonize"] = 0;//设置是否已后台守护进程运行$server->set($configs);//注册监听客户端HTTP请求回调事件$server->on("request", function(swoole_http_request $request, swoole_http_response $response) use($server){    var_dump($request);    var_dump($response);        //获取客户端文件描述符    $fd = $request->fd;    if(!empty($fd)){        //获取连接信息        $clientinfo = $server->getClientInfo($fd);        var_dump($clientinfo);        //获取收包时间        var_dump($clientinfo["last_time"]);    }    //响应客户端HTTP请求    $response->write("success");//向客户端写入响应数据    $response->end();//浏览器中输出结果});//启动服务器$server->start();1
登录后复制

Cookie设置必须在end方法之前方才生效,Swoole底层自动会对$value进行urlencode编码处理,同时允许设置多个相同的$key的Cookie。

Http\Response->status
<?php//创建HTTP服务器对象$host = "0.0.0.0";$port = 9501;$server = new swoole_http_server($host, $port);var_dump($server);//设置服务器运行参数$configs = [];$configs["worker_num"] = 2;//设置Worker工作进程数量$configs["daemonize"] = 0;//设置是否已后台守护进程运行$server->set($configs);//注册监听客户端HTTP请求回调事件$server->on("request", function(swoole_http_request $request, swoole_http_response $response) use($server){    var_dump($request);    var_dump($response);        //获取客户端文件描述符    $fd = $request->fd;    if(!empty($fd)){        //获取连接信息        $clientinfo = $server->getClientInfo($fd);        var_dump($clientinfo);        //获取收包时间        var_dump($clientinfo["last_time"]);    }    //响应客户端HTTP请求    $response->write("success");//向客户端写入响应数据    $response->end();//浏览器中输出结果});//启动服务器$server->start();2
登录后复制

status方法用于发送HTTP状态码,$http_status_code必须是合法的HTTP状态码,如2xx、3xx、4xx、5xx等,若不是在会报错,另外status方法也必须在$response->end()之前执行方才生效。

string $url表示跳转的新地址会作为HTTP Header头中的Location选项进行发送int $http_code 表示状态码,默认为302临时跳转,传入301表示永久跳转。Http\Response->redirect

redirect方法适用于Swoole2.2.0+版本,用于发送HTTP跳转,调用后会自动执行end方法并发送结束响应。

<?php//创建HTTP服务器对象$host = "0.0.0.0";$port = 9501;$server = new swoole_http_server($host, $port);var_dump($server);//设置服务器运行参数$configs = [];$configs["worker_num"] = 2;//设置Worker工作进程数量$configs["daemonize"] = 0;//设置是否已后台守护进程运行$server->set($configs);//注册监听客户端HTTP请求回调事件$server->on("request", function(swoole_http_request $request, swoole_http_response $response) use($server){    var_dump($request);    var_dump($response);        //获取客户端文件描述符    $fd = $request->fd;    if(!empty($fd)){        //获取连接信息        $clientinfo = $server->getClientInfo($fd);        var_dump($clientinfo);        //获取收包时间        var_dump($clientinfo["last_time"]);    }    //响应客户端HTTP请求    $response->write("success");//向客户端写入响应数据    $response->end();//浏览器中输出结果});//启动服务器$server->start();3
登录后复制

例如

<?php//创建HTTP服务器对象$host = "0.0.0.0";$port = 9501;$server = new swoole_http_server($host, $port);var_dump($server);//设置服务器运行参数$configs = [];$configs["worker_num"] = 2;//设置Worker工作进程数量$configs["daemonize"] = 0;//设置是否已后台守护进程运行$server->set($configs);//注册监听客户端HTTP请求回调事件$server->on("request", function(swoole_http_request $request, swoole_http_response $response) use($server){    var_dump($request);    var_dump($response);        //获取客户端文件描述符    $fd = $request->fd;    if(!empty($fd)){        //获取连接信息        $clientinfo = $server->getClientInfo($fd);        var_dump($clientinfo);        //获取收包时间        var_dump($clientinfo["last_time"]);    }    //响应客户端HTTP请求    $response->write("success");//向客户端写入响应数据    $response->end();//浏览器中输出结果});//启动服务器$server->start();4
登录后复制Http\Response->write

write方法用于启用HTTP的chunk分段以向浏览器发送相应的内容,使用write分段发送数据后end方法将不再接收任何参数,调用end方法后会发送一个长度为0的分段chunk表示数据传输完毕。

<?php//创建HTTP服务器对象$host = "0.0.0.0";$port = 9501;$server = new swoole_http_server($host, $port);var_dump($server);//设置服务器运行参数$configs = [];$configs["worker_num"] = 2;//设置Worker工作进程数量$configs["daemonize"] = 0;//设置是否已后台守护进程运行$server->set($configs);//注册监听客户端HTTP请求回调事件$server->on("request", function(swoole_http_request $request, swoole_http_response $response) use($server){    var_dump($request);    var_dump($response);        //获取客户端文件描述符    $fd = $request->fd;    if(!empty($fd)){        //获取连接信息        $clientinfo = $server->getClientInfo($fd);        var_dump($clientinfo);        //获取收包时间        var_dump($clientinfo["last_time"]);    }    //响应客户端HTTP请求    $response->write("success");//向客户端写入响应数据    $response->end();//浏览器中输出结果});//启动服务器$server->start();5
登录后复制

参数$data表示要发送的数据内容,最大长度不得超过2MB,受buffer_output_size配置项控制。

Http\Response->sendfile

sendfile用于发送文件到浏览器

<?php//创建HTTP服务器对象$host = "0.0.0.0";$port = 9501;$server = new swoole_http_server($host, $port);var_dump($server);//设置服务器运行参数$configs = [];$configs["worker_num"] = 2;//设置Worker工作进程数量$configs["daemonize"] = 0;//设置是否已后台守护进程运行$server->set($configs);//注册监听客户端HTTP请求回调事件$server->on("request", function(swoole_http_request $request, swoole_http_response $response) use($server){    var_dump($request);    var_dump($response);        //获取客户端文件描述符    $fd = $request->fd;    if(!empty($fd)){        //获取连接信息        $clientinfo = $server->getClientInfo($fd);        var_dump($clientinfo);        //获取收包时间        var_dump($clientinfo["last_time"]);    }    //响应客户端HTTP请求    $response->write("success");//向客户端写入响应数据    $response->end();//浏览器中输出结果});//启动服务器$server->start();6
登录后复制string $filename 表示要发送的文件名称,文件不存在或没有访问权限则会发送失败。int $offset 表示上传文件的偏移量,可以指定从文件在中间部分开始传输数据,用于断点续传,适用于Swoole1.9.11+。int $length 表示发送数据的尺寸,默认为整个文件的尺寸,适用于Swoole1.9.11+。
<?php//创建HTTP服务器对象$host = "0.0.0.0";$port = 9501;$server = new swoole_http_server($host, $port);var_dump($server);//设置服务器运行参数$configs = [];$configs["worker_num"] = 2;//设置Worker工作进程数量$configs["daemonize"] = 0;//设置是否已后台守护进程运行$server->set($configs);//注册监听客户端HTTP请求回调事件$server->on("request", function(swoole_http_request $request, swoole_http_response $response) use($server){    var_dump($request);    var_dump($response);        //获取客户端文件描述符    $fd = $request->fd;    if(!empty($fd)){        //获取连接信息        $clientinfo = $server->getClientInfo($fd);        var_dump($clientinfo);        //获取收包时间        var_dump($clientinfo["last_time"]);    }    //响应客户端HTTP请求    $response->write("success");//向客户端写入响应数据    $response->end();//浏览器中输出结果});//启动服务器$server->start();7
登录后复制

由于Swoole底层无法推断要发送文件的媒体类型MIME格式,因此需要应用程序指定Content-Type。调用sendfile前不得使用write方法发送HTTP数据段Chunk,调用sendfile后Swoole底层会自动执行end方法,另外sendfile不支持gzip压缩。

Http\Response->end

end方法用于发送HTTP响应体,并结束请求处理。

<?php//创建HTTP服务器对象$host = "0.0.0.0";$port = 9501;$server = new swoole_http_server($host, $port);var_dump($server);//设置服务器运行参数$configs = [];$configs["worker_num"] = 2;//设置Worker工作进程数量$configs["daemonize"] = 0;//设置是否已后台守护进程运行$server->set($configs);//注册监听客户端HTTP请求回调事件$server->on("request", function(swoole_http_request $request, swoole_http_response $response) use($server){    var_dump($request);    var_dump($response);        //获取客户端文件描述符    $fd = $request->fd;    if(!empty($fd)){        //获取连接信息        $clientinfo = $server->getClientInfo($fd);        var_dump($clientinfo);        //获取收包时间        var_dump($clientinfo["last_time"]);    }    //响应客户端HTTP请求    $response->write("success");//向客户端写入响应数据    $response->end();//浏览器中输出结果});//启动服务器$server->start();8
登录后复制

end方法只能调用一次,如果需要分多次向客户端发送数据下需使用write方法,send操作后将会向客户端浏览器发送HTML内容。如果客户端开启了KeepAlive连接会保持,服务器会等待下一次请求。如果没有开启KeepAlive服务器将会切断连接。

Http\Response->detach

detach表示分离响应对应,调用后$response对象销毁时将不会自动执行end方法,一般detach会与Http\Response::create以及Server::send配合使用,适用于Swoole2.2.0+版本。

<?php//创建HTTP服务器对象$host = "0.0.0.0";$port = 9501;$server = new swoole_http_server($host, $port);var_dump($server);//设置服务器运行参数$configs = [];$configs["worker_num"] = 2;//设置Worker工作进程数量$configs["daemonize"] = 0;//设置是否已后台守护进程运行$server->set($configs);//注册监听客户端HTTP请求回调事件$server->on("request", function(swoole_http_request $request, swoole_http_response $response) use($server){    var_dump($request);    var_dump($response);        //获取客户端文件描述符    $fd = $request->fd;    if(!empty($fd)){        //获取连接信息        $clientinfo = $server->getClientInfo($fd);        var_dump($clientinfo);        //获取收包时间        var_dump($clientinfo["last_time"]);    }    //响应客户端HTTP请求    $response->write("success");//向客户端写入响应数据    $response->end();//浏览器中输出结果});//启动服务器$server->start();9
登录后复制

detach方法操作后,若客户端已经完成响应则会返回true,否则返回false

detach应用于跨进程响应

在某些情况下需要在Task任务进程中对客户端发出响应,此时可以利用detach方法使$response对象独立,如此一来在Task任务进程中就可以重新构建$response对象以发起HTTP请求响应。

# 使用PHP-CLI运行服务器脚本$ php server.php# 使用CURL向HTTP服务器发送请求测试$ curl 127.0.0.1:95010
登录后复制

detach方法应用于发送任意内容

在某些特殊场景下,需要对客户端发送特殊的响应内容,Http\Response对象自带的end方法无法满足需求,可以使用detach方法分离响应对象,然后自行组包并使用Server::send方法发送数据。

# 使用PHP-CLI运行服务器脚本$ php server.php# 使用CURL向HTTP服务器发送请求测试$ curl 127.0.0.1:95011
登录后复制

Http\Response::create

create静态方法用于构造新的Http\Response响应对象,使用前必须调用detach方法将旧有$response对象分离,否则 可能会造成同一个请求发送两次响应内容。

# 使用PHP-CLI运行服务器脚本$ php server.php# 使用CURL向HTTP服务器发送请求测试$ curl 127.0.0.1:95012
登录后复制

create静态方法的参数$fd表示需要绑定连接的文件描述符,调用Http\Response对象的end方法和write方法时会向此连接发送数据。如果调用成功则返回一个新的Http\Response对象,否则失败返回false,适用于Swoole2.2.0+版本。


注册事件回调函数

Http\Server注册事件回调函数于Http\Server->on相同,不同之处在于HTTP\Server->on不接受onConnectonReceive回调设置,Http\Server->on会额外接受一种新的事务类型onRequest

onRequest 事件

onRequest事件适用于Swoole1.7.7+版本,当服务器收到一个完整的HTTP请求后会调用onRequest函数。

# 使用PHP-CLI运行服务器脚本$ php server.php# 使用CURL向HTTP服务器发送请求测试$ curl 127.0.0.1:95013
登录后复制

onRequest回调函数共有两个参数

swoole_http_requst $request HTTP请求信息对象,包含了Header/GET/POST/Cookie等信息。swoole_http_response $response HTTP响应信息对象,支持Cookie/Header/Status等HTTP操作。

onRequest回调函数返回时会销毁$request$response对象,如果未执行$response->end()操作,Swoole底层会自动执行一次$response->end("")

$request$response对象在传递给其它函数时,是不需要添加&取地址的引用符号的,传递后引用计数会增加,当onRequest退出时并不会被销毁。

案例

# 使用PHP-CLI运行服务器脚本$ php server.php# 使用CURL向HTTP服务器发送请求测试$ curl 127.0.0.1:95014
登录后复制登录后复制登录后复制登录后复制登录后复制
# 使用PHP-CLI运行服务器脚本$ php server.php# 使用CURL向HTTP服务器发送请求测试$ curl 127.0.0.1:95015
登录后复制
# 使用PHP-CLI运行服务器脚本$ php server.php# 使用CURL向HTTP服务器发送请求测试$ curl 127.0.0.1:95016
登录后复制

获取动态请求的参数

# 使用PHP-CLI运行服务器脚本$ php server.php# 使用CURL向HTTP服务器发送请求测试$ curl 127.0.0.1:95014
登录后复制登录后复制登录后复制登录后复制登录后复制
# 使用PHP-CLI运行服务器脚本$ php server.php# 使用CURL向HTTP服务器发送请求测试$ curl 127.0.0.1:95018
登录后复制

测试带参数的请求

# 使用PHP-CLI运行服务器脚本$ php server.php# 使用CURL向HTTP服务器发送请求测试$ curl 127.0.0.1:95019
登录后复制

观察请求参数的输出

var_dump($server);0
登录后复制

静态文件处理

var_dump($server);1
登录后复制
var_dump($server);2
登录后复制
# 使用PHP-CLI运行服务器脚本$ php server.php# 使用CURL向HTTP服务器发送请求测试$ curl 127.0.0.1:95014
登录后复制登录后复制登录后复制登录后复制登录后复制
var_dump($server);4
登录后复制

发送请求,浏览器访问127.0.0.1:9501/test.jpeg,查看图片。

面向对象

# 使用PHP-CLI运行服务器脚本$ php server.php# 使用CURL向HTTP服务器发送请求测试$ curl 127.0.0.1:95014
登录后复制登录后复制登录后复制登录后复制登录后复制
var_dump($server);6
登录后复制

压力测试

使用Apache Bench工具进行压力测试可以发现,swoole_http_server远超过PHP-FPM、Golang自带的HTTP服务器、Node.js自带的HTTP服务器,性能接近Nginx的静态文件处理。

Swoole的http server与PHP-FPM的性能对比

安装Apache的压测工作ab

var_dump($server);7
登录后复制

使用100个客户端跑1000次,平均每个客户端10个请求。

var_dump($server);8
登录后复制

观察可以发现QPS可以达到 Requests per second: 2084.98 [#/sec] (mean)

HTTP SERVER 配置选项

swoole_server::set()用于设置swoole_server运行时的各项参数化。

var_dump($server);9
登录后复制

配置HTTP SERVER参数后测试并发

# 使用PHP-CLI运行服务器脚本$ php server.php# 使用CURL向HTTP服务器发送请求测试$ curl 127.0.0.1:95014
登录后复制登录后复制登录后复制登录后复制登录后复制
object(Swoole\Connection\Iterator)#2 (0) {  ["host"]=>string(7) "0.0.0.0"  ["port"]=>int(9501)  ["type"]=>int(1)  ["mode"]=>int(2)  ["ports"]=>  array(1) {    [0]=>    object(Swoole\Server\Port)#3 (16) {      ["onConnect":"Swoole\Server\Port":private]=>NULL      ["onReceive":"Swoole\Server\Port":private]=>NULL      ["onClose":"Swoole\Server\Port":private]=>NULL      ["onPacket":"Swoole\Server\Port":private]=>NULL      ["onBufferFull":"Swoole\Server\Port":private]=>NULL      ["onBufferEmpty":"Swoole\Server\Port":private]=>NULL      ["onRequest":"Swoole\Server\Port":private]=>NULL      ["onHandShake":"Swoole\Server\Port":private]=>NULL      ["onOpen":"Swoole\Server\Port":private]=>NULL      ["onMessage":"Swoole\Server\Port":private]=>NULL      ["host"]=>string(7) "0.0.0.0"      ["port"]=>int(9501)      ["type"]=>int(1)      ["sock"]=>int(4)      ["setting"]=>NULL      ["connections"]=>object(Swoole\Connection\Iterator)#4 (0) {      }    }  }  ["master_pid"]=>int(0)  ["manager_pid"]=>int(0)  ["worker_id"]=>int(-1)  ["taskworker"]=>bool(false)  ["worker_pid"]=>int(0)  ["onRequest":"Swoole\Http\Server":private]=>NULL  ["onHandshake":"Swoole\Http\Server":private]=>NULL}1
登录后复制

查看进程

object(Swoole\Connection\Iterator)#2 (0) {  ["host"]=>string(7) "0.0.0.0"  ["port"]=>int(9501)  ["type"]=>int(1)  ["mode"]=>int(2)  ["ports"]=>  array(1) {    [0]=>    object(Swoole\Server\Port)#3 (16) {      ["onConnect":"Swoole\Server\Port":private]=>NULL      ["onReceive":"Swoole\Server\Port":private]=>NULL      ["onClose":"Swoole\Server\Port":private]=>NULL      ["onPacket":"Swoole\Server\Port":private]=>NULL      ["onBufferFull":"Swoole\Server\Port":private]=>NULL      ["onBufferEmpty":"Swoole\Server\Port":private]=>NULL      ["onRequest":"Swoole\Server\Port":private]=>NULL      ["onHandShake":"Swoole\Server\Port":private]=>NULL      ["onOpen":"Swoole\Server\Port":private]=>NULL      ["onMessage":"Swoole\Server\Port":private]=>NULL      ["host"]=>string(7) "0.0.0.0"      ["port"]=>int(9501)      ["type"]=>int(1)      ["sock"]=>int(4)      ["setting"]=>NULL      ["connections"]=>object(Swoole\Connection\Iterator)#4 (0) {      }    }  }  ["master_pid"]=>int(0)  ["manager_pid"]=>int(0)  ["worker_id"]=>int(-1)  ["taskworker"]=>bool(false)  ["worker_pid"]=>int(0)  ["onRequest":"Swoole\Http\Server":private]=>NULL  ["onHandshake":"Swoole\Http\Server":private]=>NULL}2
登录后复制

查看后台守护进程

object(Swoole\Connection\Iterator)#2 (0) {  ["host"]=>string(7) "0.0.0.0"  ["port"]=>int(9501)  ["type"]=>int(1)  ["mode"]=>int(2)  ["ports"]=>  array(1) {    [0]=>    object(Swoole\Server\Port)#3 (16) {      ["onConnect":"Swoole\Server\Port":private]=>NULL      ["onReceive":"Swoole\Server\Port":private]=>NULL      ["onClose":"Swoole\Server\Port":private]=>NULL      ["onPacket":"Swoole\Server\Port":private]=>NULL      ["onBufferFull":"Swoole\Server\Port":private]=>NULL      ["onBufferEmpty":"Swoole\Server\Port":private]=>NULL      ["onRequest":"Swoole\Server\Port":private]=>NULL      ["onHandShake":"Swoole\Server\Port":private]=>NULL      ["onOpen":"Swoole\Server\Port":private]=>NULL      ["onMessage":"Swoole\Server\Port":private]=>NULL      ["host"]=>string(7) "0.0.0.0"      ["port"]=>int(9501)      ["type"]=>int(1)      ["sock"]=>int(4)      ["setting"]=>NULL      ["connections"]=>object(Swoole\Connection\Iterator)#4 (0) {      }    }  }  ["master_pid"]=>int(0)  ["manager_pid"]=>int(0)  ["worker_id"]=>int(-1)  ["taskworker"]=>bool(false)  ["worker_pid"]=>int(0)  ["onRequest":"Swoole\Http\Server":private]=>NULL  ["onHandshake":"Swoole\Http\Server":private]=>NULL}3
登录后复制

杀死后台进程

object(Swoole\Connection\Iterator)#2 (0) {  ["host"]=>string(7) "0.0.0.0"  ["port"]=>int(9501)  ["type"]=>int(1)  ["mode"]=>int(2)  ["ports"]=>  array(1) {    [0]=>    object(Swoole\Server\Port)#3 (16) {      ["onConnect":"Swoole\Server\Port":private]=>NULL      ["onReceive":"Swoole\Server\Port":private]=>NULL      ["onClose":"Swoole\Server\Port":private]=>NULL      ["onPacket":"Swoole\Server\Port":private]=>NULL      ["onBufferFull":"Swoole\Server\Port":private]=>NULL      ["onBufferEmpty":"Swoole\Server\Port":private]=>NULL      ["onRequest":"Swoole\Server\Port":private]=>NULL      ["onHandShake":"Swoole\Server\Port":private]=>NULL      ["onOpen":"Swoole\Server\Port":private]=>NULL      ["onMessage":"Swoole\Server\Port":private]=>NULL      ["host"]=>string(7) "0.0.0.0"      ["port"]=>int(9501)      ["type"]=>int(1)      ["sock"]=>int(4)      ["setting"]=>NULL      ["connections"]=>object(Swoole\Connection\Iterator)#4 (0) {      }    }  }  ["master_pid"]=>int(0)  ["manager_pid"]=>int(0)  ["worker_id"]=>int(-1)  ["taskworker"]=>bool(false)  ["worker_pid"]=>int(0)  ["onRequest":"Swoole\Http\Server":private]=>NULL  ["onHandshake":"Swoole\Http\Server":private]=>NULL}4
登录后复制

压测

object(Swoole\Connection\Iterator)#2 (0) {  ["host"]=>string(7) "0.0.0.0"  ["port"]=>int(9501)  ["type"]=>int(1)  ["mode"]=>int(2)  ["ports"]=>  array(1) {    [0]=>    object(Swoole\Server\Port)#3 (16) {      ["onConnect":"Swoole\Server\Port":private]=>NULL      ["onReceive":"Swoole\Server\Port":private]=>NULL      ["onClose":"Swoole\Server\Port":private]=>NULL      ["onPacket":"Swoole\Server\Port":private]=>NULL      ["onBufferFull":"Swoole\Server\Port":private]=>NULL      ["onBufferEmpty":"Swoole\Server\Port":private]=>NULL      ["onRequest":"Swoole\Server\Port":private]=>NULL      ["onHandShake":"Swoole\Server\Port":private]=>NULL      ["onOpen":"Swoole\Server\Port":private]=>NULL      ["onMessage":"Swoole\Server\Port":private]=>NULL      ["host"]=>string(7) "0.0.0.0"      ["port"]=>int(9501)      ["type"]=>int(1)      ["sock"]=>int(4)      ["setting"]=>NULL      ["connections"]=>object(Swoole\Connection\Iterator)#4 (0) {      }    }  }  ["master_pid"]=>int(0)  ["manager_pid"]=>int(0)  ["worker_id"]=>int(-1)  ["taskworker"]=>bool(false)  ["worker_pid"]=>int(0)  ["onRequest":"Swoole\Http\Server":private]=>NULL  ["onHandshake":"Swoole\Http\Server":private]=>NULL}5
登录后复制

观察可以发现QPC为Requests per second: 4417.72 [#/sec] (mean)

性能优化

使用swoole_http_server服务后,若发现服务的请求耗时监控毛刺十分严重,接口耗时波动较大的情况,可以观察下服务的响应包response的大小,若响应包超过1~2M甚至更大,则可判断是由于包太多而且很大导致服务响应波动较大。

为什么响应包惠导致相应的时间波动呢?主要有两个方面的影响,第一是响应包太大导致Swoole之间进程通信更加耗时并占用更多资源。第二是响应包太大导致Swoole的Reactor线程发包更加耗时。

以上就是一起看看Swoole HTTP的详细内容,更多请关注9543建站博客其它相关文章!

9543建站博客
一个专注于网站开发、微信开发的技术类纯净博客。
作者头像
admin创始人

肥猫,知名SEO博客站长,14年SEO经验。

上一篇:wampserver php设置密码
下一篇:详解ThinkPHP5查询数据和打印的方法

发表评论

关闭广告
关闭广告