High Performance Programmatic Server for PHP with Async IO, Coroutines and Fibers

Build high-performance, scalable, concurrent TCP, UDP, Unix Socket, HTTP, WebSocket services with PHP and easy to use coroutine, fibers API.


use function Swoole\Coroutine\run;
use function Swoole\Coroutine\go;

run(function() {
    sleep(1);
});

use function Swoole\Coroutine\run;
use function Swoole\Coroutine\go;

run(function() {
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);
    $result = $redis->keys('*');
    var_dump($result);
});

use function Swoole\Coroutine\run;
use function Swoole\Coroutine\go;

run(function() {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://httpbin.org/get');
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $result = curl_exec($ch);
    curl_close($ch);
    var_dump($result);
});

use function Swoole\Coroutine\run;
use function Swoole\Coroutine\go;

run(function () {
    go(function () {
        $pdo = new PDO('mysql:host=10.66.110.163;dbname=coding_test;charset=utf8', 'coding_test', 'coding_test');
        $statement = $pdo->prepare('SELECT * FROM `coding_test`');
        $statement->execute();
        var_dump($statement->fetchAll());
    });
    go(function () {
        $mysqli = new mysqli('10.66.110.163', 'coding_test', 'coding_test', 'coding_test');
        $statement = $mysqli->prepare('SELECT `id` FROM `coding_test`');
        $statement->bind_result($id);
        $statement->execute();
        $statement->fetch();
        var_dump($id);
    });
});

use Swoole\Coroutine;
use function Swoole\Coroutine\run;
use function Swoole\Coroutine\go;

run(function() {
    $result = [];
    Coroutine::join([
        go(function () use (&$result) {
            $result['baidu'] = file_get_contents("https://www.baidu.com/");
        }),
        go(function () use (&$result) {
            $result['taobao'] = file_get_contents("https://www.taobao.com/");
        })
    ]);

    echo "all done\n";
});

$http = new Swoole\Http\Server('127.0.0.1', 9501);

$http->on('start', function ($server) {
    echo "Swoole http server is started at http://127.0.0.1:9501\n";
});

$http->on('request', function ($request, $response) {
    $response->header('Content-Type', 'text/plain');
    $response->end('Hello World');
});

$http->start();

$server = new Swoole\Server('127.0.0.1', 9503);

$server->on('start', function ($server) {
    echo "TCP Server is started at tcp://127.0.0.1:9503\n";
});

$server->on('connect', function ($server, $fd){
    echo "connection open: {$fd}\n";
});

$server->on('receive', function ($server, $fd, $reactor_id, $data) {
    $server->send($fd, "Swoole: {$data}");
});

$server->on('close', function ($server, $fd) {
    echo "connection close: {$fd}\n";
});

$server->start();

$server = new Swoole\Server('127.0.0.1', 9504, SWOOLE_PROCESS, SWOOLE_SOCK_UDP);

$server->on('start', function ($server) {
    echo "UDP Server is started at udp://127.0.0.1:9504\n";
});

$server->on('packet', function ($server, $data, $clientInfo) {
    $server->sendTo($clientInfo['address'], $clientInfo['port'], "Server:{$data}");
});

$server->start();

$server = new Swoole\Websocket\Server('127.0.0.1', 9502);

$server->on('start', function ($server) {
    echo "Websocket Server is started at ws://127.0.0.1:9502\n";
});

$server->on('open', function($server, $req) {
    echo "connection open: {$req->fd}\n";
});

$server->on('message', function($server, $frame) {
    echo "received message: {$frame->data}\n";
    $server->push($frame->fd, json_encode(['hello', 'world']));
});

$server->on('close', function($server, $fd) {
    echo "connection close: {$fd}\n";
});

$server->start();

use function Swoole\Coroutine\run;
use function Swoole\Coroutine\go;

run(function() {
    $id = go(function(){
        $id = Co::getUid();
        echo "start coro $id\n";
        Co::suspend($id);
        echo "resume coro $id @1\n";
        Co::suspend($id);
        echo "resume coro $id @2\n";
    });
    echo "start to resume $id @1\n";
    Co::resume($id);
    echo "start to resume $id @2\n";
    Co::resume($id);
    echo "main\n";
});

