1
0
mirror of https://gitee.com/zhc02/timely_service.git synced 2025-07-16 21:16:13 +08:00
2019-10-30 23:42:52 +08:00

483 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

ThinkPHP 5.1 Swoole 扩展
===============
## 安装
首先按照Swoole官网说明安装swoole扩展然后使用
~~~
composer require topthink/think-swoole
~~~
安装swoole扩展。
## 使用方法
### HttpServer
直接在命令行下启动服务端。
~~~
php think swoole
~~~
启动完成后会在0.0.0.0:9501启动一个HTTP Server可以直接访问当前的应用。
swoole的参数可以在应用配置目录下的swoole.php里面配置具体参考配置文件内容
如果需要使用守护进程方式运行,可以使用
~~~
php think swoole -d
~~~
或者在swoole.php文件中设置
~~~
'daemonize' => true
~~~
注意由于onWorkerStart运行的时候没有HTTP_HOST因此最好在应用配置文件中设置app_host
支持的操作包括
~~~
php think swoole [start|stop|reload|restart]
~~~
### Server
可以支持直接启动一个Swoole server
~~~
php think swoole:server
~~~
会在0.0.0.0:9508启动一个Websocket服务。
如果需要自定义参数可以在config/swoole_server.php中进行配置包括
配置参数 | 描述
--- | ---
type| 服务类型
host | 监听地址
port | 监听端口
mode | 运行模式
sock_type | Socket type
并且支持swoole所有的参数。
也支持使用闭包方式定义相关事件回调。
~~~
return [
// 扩展自身配置
'host' => '0.0.0.0', // 监听地址
'port' => 9501, // 监听端口
'type' => 'socket', // 服务类型 支持 socket http server
'mode' => SWOOLE_PROCESS,
'sock_type' => SWOOLE_SOCK_TCP,
// 可以支持swoole的所有配置参数
'daemonize' => false,
// 事件回调定义
'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";
},
];
~~~
也可以使用自定义的服务类
~~~
<?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 $option = [
'worker_num'=> 4,
'daemonize' => true,
'backlog' => 128
];
public function onReceive($server, $fd, $from_id, $data)
{
$server->send($fd, 'Swoole: '.$data);
}
}
~~~
支持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
~~~
支持reload|restart|stop|status 操作
~~~
php think swoole:server reload
~~~
### 配置信息详解
swoole.php
```php
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use think\facade\Env;
// +----------------------------------------------------------------------
// | Swoole设置 php think swoole命令行下有效
// +----------------------------------------------------------------------
return [
// 扩展自身配置
'host' => '0.0.0.0', // 监听地址
'port' => 9501, // 监听端口
'mode' => '', // 运行模式 默认为SWOOLE_PROCESS
'sock_type' => '', // sock type 默认为SWOOLE_SOCK_TCP
'app_path' => '', // 应用地址 如果开启了 'daemonize'=>true 必须设置(使用绝对路径)
'file_monitor' => false, // 是否开启PHP文件更改监控调试模式下自动开启
'file_monitor_interval' => 2, // 文件变化监控检测时间间隔(秒)
'file_monitor_path' => [], // 文件监控目录 默认监控application和config目录
// 可以支持swoole的所有配置参数
'pid_file' => Env::get('runtime_path') . 'swoole.pid',//swoole主进程pid存放文件
'log_file' => Env::get('runtime_path') . 'swoole.log',//swoole日志存放文件
'document_root' => Env::get('root_path') . 'public',//设置静态服务根目录
'enable_static_handler' => true,//是否由SWOOLE底层自动处理静态文件TRUE表示SWOOLE判断是否存在静态文件如果存在则直接返回静态文件信息
'timer' => true,//是否开启系统定时器
'interval' => 500,//系统定时器 时间间隔
'task_worker_num' => 1,//swoole 任务工作进程数量
'user' =>'www',//表示swoole worker进程所属的管理员名称如果要绑定1024以下端口则必须要求具有root权限如果设置了该项则除主进程外的所有进程都运行于指定用户下
];
```
timer.php
```php
<?php
/**
* Created by PhpStorm.
* User: xavier
* Date: 2018/8/15
* Time: 下午2:14
* 秒 分 时 日 月 星期几
* crontab 格式 * * * * * * => "类"
* *中间一个空格
* 系统定时任务需要在swoole.php中开启
* 自定义定时器不受其影响
*/
return [
'*/5 * * * * *' => '\\app\\lib\\Timer',//时间配置方式参考crontab主要是增加秒其他和crontab一致对应Value为定时器接口实现类的完整命名空间包含类名
];
```
### 异步任务投递
1.异步任务接口实现
```php
<?php
/**
* Created by PhpStorm.
* User: xavier
* Date: 2018/8/19
* Time: 下午8:28
*/
namespace app\lib;
use think\swoole\template\Task;
class TestTask extends Task
{
public function _initialize(...$arg)
{
// TODO: Implement _initialize() method.
}
public function run($serv, $task_id, $fromWorkerId)
{
// TODO: Implement run() method.
}
}
```
2.异步任务投递在控制器中的使用
```php
<?php
namespace app\index\controller;
use think\swoole\facade\Task;
class Index
{
public function hello()
{
//投递任务模板
$task=new \app\lib\TestTask();
Task::async($task);
//异步任务投递闭包
Task::async(function ($serv, $task_id, $data) {
$i = 0;
while ($i < 10) {
$i++;
echo $i;
sleep(1);
}
});
return 'hello' ;
}
}
```
### 定时器的使用
定时器分为系统定时器和自定义定时器系统定时器需要在配置文件timer.php中进行配置会根据配置由系统自动处理
1. 定时器接口的实现
```php
<?php
namespace app\lib;
/**
* Created by PhpStorm.
* User: xavier
* Date: 2018/8/19
* Time: 下午8:01
*/
use think\swoole\template\Timer;
class TestTimer extends Timer
{
public function _initialize(...$arg)
{
// TODO: Implement _initialize() method.
}
public function run()
{
$i=0;
// TODO: Implement run() method.
while($i<10){
var_dump(12);
$i++;
sleep(1);
}
}
}
```
2. 系统定时器的使用
参考上面timer.php的配置方法系统定时器任务会自动进行异步投递因此必须在swoole.php中配置task_worker_num系统会自动调用非繁忙的task worker进行任务处理
3. 自定义定时器
自定义定时器可以执行闭包和Timer接口实现类。注意如非必要请勿在控制器等重复调用的地方使用tick方法因为每次请求都会创建新的定时器。如果必须创建请注意定时器回收。
```php
<?php
namespace app\index\controller;
use think\swoole\facade\Task;
use think\swoole\facade\Timer;
class Index
{
public function hello()
{
//闭包方式使用定时器
Timer::tick(1000,function(){
var_dump(1);
});
//使用定时器模板
$t=new \app\lib\TestTimer();
Timer::tick(1000,$t);
return 'hello,' ;
}
}
```
### 获取Server
获取Swoole实例对象
```php
<?php
namespace app\index\controller;
use think\Container;
class Index
{
public function hello()
{
$swoole=Container::get('swoole');//获取swoole实例
}
}
```
### 自定义服务启动
如果需要在Swoole启动的时候创建一些服务可以按照如下方法进行自定义
在swoole.php中配置配置
//闭包方式
```php
'wokerstart'=>function($server, $worker_id){
//如果只在一个进程处理 则可以这样
if (0==$worker_id){
//这样只会在第一个woker进程处理
}
}
```
如果需要实现Workerstart的接口可以这样实现
```php
<?php
/**
* Created by PhpStorm.
* User: xavier
* Date: 2018/8/23
* Time: 下午5:27
* Email:499873958@qq.com
*/
namespace app\lib;
use think\swoole\template\WorkerStart as Woker;
class WorkStart extends Woker
{
public function _initialize($server, $worker_id)
{
// TODO: Implement _initialize() method.
}
public function run()
{
var_dump(1);
}
}
```
配置文件
```php
'wokerstart'=>'\\app\\lib\\WorkStart'
```
### Websocket支持
需要在swoole.php修改
```a
'server_type' => 'websocket', // 服务类型 支持 http websocket
```
由于Swoole\WebSocket\Server继承于Swoole\Http\Server顾Http服务具有的功能Websocket也具有。如果采用如下websocket服务
通讯数据格式已经固定,如采用自定义数据结构,请采用自定义服务
WebSocket通讯数据结构
```json
{
"event":"",//事件名称
"url":"",//目标地址
"arguments":{//客户端投递数据
"post":[],//post数据
"get":[],//get数据
"cookie":[],//cookie数据
}
}
```
详解
* event 该参数为事件名称,用于触发客户端事件,即接收服务器推送数据处理指定任务
* url该为访问的目标地址相当于http模式下http://xxx.com/url
* arguments 客户端投递的所有数据如果希望可以按照原来POST,GET的方式处理数据可以提交时按照上述方式提交会自动处理
客户端JS可以参考example里websocketclient.js
服务端发送数据
```php
use think\swoole\WebSocketFrame;
$client=WebSocketFrame::getInstance();
//发送数据给当前请求的客户端
$client->pushToClient([]);//参数为数组,字符串,数字
//发送给所有客户端
$client->pushToClients([]);//参数为数组,字符串,数字
$client->getArgs();//获取arguments里的参数
$client->getData();//获取客户端发送给的所有数据
$client->getServer();//获取当前server
$client->getFrame();//获取当前客户端给发送的原始数据
```
新增队列支持
think-queue是一个非常好用的队列服务xavier-swoole的队列服务依赖于think-queue使用方法和think-queue保持一致
主要增加如下功能
1. 采用多进程模式运行或采用Task异步执行
2. 可以指定同时消耗队列任务的进程数量
3. Task模式和Server共享Task进程充分利用资源
4. Process模式采用进程模式各个任务之间相互隔离执行一定次数后重启进程防止内存泄露
如果任务较多且复杂推荐采用Process模式
```php
'queue_type'=>'task',//task or process
'queue'=>[
"Index"=>[
"delay"=>0,//延迟时间
"sleep"=>3,//休息时间
"maxTries"=>0,//重试次数
"nums"=>2//进程数量
],
]
```