Swoole教程(一):服务器开发

2023-10-10 496 阅读 0评论

Swoole是什么

Swoole 是一个使用 C++ 语言编写的基于异步事件驱动和协程的并行网络通信引擎,为 PHP 提供协程高性能网络编程支持。提供了多种通信协议的网络服务器和客户端模块,可以方便快速的实现 TCP/UDP服务、高性能Web、WebSocket服务、物联网、实时通讯、游戏、微服务等,使 PHP 不再局限于传统的 Web 领域

以上是swoole官网的介绍,这里说下我自己的一些看法。与其他 PHP 扩展(如 Opcache、Imagick、Redis 等)一样,Swoole 也是一个外部扩展,但是Swoole 带来了一些概念。例如,服务器模式原生协程协程调度器多路复用和异步 I/O协程调度器和异步 I/O 状态管理进程管理等。与其他普通php扩展不一样的地方是,Swoole为php开发人员带来的编程方式的改变,让php编程更加Nodejs化,Swoole 为开发者提供使用 PHP 语法方式创建和管理 TCP、HTTP、WebSocket 服务器的手段,与 PHP-FPM 仅支持无状态模型不同,使用 Swoole,您可以在服务器内提供缓存和管理状态以提高性能,达到类型java等静态语言那样常驻内存的效果。它完全提供了一种新的PHP应用程序运行模式

图片


为什么要使用Swoole

Swoole已经经过了压力测试和验证

国内很多公司都已经用上了swoole了,在招聘网站输入swoole可以看到很多的招聘需求。据统计,swoole已经在高流量的生产环境中经过了压力测试和验证。说明php使用swoole是值得信赖和使用的。

支持多线程

如上所述,Swoole具有多个网络工作者和独立的任务工作者,这使得代码可以延期。长时间运行的进程的延期为你的API和应用程序中许多以前无法实现的方法打开了大门,例如将处理过程推迟到发送响应之后

支持协程

Swoole的Coroutine支持意味着你可以处理大量的请求,即使你正在做大量昂贵的I/O(例如,与你的数据库对话,使用文件系统,进行HTTP请求)。
自举系统只被加载一次,所以你消除了每次请求的15-25%的税。因为它是你初始化的一部分,这意味着你在每次请求中使用的资源更少,包括内存和CPU。对于一些应用程序,这可能意味着你需要更少的服务器,由于异步运行时的存在,这可能已经成为可能。

不需要Server支持,本身就是Server

说到更少的服务器,你不需要网络服务器,因为Swoole就是网络服务器。你可以启动一个只安装PHP的docker容器,你不需要NGINX坐在它的前面。

你不必把NGINX或Apache编在同一个容器中,它可以只是PHP。而且,如果你正在做任何形式的容器化,拥有这些单进程的容器和一种语言是真正的黄金标准。

更多并发请求支持

异步服务器能够处理的请求是非异步服务器的4到7倍,Node已经一次又一次地证明了这点。

安装swoole

通过宝塔安装swoole

这种方式是最简单的方式。直接安装php的swoole插件即可

图片


通过源码编译安装swoole

此方法同时适用于ubuntu和centos等linux系统

git clone https://github.com/swoole/swoole-src.git
cd swoole-src
phpize
./configure
make && make install

编译安装到系统成功后,需要在 php.ini 中加入一行 extension=swoole.so 来启用 Swoole 扩展

通过docker直接安装启用

docker pull phpswoole/swoole

使用swoole进行服务端编程

Tcp服务器

网络编程中常用Tcp服务器,即使最常见的HTTP1和HTTP2也是基于TCP协议上封装的的,HTTP3才是基于UDP。用Swoole创建服务一般2种方式,异步风格和协程风格,分别对应的Server类是Swoole\Server和Swoole\Coroutine\Server ,
异步风格

$server = new Swoole\Server("127.0.0.1", 9501);
$server->on('connect', function ($server, $fd){
  echo "Client:Connect.\n";
});
$server->on('receive', function ($server, $fd, $reactor_id, $data) {
  $server->send($fd, 'Swoole: '.$data);
  $server->close($fd);
});
$server->on('close', function ($server, $fd) {
  echo "Client: Close.\n";
});
$server->start();

协程风格

协程风格下链接是动态创建和销毁的,可以设置5秒没收到数据自动超时关闭

go(function(){
    $server = new \Swoole\Coroutine\Server('0.0.0.0',9501,false,true);
    $server->handle(function (\Swoole\Coroutine\Server\Connection $conn){
        echo '您好,欢迎进入聊天室'."\n";
        $socket = $conn->exportSocket();
        while (true){
            $data = $conn->recv(5);
            if ($data === '' || $data === false) {
//                $errCode = swoole_last_error();
//                $errMsg = socket_strerror($errCode);
                echo "协程风格下链接是动态创建和销毁的,可以设置5秒没收到数据自动超时关闭\n";
                $conn->close();
                break;
            }
            //发送数据
            $conn->send('您好,您输入的data是: '.$data);
        }
        echo '客户端:'.$socket->fd.'的链接已经关闭';
    });
    $server->start();
});
Swoole\Event::wait();