use Swoole\Coroutine;
use Swoole\Coroutine\Channel;
use function Swoole\Coroutine\run;
use function Swoole\Coroutine\go;

run(function(){
    $channel = new Channel(1);
    go(function () use ($channel) {
        for($i = 0; $i < 10; $i++) {
            Coroutine::sleep(1.0);
            $channel->push(['rand' => rand(1000, 9999), 'index' => $i]);
            echo "{$i}\n";
        }
    });
    go(function () use ($channel) {
        while(true) {
            $data = $channel->pop(2.0);
            if ($data) {
                var_dump($data);
            } else {
                assert($channel->errCode === SWOOLE_CHANNEL_TIMEOUT);
                break;
            }
        }
    });
});

use Swoole\Coroutine\Socket;
use function Swoole\Coroutine\run;
use function Swoole\Coroutine\go;

run(function() {
    go(function () {
        $socket = new Socket(AF_INET, SOCK_DGRAM, 0);
        $socket->bind('127.0.0.1', 9503);
        $client_map = [];
        for ($c = 128; $c--;) {
            for ($n = 0; $n < 100; $n++) {
                $recv = $socket->recvfrom($peer);
                $client_uid = "{$peer['address']}:{$peer['port']}";
                $id = $client_map[$client_uid] = ($client_map[$client_uid] ?? -1) + 1;
                assert($recv === "Client: Hello #{$id}!");
                $socket->sendto($peer['address'], $peer['port'], "Server: Hello #{$id}!");
            }
        }
        $socket->close();
    });
    for ($c = 128; $c--;) {
        go(function () {
            $fp = stream_socket_client('udp://127.0.0.1:9503', $errno, $errstr, 1);
            if (!$fp) {
                echo "{$errstr} ({$errno})\n";
                return;
            }
            for ($n = 0; $n < 100; $n++) {
                fwrite($fp, "Client: Hello #{$n}!");
                $recv = fread($fp, 1024);
                list($address, $port) = explode(':', (stream_socket_get_name($fp, true)));
                assert($address === '127.0.0.1' && (int)$port === 9503);
                assert($recv === "Server: Hello #{$n}!");
            }
            fclose($fp);
        });
    }
    echo 'Done', PHP_EOL;
});

use function Swoole\Coroutine\run;

run(function(){
    $fp1 = stream_socket_client('tcp://www.baidu.com:80', $errno, $errstr, 30);
    $fp2 = stream_socket_client('tcp://www.qq.com:80', $errno, $errstr, 30);
    if (!$fp1) {
        echo "$errstr ($errno) \n";
    } else {
        fwrite($fp1, "GET / HTTP/1.0\r\nHost: www.baidu.com\r\nUser-Agent: curl/7.58.0\r\nAccept: */*\r\n\r\n");
        $r_array = [$fp1, $fp2];
        $w_array = $e_array = null;
        $n = stream_select($r_array, $w_array, $e_array, 10);
        $html = '';
        while (!feof($fp1)) {
            $html .= fgets($fp1, 1024);
        }
        fclose($fp1);
        echo strlen($html);
    }
});

$server = new Swoole\Server('127.0.0.1', 9503);

$server->set(['task_worker_num' => 4]);

$server->on('start', function ($server) {
    echo "TCP Server is started at tcp://127.0.0.1:9503\n";
});

$server->on('receive', function($server, $fd, $reactor_id, $data) {
    $task_id = $server->task('Async');
    $server->send($fd, "Dispatch AsyncTask: [id={$task_id}]\n");
});

$server->on('task', function ($server, $task_id, $reactor_id, $data) {
    echo "New AsyncTask[id={$task_id}]\n";
    $server->finish("{$data} -> OK");
});

$server->on('finish', function ($server, $task_id, $data) {
    echo "AsyncTask[{$task_id}] finished: {$data}\n";
});

$server->start();
Run

开源、高性能、生产力

如果您有基于 Swoole 的优秀项目希望展示在官网,请扫描微信二维码联系我们

