TP5.1Swoole 教程-快速上手指南
2022年04月22日10:52:41更新
本篇内容主要讲述了最新的think-swoole
扩展的使用。
本指南的目的不是为了让你掌握
Swoole
开发,而且帮助你使用think-swoole
快速部署ThinkPHP5.1
应用到Swoole
的HttpServer
,以及使用快速启动Swoole
服务,如果你需要了解Swoole
的具体用法和原理,请参考Swoole官方文档,说的比较详细了。
本文的内容并不适用于ThinkPHP
5.0
及以下版本(5.0
或者5.1.18
之前版本的Swoole
的支持可以参考这里) !
安装Swoole
首先按照Swoole官网说明安装swoole
扩展,推荐新手可以直接使用
sudo pecl install swoole
会安装最新的稳定版(截至本文发布最新版本是4.0.3
版本),如果你需要安装某个版本,例如,如果你不需要使用协程功能,只需要安装1.*
版本,可以使用:
sudo pecl install swoole-1.10.5
可以在这里查看所有的swoole版本。
安装完成后,你可能需要在你的php.ini
中添加:
extension=swoole
最后,请确认你的php的swoole
模块已经支持。
php -m
如果你能够看到swoole
在列表中,说明swoole
模块已经正常安装了。
如果安装过程中遇到问题,根据提示进行操作即可,或者自行百度,这里不再赘述。
安装think-swoole
接下来第二步是安装think-swoole
扩展,本文中的内容以最新版本的扩展为例(可能部分功能老版本的扩展不支持),如果你的扩展版本较旧,请更新框架或者扩展版本。
think-swoole
是ThinkPHP官方发布的swoole
扩展,从2.0+
版本完善了对Swoole
的支持。
ThinkPHP5+
的扩展都是基于Composer
安装的,所以确认你已经安装了Composer
。
如果你已经有自己的ThinkPHP5.1
项目了,为了使用最新的特性,建议更新到最新版本(V5.1.20+
),然后可以在应用根目录下使用下面命令安装扩展。
composer require topthink/think-swoole=2.0.*
会安装最新的稳定版本的think-swoole
扩展。
如果你是第一次使用ThinkPHP5.1
,那么可以先创建一个初始项目,然后再安装扩展,依次执行下面的命令即可。
composer create-project topthink/think tp
cd tp
composer require topthink/think-swoole
如果你的composer不是最新版本的,请执行命令更新:composer self-update
如果你的composer镜像不是国内的,请执行命令切换阿里composer镜像:
所有项目都会使用该镜像地址:
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
取消配置:
composer config -g --unset repos.packagist
项目配置
仅修改当前工程配置,仅当前工程可使用该镜像地址:
composer config repo.packagist composer https://mirrors.aliyun.com/composer/
取消配置:
composer config --unset repos.packagist
调试
composer 命令增加 -vvv 可输出详细的信息,命令如下:
composer -vvv require alibabacloud/sdk
启动Swoole HTTP
服务
第一个场景(也是该扩展最重要的一个场景),毕竟大部分使用think-swoole
扩展的用户都是在使用ThinkPHP开发网站或者项目,使用think-swoole
扩展可以让你的产品直接部署到Swoole
上,并且享受下面的优势:
- 无需对代码进行改造就能带来性能的数倍提升;
- 可以在
Apache
/Nginx
等传统WEB服务器和Swoole
之间切换部署;
简单点说,就是你可以在传统模式下开发你的应用,然后直接部署到
Swoole
上运行,但无需针对Swoole
写任何的处理代码。
安装完扩展后,你什么都不需要做,最简单的就是直接在命令行(应用根目录下面)下执行:
php think swoole
启动成功后会显示
Starting swoole http server...
Swoole http server started: <http://0.0.0.0:9501>
You can exit with `CTRL-C`
可以看到已经在0.0.0.0:9501
启动一个HTTP Server服务端,下面我们可以直接访问当前的应用。
http://localhost:9501
如果你之前已经有运行一个80端口的WEB服务,那么可以比较下两个页面的区别。
如果你是刚创建的项目,那么可以直接看到ThinkPHP5.1
的欢迎页面。
否则你会看到你的项目首页。
配置文件
HTTPServer
的参数可以在应用配置目录下的swoole.php
里面配置,该文件会在扩展安装的时候自动生成(如果没有则可以自己创建)。
扩展自带的配置参数主要包括:
配置参数 | 描述 | 默认值 |
---|---|---|
host | 监听地址 | 0.0.0.0 |
port | 监听端口 | 9501 |
mode | 运行模式 | SWOOLE_PROCESS |
sock_type | Socket type | SWOOLE_SOCK_TCP |
app_path | 应用目录(守护进程模式必须设置) | 自动识别 |
ssl | 是否启用https | false |
file_monitor | 是否监控文件更改(V2.0.9+) | false |
file_monitor_interval | 监控文件间隔(秒)(V2.0.9+) | 2 |
file_monitor_path | 监控目录 (V2.0.9+) | 默认监控application和config目录 |
其它的
swoole
参数可以参考官方文档的配置参数,所有swoole
本身支持的配置参数都可以直接在swoole.php
中使用。
守护进程模式
如果需要使用守护进程模式运行,可以使用
php think swoole -d
或者在swoole.php
文件中设置
'daemonize' => true
不过一定要记得,如果启用守护进程模式,必须设置应用目录app_path
(使用绝对路径),否则会出错。
'host' => '0.0.0.0', // 监听地址
'port' => 9501, // 监听端口
'daemonize' => true,
'app_path' => '/home/www/tp/application/',
基本操作
如果要停止服务,可以使用
php think swoole stop
reload
服务
php think swoole reload
stop
服务
php think swoole stop
restart
服务
php think swoole restart
restart
和reload
的区别是,restart
会先stop
然后start
,而reload
则是平滑重启服务,不会中断服务。
如果你需要修改地址和端口,可以修改swoole.php
配置文件
'host' => 'tp5.com', // 监听地址
'port' => 8080, // 监听端口
改完后,需要重启服务才能生效
php think swoole restart
现在可以直接访问
http://tp5.com:8080
如果你需要设置
80
端口,需要root
权限才可以。
如果你安装的是
2.0.12+
版本的扩展,还可以支持在命令行指定地址和端口,例如:
php think swoole -H tp.com -p 9508
如果启动了多个不同端口的服务,reload
、restart
和stop
操作必须也是针对某个端口的才能正确操作,我们以reload
操作为例进行说明。
如果我们需要reload
前面启动的tp.com:9508
服务,下面的指令是错误的
php think swoole reload
可能会出现错误提示:
no swoole http server process running.
必须带上正确的端口号(host
不是必须的)
php think swoole reload -p 9508
然后,你会看到提示信息如下,表示reload
成功:
Reloading swoole http server...
> success
Cookie
和Session
由于Swoole
的特殊性,扩展本身接管了Cookie
类和Session
类的处理,因此不要调用(包括依赖注入)think\Cookie
和think\Session
类,而应该改为think\swoole\Cookie
类和think\swoole\Session
类。但think\facade\Cookie
和think\facade\Session
类的用法是正常的,因此原来的静态方法调用依然可以正常使用。同时,Request
对象的cookie
方法和session
方法也可以正常使用。
关于Swoole
的Session
的用法,这里要特别强调下。
Swoole
是没有Session
的概念,因此所有PHP内置的session
函数都是无效的,think-swoole
扩展单独封装了一个Session
类,和系统的Session
机制无关。
该扩展提供的think\swoole\Session
类是基于swoole_table
和ThinkPHP
缓存的混合解决方案。
每次Session::start()
的时候系统会从swoole_table
或者定义的缓存类型中获取当前用户的Session
数据,而session_id
数据则通过Cookie
获取。并且在当前worker
进程中不会过期,但每次从swoole_table
或者缓存中获取session
的时候则会判断是否过期,session
的有效期还是通过session.php
配置文件的expire
配置参数进行设置。
swoole_table
一个基于共享内存和锁实现的超高性能,并发数据结构。用于解决多进程/多线程数据共享和同步加锁问题。
由于swoole_table
需要事先分配内存大小和字段定义,在swoole.php
配置文件中需要添加定义:
'table' => [
// 定义最大记录数
'size' => 1024,
// 字段类型定义(目前仅支持 string int 和 float类型)
'column' =>[
'data' => ['string',255], // 字符串类型 长度为255个字节
'expire'=> ['int',8], // 整型 长度为8
],
],
swoole_table
分配的内存无法动态扩容和调整字段类型,如果修改则需要重启才能生效。
然后在session.php
配置文件中,添加
'use_swoole_table' => true,
swoole_table
是一个可选方案。我们更建议使用缓存机制来处理Session
,如果你的应用比较大,则应该配置使用redis
之类的缓存机制更加适合,直接在你的cache.php
中定义相关缓存配置即可。
为了避免复杂,swoole的
Session
类不再支持prefix
参数,如果需要区分比如前后台不同session
的需求,可以使用name
参数进行区分。
文件监控
由于Swoole
服务运行过程中PHP文件是常驻内存运行的,这样可以避免重复读取磁盘、重复解释编译PHP,以便达到最高性能。所以更改业务代码后必须手动reload
或者restart
才能生效。
think-swoole
扩展提供了监控文件更新的功能,在检测到相关目录的文件有更新后会自动reload
,从而不需要手动进行reload
操作,方便开发调试。
如果你的应用开启了调试模式,文件监控功能是自动开启的。原则上,在部署模式下不建议开启文件监控,一方面有性能损耗,另外一方面对文件所做的任何修改都需要确认无误才能进行更新部署。如果你确实需要在部署模式下开启文件监控,可以设置如下:
'file_monitor' => true, // 开启文件监控
'file_monitor_interval' => 1, // 文件监控检测的时间间隔
'file_monitor_path' => '', // 文件监控目录 一般不需要设置 默认会监控应用目录和配置目录
事件回调
扩展自带的HTTPServer
包含了onWorkerStart
和onRequest
两个事件回调,你如果需要增加其它的回调事件处理,可以在配置文件中直接添加:
'WorkerStop' => function($server, $worker_id) {
},
'WorkerError' => function($serv, $worker_id, $worker_pid, $exit_code, $signal) {
},
关于事件回调的具体用法,可以参考swoole
官方文档。
如果不熟悉内部机制,请勿随意替换和更改
onWorkerStart
和onRequest
事件回调,会导致不可预期的结果。
Nginx+Swoole
部署
可以使用Nginx
请求转发到Swoole
的方式部署,充分发挥Nginx
的配置优势和强大功能。
server {
listen 80;
root /var/www/tp/public/;
server_name 127.0.0.1;
index index.html index.htm index.php;
location / {
proxy_http_version 1.1;
proxy_set_header Connection "keep-alive";
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.0.1:9501;
}
}
静态资源访问
如果你没有使用Nginx
代理的话,为了确保静态资源的正常访问,请确认下面的参数配置正确:
// 网站根目录位置
'document_root' => Env::get('root_path') . 'public',
// 开启静态资源处理
'enable_static_handler' => true,
使用Chrome浏览器会自动请求一次
favicon.ico
,所以确保你的网站根目录下面有存在favicon.ico
文件,否则会产生一次404
请求的错误日志。
HTTPS
和HTTP2
支持
如果需要配置你的HTTP
服务支持HTTPS
,需要增加配置如下:
'ssl' => true,
'ssl_cert_file' => __DIR__.'/ssl.crt',
'ssl_key_file' => __DIR__.'/ssl.key',
记得准确指定你的cert
证书和key
私钥的路径。
使用
SSL
必须在编译swoole
时加入--enable-openssl
选项
如果需要支持HTTP2
协议,则在SSL支持的基础上还需要在编译的时候加入--enable-http2
选项
./configure --enable-openssl --enable-http2
然后在swoole.php
中增加配置
'open_http2_protocol' => true
其它注意事项
为了让你的应用能够顺利的运行在
Swoole
上面,扩展做了大量的底层处理工作,包括让你的请求数据、Cookie
和Session
正常运作。
在
Swoole
下面,不能使用$_GET
、$_POST
、$_REQUEST
、$_SERVER
、$_COOKIE
以及$_SESSION
等原生的PHP用法,只能使用框架提供的类和方法进行获取。
错误的用法:
$name = $_GET['name'];
$name = $_POST['name'];
$name = $_COOKIE['name'];
$name = $_SESSION['name'];
$host = $_SERVER['HTTP_HOST'];
V2.0.11+
版本开始,系统可以支持原生全局变量的获取,但仍然不建议使用。
正确的用法(以下用法都采用了Facade
静态代理类):
$name = Request::get('name');
$name = Request::param('name');
$name = Cookie::get('name');
$name = Session::get('name');
$host = Request::server('http_host');
如果你要获取php://input
内容,必须把原来的代码
file_get_contents('php://input');
改成
Request::getInput();
不过更建议使用
Request::put();
因为可以支持json
数据的自动解析而不需要手动进行json_decode
。
由于onWorkerStart
运行的时候还没有HTTP_HOST
,因此最好在应用配置文件config/app.php
中设置app_host
。
请不要调用PHP原生的header
方法,使用Response
对象的header
方法替代。
不要使用PHP原生的session
相关函数,使用Session
类的相关方法。
目前为止,尚有一些功能不够完善(例如文件上传之类),请期待后续版本更新。
快速启动Swoole Server
现在来看第二个场景,通过简单的配置快速启动一个swoole
服务,包括WebSocket
/Http
/Socket
服务。
可以支持直接启动一个Swoole server(需要think-swoole
扩展 2.0.9+
版本)
php think swoole:server
会显示如下信息:
Starting swoole server...
Swoole socket server started: <0.0.0.0:9508>
You can exit with `CTRL-C`
这个时候已经在0.0.0.0:9508
启动一个Websocket
服务。
你可以在浏览器中访问
http://127.0.0.1:9508
会看到类似下面的页面(后面是一串随机数)。
守护进程
如果需要使用守护进程方式运行,可以使用
php think swoole:server -d
或者在swoole.php
文件中设置
'daemonize' => true
配置文件
如果需要自定义参数,可以在config/swoole_server.php
中进行配置,包括:
配置参数 | 描述 | 默认值 |
---|---|---|
type | 服务类型(支持socket、http或者留空) | socket |
host | 监听地址 | 0.0.0.0 |
port | 监听端口 | 9508 |
mode | 运行模式 | SWOOLE_PROCESS |
sock_type | Socket type | SWOOLE_SOCK_TCP |
daemonize | 守护进程 | false |
注意不要和
swoole.php
文件文件混淆,两者的作用完全不同。
并且支持swoole
所有的参数,以及支持使用闭包方式定义相关事件回调。
return [
// 扩展自身配置
'host' => '0.0.0.0', // 监听地址
'port' => 9501, // 监听端口
'type' => 'socket', // 服务类型 支持 socket http或者留空
'mode' => SWOOLE_PROCESS,
'sock_type' => SWOOLE_SOCK_TCP,
// 可以支持swoole的所有配置参数
'daemonize' => false,
'worker_num' => 4,
// 事件回调定义
'onOpen' => function ($server, $request) {
echo "server: handshake success with fd{$request->fd}\n";
},
'onMessage' => function ($server, $frame) {
echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
$server->push($frame->fd, "this is server");
},
'onRequest' => function ($request, $response) {
$response->end("<h1>Hello Swoole. #" . rand(1000, 9999) . "</h1>");
},
'onClose' => function ($ser, $fd) {
echo "client {$fd} closed\n";
},
];
自定义服务类
如果你需要更高级的自定义事件回调,也可以使用自定义的Swoole
服务类。
<?php
namespace app\http;
use think\swoole\Server;
class Swoole extends Server
{
protected $host = '127.0.0.1';
protected $port = 9502;
protected $serverType = 'socket';
protected $mode = SWOOLE_PROCESS;
protected $sockType = SWOOLE_SOCK_TCP;
protected $option = [
'worker_num'=> 4,
'daemonize' => true,
'backlog' => 128
];
public function onReceive($server, $fd, $from_id, $data)
{
$server->send($fd, 'Swoole: '.$data);
}
}
自定义服务类必须继承
think\swoole\Server
类,支持swoole
所有的回调方法定义(回调方法必须是public
类型)。
serverType
属性定义为 socket
或者http
则支持swoole的swoole_websocket_server
和swoole_http_server
然后在swoole_server.php
中增加配置参数:
return [
'swoole_class' => 'app\http\Swoole',
];
定义该参数后,其它配置参数均不再有效。
然后就可以在命令行启动服务端
php think swoole:server
一样可以支持使用守护进程模式运行,
php think swoole:server -d
同样也支持reload
、restart
和stop
操作。
php think swoole:server reload
客户端代码的实现有很多,如果你是使用PHP的话,可以用Swoole\Client
类。
<?php
namespace app\index\controller;
use Swoole\Client;
use think\Controller;
class Test extends Controller
{
public function index() {
$client = new Client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC);
$ret = $client->connect("127.0.0.1", 9501);
if(empty($ret)){
echo 'error!connect to swoole_server failed';
} else {
$client->send('test');
}
}
}
启动多个swoole
服务
你可以通过命令行的指令启动多个不同端口的swoole
服务,例如:
php think swoole:server -p 9800
php think swoole:server -p 9700
如果要分别对不同端口的服务进行stop
操作,务必使用
php think swoole:server stop -p 9800
php think swoole:server stop -p 9700
本文来自博客园,作者:wekyun,转载请注明原文链接:https://www.cnblogs.com/wekyun/articles/15628537.html
原文地址:https://www.kancloud.cn/thinkphp/think-swoole/722895