由于我个人异步风格方式写得比较多,后面就都用协程风格来写。

UDP服务器

Swoole创建Udp服务的类是Swoole\Coroutine\Socket,异步方式请同学自行查看官方文档。

<?php
use function Swoole\Coroutine\go;
go(function (){
    $socket = new Swoole\Coroutine\Socket(AF_INET, SOCK_DGRAM, 0); //domain, type, protocol
    // domain=AF_INET, 使用ipv4通信
    // type=SOCK_DGRAM, 无保障的面向消息的socket,主要用于在网络上发广播信息
    $socket->bind('0.0.0.0', 9501);//绑定监听的ip和端口
    $socket->listen(128);
    $peer = null;
    while (true){
        $data = $socket->recvfrom($peer,5);
        var_dump($data);
        if($peer){
            echo "收到来自{$peer['address']}:{$peer['port']}的消息 : $data\n";
            $socket->sendto($peer['address'], $peer['port'], "你好,你的消息是: $data");
        }
    }
});
Swoole\Event::wait();

HTTP服务器

HTTP服务器对应的类是Swoole\Coroutine\Http\Server,这个就比较常用了,同TCP一样也是通过handle来处理请求,但回调函数置入了Swoole\Http\Request 和 Swoole\Http\Response 两个对象,这就非常好办了

<?php
use Swoole\Coroutine\Http\Server;
use function Swoole\Coroutine\run;

run(function () {
    $server = new Server('0.0.0.0', 9501, false);
    //可以通过request对象来进一步判断映射路由,
    $server->handle('/', function ($request, $response) {
        $info = $request->header['host'];
        $response->end("<h1>您访问了路径/,来自{$info}</h1>");
    });
    $server->handle('/test', function ($request, $response) {
        $response->end("<h1>您访问了路径/test</h1>");
    });
    $server->handle('/stop', function ($request, $response) use ($server) {
        $response->end("<h1>您访问了路径/stop</h1>");
        $server->shutdown();
    });
    $server->start();
});

图片


WebSocket服务器

WebSocket同样是采用Swoole\Coroutine\Http\Server,但是处理流程有点不一样。请求进来时必须先调用$response->upgrade();向客户端发送WebSocket握手消息,将请求升级为websocket请求。然后通过while(true)循环处理消息的接收和发送

<?php
use Swoole\WebSocket\CloseFrame;
use function Swoole\Coroutine\go;
go(function (){
    $server = new \Swoole\Coroutine\Http\Server('0.0.0.0',9502,false);
    $server->handle('/',function (\Swoole\Http\Request $request,\Swoole\Http\Response $response){
        $response->upgrade();
        while (true) {
            $frame = $response->recv();
            if ($frame === '') {
                $response->close();
                break;
            } else if ($frame === false) {
                echo '发生错误: ' . swoole_last_error() . "\n";
                $response->close();
                break;
            } else {
                if ($frame->data == 'close' || get_class($frame) === CloseFrame::class) {
                    $response->close();
                    break;
                }
                $response->push("你好 {$request->fd},你说了:{$frame->data}!");
                $response->push("你好啊{$request->fd},我又一次回复 {$frame->data}给你");
            }
        }
        echo '客户端断开了'."\n";
    });
    $server->start();
});
Swoole\Event::wait();


其他服务端

Swoole还可以做很多事情,比如用于物联网的Mqtt服务器,比如用于定时任务处理,还比如消息队列等等,本篇作为开篇先讲到这,后面有时间我会继续输出Swoole相关的知识。

喜欢就支持以下吧
点赞 0

发表评论

快捷回复: 表情:
aoman baiyan bishi bizui cahan ciya dabing daku deyi doge fadai fanu fendou ganga guzhang haixiu hanxiao zuohengheng zhuakuang zhouma zhemo zhayanjian zaijian yun youhengheng yiwen yinxian xu xieyanxiao xiaoku xiaojiujie xia wunai wozuimei weixiao weiqu tuosai tu touxiao tiaopi shui se saorao qiudale qinqin qiaoda piezui penxue nanguo liulei liuhan lenghan leiben kun kuaikule ku koubi kelian keai jingya jingxi jingkong jie huaixiao haqian aini OK qiang quantou shengli woshou gouyin baoquan aixin bangbangtang xiaoyanger xigua hexie pijiu lanqiu juhua hecai haobang caidao baojin chi dan kulou shuai shouqiang yangtuo youling
提交
评论列表 (有 0 条评论, 496人围观)

最近发表

热门文章

最新留言

热门推荐

标签列表