PHP 微服务(Micro Service)
Hyperf 是基于 Swoole 4.4+ 实现的高性能、高灵活性的 PHP 协程框架,内置协程服务器及大量常用的组件,性能较传统基于 PHP-FPM 的框架有质的提升,提供超高性能的同时,也保持着极其灵活的可扩展性,标准组件均基于 PSR 标准实现,基于强大的依赖注入设计,保证了绝大部分组件或类都是可替换与可复用的
HyperfCMS
HyperfCMS 是基于 Swoole+Hyperf 框架前后端分离架构的一套开源且完美的建站系统,拥有简单大气设计、友好的交互体验、清晰明了的代码规范。组件化的封装应用,编写复杂的管理应用,效率是质的提升、时间成倍缩短,人员可以减半,事半功倍。可以提供定制化服务!
物联网(IOT)解决方案
MQTT 是一个客户端服务端架构的发布 / 订阅模式的消息传输协议。它的设计思想是轻巧、开放、简单、规范,易于实现。这些特点使得它对很多场景来说都是很好的选择,特别是对于受限的环境如机器与机器的通信(M2M)以及物联网环境(IoT)。可以使用 Swoole 作为 MQTT 服务端或客户端,实现一套完整物联网(IOT)解决方案
MoChat
MoChat - 基于 Hyperf 框架的国内首款完全开源的 PHP 企业微信管理系统
魔兽世界
魔兽模拟游戏服务器,项目采用 PHP 开发,TCP 长连接基于 Swoole,支持鉴权,角色的创建,地图的加载,NPC 和生物的构建及各种眼花缭乱的物品和技能等等
分布式定时任务 (Swoole Crontab)
基于 Swoole 的定时器程序,支持秒级处理,完全兼容 crontab 语法,且支持秒的配置,可使用数组规定好精确操作时间,Web 界面管理,增删改查任务,完整的权限控制
实时视频语音 (Webrtc)
基于 Swoole4 高性能协程的 demo 级实时视频和语音通话方案,采用 webrtc 协议,并已经做好 p2p 打洞,中继服务器,演示地址:https://webrtc.dingjw.com/room.php?cid=2
斗地主
基于 Swoole + Hyperf 框架开发 demo 级的斗地主游戏,实现斗地主游戏服务端逻辑,并采用原生 js 和 WebSocket 实现简单的客户端打牌逻辑,可以做到简单的玩斗地主游戏
ThinkCMF
ThinkCMF 是一款基于 ThinkPHP+Mysql 开发的 CMS,完美支持 Swoole,框架自身提供基础的管理功能,而开发者可以根据自身的需求以应用的形式进行扩展。每个应用都能独立的完成自己的任务,也可通过系统调用其他应用进行协同工作。在这种运行机制下,开发商场应用的用户无需关心开发 SNS 应用时如何工作的,但他们之间又可通过系统本身进行协调,大大的降低了开发成本和沟通成本
Swoole Worker
Swoole Worker是基于Swoole4开发的一款分布式长连接开发框架。常驻内存,协程,高性能高并发;分布式部署,横向扩容,使得能支持庞大的连接数;无感知安全重启,无缝升级代码;接口丰富,支持单个发送,分组发送,群发广播等接口。
LaravelS
LaravelS 是 Swoole 和 Laravel/Lumen 之间开箱即用的适配器,内置 HTTP/WebSocket Server,支持 TCP/UDP Server、自定义进程、异步的事件监听、异步任务、毫秒级定时任务、平滑Reload等特性,让 Laravel 如虎添翼。
Yasd
Yasd 是一个 Swoole 调试器,类似 Xdebug,完美支持协程,支持断点调试、单步追踪、watch 变量
Markdown文档系统
软擎文档系统是基于 Swoole + Rangine 框架开发的开源版 MarkDown 文档管理系统,不同于 docsify.js 等前端文档系统,本文档系统是偏后端的文档系统,对于广大PHPer来说更加友好。支持多用户协同操作,管理员审核发布等功能。 让您的工作更高效,更智慧。
Mysql Proxy(Mysql中间件)
一个基于 MySQL 协议,Swoole 开发的 MySQL 数据库连接池,支持读写分离支持数据库连接池,能够有效解决 PHP 带来的数据库连接瓶颈,支持 SQL92 标准,采用协程调度,遵守 MySQL 原生协议,跨语言,跨平台的通用中间件代理,支持 MySQL 事务,完美兼容 MySQL5.5 - 8.0
PaySDK
PHP 集成支付 SDK ,集成了支付宝、微信支付的支付接口和其它相关接口的操作。支持 php-fpm 和 Swoole,所有框架通用。
Ain't Queue 异步队列
Ain't Queue 借助 Swoole 提供的便捷多进程 API 和 CSP 编程能力实现了主进程+监控进程+多工作进程的进程模型,并且提供了各类事件自定义注册的能力(队列监控、快照记录、任务中间件等)。默认使用 Redis 驱动,全原子操作,可延时可重试,自带漂亮的仪表盘,稳定可靠,已经在公司生产环境使用。
xlswriter
xlswriter是一个 PHP C 扩展,支持 Swoole 协程环境,可用于在 Excel 2007+ XLSX 文件中读取数据,插入多个工作表,写入文本、数字、公式、日期、图表、图片和超链接。
ZooKeeper
基于 Swoole 协程的PHP ZooKeeper客户端
蘑菇灯
使用 APISIX + Hyperf + Premetheus + Grafana + SwooleTracker + Elasticsearch + Supervisor 做了一个完整的 DEMO 示例,旨在为广大 PHPer 从架构至运维层面提供高性能网关 + 高性能应用服务 + 全方位可视化运维监控 + 全链路跟踪分析的服务
电商系统 CRMEB Pro
CRMEB Pro是一套集多门店管理线下配送、核销、收银与一体的企业级高性能单商户商城系统。在满足商城常用功能基础上,结合多门店管理、线上线下业务相融合;支持门店后台管理、到店核销、线下配送、线下收银功能;系统用户端页面支持个性化DIY装修设计、多种主题风格切换,支持店铺客服移动端改价、发货、核销订单管理;同时满足微信公众号、小程序、H5、PC端、APP多端适配,数据同步,CRMEB Pro系统采用Tp6 + Swoole+redis高性能框架开发,基于异步事件驱动和协程的并行网络通信引擎,充分利用了底层的epoll / kqueue实现网络事件请求处理;通过 Swoole协程异步处理数据,彻底解决了PHP高并发处理问题;通过集群部署,进一步提升系统性能。是集团性公司、品牌连锁企业电商系统的第一选择!
基于 Swoole 的多进程队列系统
基于 Swoole 的多进程队列系统,Manager 进程管理子进程,Master 进程监听队列分发任务,Worker 进程执行任务, 多进程、低延时(最低毫秒级)、高可用、低资源占用、可多服务器分布式部署。可与 Laravel、ThinkPHP 等框架配合使用。默认 Redis 驱动,原子性操作,支持延时投递、错误重试、自定义超时,支持后台守护运行,无需其余进程管理工具。提供多种命令,方便管理及查询进程状态、任务状态。

联系我们

联系我们

官方公众号

官方公众号

Swoole 特性

Swoole 使用 C/C++ 语言编写,提供了 PHP 语言的异步多线程服务器、异步 TCP/UDP 网络客户端、异步 MySQL、异步 Redis、数据库连接池、AsyncTask、消息队列、毫秒定时器、异步文件读写、异步 DNS 查询。 Swoole 内置了 Http/WebSocket 服务器端/客户端、Http2.0 服务器端。

除了异步 IO 的支持之外,Swoole 为 PHP 多进程的模式设计了多个并发数据结构和 IPC 通信机制,可以大大 简化多进程并发编程的工作。其中包括了原子计数器、Table、Channel、Lock、进程间通信 IPC 等丰富的功能特性。

Swoole4.0 支持了类似 Go 语言的协程,可以使用完全同步的代码实现异步程序。PHP 代码无需额外增加任何 关键词,底层自动进行协程调度,实现异步 IO。