swooleサーバーの実行中、PHPファイルは常駐メモリ内で実行されるため、ディスクの繰り返し読み取り、PHPの解釈とコンパイルの繰り返しを回避できます。最高のパフォーマンスを実現するには、コードを変更するにはサービスを再起動する必要があります。
think-swoole 拡張機能には、ホット アップデート機能が用意されています。関連ファイルの更新を検出した後、自動的に再起動されます。手動で完了する必要はありません。再起動は、開発やデバッグに便利です。
運用環境では、パフォーマンスの低下を引き起こすため、ファイル監視を開始することはお勧めできません。通常の状況では、変更するファイルは変更する前に確認する必要があります。
#パラメータ 説明 enable ホット アップデートを有効にするかどうか name 監視されるファイルの変更の種類 include ファイルの変更を監視するディレクトリ exclude ディレクトリを除外 websocket 先来一个官方的例子
$server = new Swoole\WebSocket\Server("0.0.0.0", 9501);
$server->on('open', function (Swoole\WebSocket\Server $server, $request) {
echo "server: handshake success with fd{$request->fd}\n";
});
$server->on('message', function (Swoole\WebSocket\Server $server, $frame) {
echo "receive from {$frame->fd}:{$frame->data}\n";
$server->push($frame->fd, "this is server");
});
$server->on('close', function ($ser, $fd) {
echo "client {$fd} closed\n";
});
$server->start(); ログイン後にコピー
开启think-swoole的websocket功能 \config\swoole.php
'websocket' => [
'enable' => true,
], ログイン後にコピー
创建三个事件
php think make:listener SwWsConnect
php think make:listener SwWsClose
php think make:listener SwWsMessage ログイン後にコピー
然后将这三个事件写到到事件监听中,分别有以下2中文件可以修改方式,注意二选一
thinkphp6自带的事件绑定app\event.php
'listen' => [
........
// 监听链接
'swoole.websocket.Connect' => [
\app\listener\SwWsConnect::class
],
//关闭连接
'swoole.websocket.Close' => [
\app\listener\SwWsClose::class
],
//发送消息场景
'swoole.websocket.Message' => [
\app\listener\SwWsMessage::class
]
], ログイン後にコピー
think-swoole事件绑定config\swoole.php
'listen' => [
'connect'=>\app\listener\SwWsConnect::class,
'close'=>\app\listener\SwWsClose::class,
'message'=> \app\listener\SwWsMessage::class
], ログイン後にコピー
怎么选择是保存在config\swoole.php
还是app\event.php
配置中呢?首先我们 我们确定一下我们这个项目中存在有几个实时通讯,
如果只是存在一个实时通讯 个人建议 保存在config\swoole.php
如果是存在多个实时通讯,就保存在app\event.php
key值 必须是swoole.websocket.事件名称
例如 swoole.websocket.Message
开始写事件中中方法
连接事件app\listener\SwWsConnect.php
public function handle($event, \think\swoole\websocket $ws)
{
// 获取当前发送者的fd
$fd = $ws->getSender();
echo "server: handshake success with fd{$fd}\n";
} ログイン後にコピー
关闭事件app\listener\SwWsClose.php
public function handle($event, \think\swoole\websocket $ws)
{
$fd = $ws->getSender();
echo "client {$fd} closed\n";
} ログイン後にコピー
message事件app\listener\SwWsMessage.php
public function handle($event, \think\swoole\websocket $ws)
{
$fd = $ws->getSender();
$data = json_encode($event);
echo "receive from {$fd}:{$data}\n";
$ws->emit("this is server", $fd);
} ログイン後にコピー
启动php think swoole
进行测试
think-swoole中的websocket方法总结
//给自己发消息
$ws->emit("this is server", $ws->getSender());
//给指定一个fd发消息
$ws->to($to)->emit("messagecallback",$data);
//给指定多个人发消息
$ws->to([1,2,3])->emit("messagecallback",$data);
//发送给所有的(不包含自己)
$ws->broadcast()->emit("messagecallback",$data);
//模拟formfd 给tofd 发送消息
$ws->setSender($formfd)->to($tofd)->emit("messagecallback",$data); ログイン後にコピー
注意:在多个实时通讯场景下使用 emit
第一个参数传入 传入 事件名称callback 例如 messagecallback
如果你发现你think-swoole中有些没有swoole中的方法可以这么干
$sw = app('swoole.server');
$sw = app("think\swoole\Manager")->getServer();
//以上二选一
$es = $sw->isEstablished($fd); //检查连接是否为有效的WebSocket客户端连接
var_dump($es); ログイン後にコピー
聊天室room实现 前端文件参考 html\room.html
或 html\room-socket-io.html
php think make:listener SwRoomJoin
php think make:listener SwRoomLeave
php think make:listener SwRoomMessage ログイン後にコピー
事件绑定
// 加入房间
'swoole.websocket.RoomJoin' => [
\app\listener\SwRoomJoin::class
],
// 离开房间
'swoole.websocket.Roomleave' => [
\app\listener\SwRoomLeave::class
],
// 在房间发消息
'swoole.websocket.RoomMessage' => [
\app\listener\SwRoomMessage::class
] ログイン後にコピー
加入房间逻辑
public function handle($event, \think\swoole\websocket $ws, \think\swoole\websocket\room $room)
{
$fd = $ws->getSender();
//客户端假如定的room
$roomid = $event['room'];
//获取指定房间下有哪些客户端
$roomfds = $room->getClients($roomid);
// 判断这个房间有没有自己 如果有自己就不需要再次发送通知
if (in_array($fd, $roomfds)) {
$ws->to($roomfds)->emit("roomjoincallback", "房间{$roomid}已加入");
return;
}
//加入房间
$ws->join($roomid);
$ws->to($roomfds)->emit("roomjoincallback", "{$fd}加入房间{$roomid}成功");
} ログイン後にコピー
离开房间逻辑
public function handle($event, \think\swoole\websocket $ws, \think\swoole\websocket\Room $room)
{
$roomid = $event['room'];
$fd = $ws->getSender();
$roomfds = $room->getClients($roomid);
if (!in_array($fd, $roomfds)) {
$ws->emit("roomleavecallback", "{$fd}不在{$roomid}房间内,怎么离开~");
return;
}
//离开房间
$ws->leave($roomid);
//获取当前客户端加入了哪些客户端
$rooms = $room->getRooms($fd);
$ws->to($roomfds)->emit("roomleavecallback", "{$fd}已离开了~~");
} ログイン後にコピー
在房间发布聊天逻辑
public function handle($event, \think\swoole\websocket $ws, \think\swoole\websocket\room $room)
{
//
$roomid = $event['room'];
$text = $event['text'];
$fd = $ws->getSender();
$roomfds = $room->getClients($roomid);
if (!in_array($fd, $roomfds)) {
$ws->emit("roommessagecallback", "{$fd}不在{$roomid}房间内,无法进入发布聊天~");
return;
}
$ws->to($roomfds)->emit("roommessagecallback", $text);
} ログイン後にコピー
事件订阅 php think make:listener SwSubscribe ログイン後にコピー
applistenerSwSubscribe.php
<?php
declare (strict_types = 1);
namespace app\listener;
class SwSubscribe
{
protected $ws = null;
// public function __construct()
// {
// $this->ws = app('think\swoole\Websocket');
// }
public function __construct(\think\Container $c)
{
$this->ws = $c->make(\think\swoole\Websocket::class);
}
public function onConnect()
{
$fd = $this->ws->getSender();
echo "server: handshake success with fd{$fd}\n";
}
public function onClose()
{
$fd = $this->ws->getSender();
echo "client {$fd} closed\n";
}
public function onMessage($event)
{
$fd = $this->ws->getSender();
var_dump($event);
echo "server: handshake success with fd{$fd}\n";
$this->ws->emit("this is server", $fd);
}
} ログイン後にコピー
有点类似 将原生的swoole代码改成面向对象代码,生效方法 config\swoole.php
中在subscribe
加入\app\listener\SwSubscribe::class
'subscribe' => [
\app\listener\SwSubscribe::class
], ログイン後にコピー
在app\event.php
文件中的 swoole.websocket.Connect
相当于 app\listener\SwSubscribe.php
文件中的onConnect
函数。如果同时存在的存在的话,就会向客户端发送2次以上的消息
Task任务投递 https://wiki.swoole.com/#/start/start_task
生成事件
php think make:listener SwSendEmailTask ログイン後にコピー
编写发送邮件方法app\listener\SwSendEmailTask.php
public function handle($event)
{
var_dump($event);
//
echo "开发发送邮件".time();
sleep(3);
echo "结束发送邮件".time();
} ログイン後にコピー
注册事件app\event.php
'swoole.task'=>[
\app\listener\SwSendEmailTask::class
], ログイン後にコピー
在控制器中投递任务
public function doRegister()
{
$server = app('swoole.server');
$server->task(\app\listener\SwSendEmailTask::class);
return "注册成功";
}
public function doRegister(\think\swoole\Manager $manager)
{
$server = $manager->getServer();
$server->task(\app\listener\SwSendEmailTask::class);
return "注册成功";
}
public function doRegister(\Swoole\Server $server)
{
$server->task(\app\listener\SwSendEmailTask::class);
return "注册成功";
} ログイン後にコピー
三种获取\Swoole\Server
,任意选其一 在swoole中还有一个事件叫finish
,它的作用就是把异步任务的结果返回,在think-swool是这么处理的
定义一个发送邮件异步任务处理结果的事件
php think make:listener SwSendEmailFinish ログイン後にコピー
注册事件app\event.php
'swoole.finish'=>[
\app\listener\SwSendEmailFinish::class
], ログイン後にコピー
在task任务中调用
public function handle($event)
{
var_dump($event);
//
echo "开发发送邮件".time();
sleep(3);
echo "结束发送邮件".time();
$event->finish(\app\listener\SwSendEmailFinish::class);
} ログイン後にコピー
高性能共享内存 Table https://wiki.swoole.com/#/mem...
先定结构在进行操作数据(原生swoole操作)
$table = new Swoole\Table(1024);
//创建表
$table->column("id", Swoole\Table::TYPE_INT);
$table->column("name", Swoole\Table::TYPE_STRING);
$table->column("money", Swoole\Table::TYPE_FLOAT);
$table->create();
//添加数据
$table->set("zq", [
'id' => 1,
'name' => "zhiqiang",
'money' => 100,
]);
//获取一行数据
$table->get("zq");
// 修改数据
// 字段递增
$table->incr("zq","money",2);
//递减
$table->decr("zq","money",2);
// 返回 table 中存在的条目数。
$table->count();
//遍历table中的数据
foreach($table as $item){
var_dump($item);
} ログイン後にコピー
think-swoole中的操作
先对table表结构进行初始化config\swoole.php
'tables' => [
'user'=>[
'size'=>1024,
'columns'=>[
[
'name'=>'id',
'type'=>\Swoole\Table::TYPE_INT
],
[
'name'=>'name',
'type'=>\Swoole\Table::TYPE_STRING,
'size'=>32
],
[
'name'=>'money',
'type'=>\Swoole\Table::TYPE_FLOAT
],
],
],
], ログイン後にコピー
操作数据
$table = app('swoole.table.user');
$table->set("zq", [
'id' => 1,
'name' => "zhiqiang",
'money' => 100
]);
//获取一行数据
$table->get("zq");
// 修改数据
// 字段递增
$table->incr("zq", "money", 2);
//递减
$table->decr("zq", "money", 2);
// 返回 table 中存在的条目数。
$table->count();
//遍历table中的数据
foreach ($table as $item) {
var_dump($item);
}
// 检查 table 中是否存在某一个 key。
$table->exist('zq');
//获取实际占用内存尺寸,单位字节
$table->momorySize(); ログイン後にコピー
RPC RPC(Remote Procedure Call):远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的思想。
详细介绍:https://developer.51cto.com/a...
解决分布式系统中,服务之间的调用问题。 远程调用时,要能够像本地调用一样方便,让调用者感知不到远程调用的逻辑。 节点角色说明: Server: 暴露服务的服务提供方 Client: 调用远程服务的服务消费方 Registry: 服务注册与发现的注册中心 think-swoole实现RPC功能
服务器端 接口定义app/rpc/interfaces/UserInterface.php
<?php
namespace app\rpc\interfaces;
interface UserInterface
{
public function create();
public function find(int $id);
} ログイン後にコピー
实现接口app/rpc/services/UserService.php
<?php
namespace app\rpc\services;
use app\rpc\interfaces\UserInterface;
class UserService implements UserInterface
{
public function create()
{
// TODO: Implement create() method.
return "service create success";
}
public function find(int $id)
{
// TODO: Implement find() method.
return $id. "查询数据遍历";
}
} ログイン後にコピー
注册rpc服务config/swoole.php
'rpc' => [
'server' => [
//开启rpc服务
'enable' => true,
//rpc端口
'port' => 9000,
'services' => [
//注册服务
\app\rpc\services\UserService::class
],
],
// 如果填写也是可以调用其他服务端
'client' => [
],
], ログイン後にコピー
启动服务端
php think swoole start / php think swoole:rpc ログイン後にコピー
客户端 'rpc' => [
'server' => [
],
'client' => [
'tp6'=>[
//服务端的ip地址
'host'=>'127.0.0.1',
//服务端对应的端口
'port'=>'9000'
]
// 更多服务端
],
], ログイン後にコピー
运行php think rpc:interface
生成RPC接口文件app\rpc.php
<?php
/**
* This file is auto-generated.
*/
declare(strict_types=1);
namespace rpc\contract\tp6;
interface UserInterface
{
public function create();
public function find(int $id);
}
return ['tp6' => ['rpc\contract\tp6\UserInterface']]; ログイン後にコピー
在控制器调用
public function index(\rpc\contract\tp6\UserInterface $user)
{
//
$user->find(1);
// $user->create();
} ログイン後にコピー
定时任务 在think-swoole 2.0版本的时候还是支持自定义定时任务配置,详细参考https://github.com/top-think/think-swoole/tree/2.0
在3.0就不支持了,在这里介绍一个通用的命令行启动定时任务
php think make:command SwooleTimer ログイン後にコピー
加载命令行config/console.php
'commands' => [
'swooletimer'=>app\command\SwooleTimer::class
...........
], ログイン後にコピー
书写命令脚本app/command/SwooleTimer.php
<?php
declare (strict_types = 1);
namespace app\command;
use think\console\Command;
use think\console\input\Argument;
class SwooleTimer extends Command
{
protected function configure()
{
// 指令配置
$this->setName('app\command\swooletimer')
->addArgument('action', Argument::OPTIONAL, "start | stop", 'start')
->setDescription('Swoole Timer for ThinkPHP');
}
public function handle()
{
$action = $this->input->getArgument('action');
if (in_array($action, ['start','stopall'])) {
$this->app->invokeMethod([$this, $action], [], true);
} else {
$this->output->writeln("<error>Invalid argument action:{$action}, Expected start</error>");
}
}
/**
* 启动定时任务 主要任务计划在这里书写
*/
protected function start()
{
// https://wiki.swoole.com/#/timer
$timer_id=swoole_timer_tick(2000,function (){
echo "2s循环执行需要做的事情".time()."\n";
});
$this->output->writeln("Swoole Timer_id:{$timer_id} ");
}
/**
* 清除所有的定时任务
*/
protected function stop(){
swoole_timer_clear_all();
$this->output->writeln("Swoole Timer clear all ok");
}
} ログイン後にコピー
以上がthink-swoole の実践例を共有する [詳細なデモ]の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
2023-04-24 11:00:01
2023-04-24 10:55:51
2023-04-24 10:52:44
2023-04-23 17:40:51
2023-04-23 17:38:02
2023-04-23 17:34:02
2023-04-23 10:15:45
2023-04-23 10:10:52
2023-04-21 16:01:59
2023-04-21 15:58:01