Swoole:PHP 协程框架

Swoole 使 PHP 开发人员可以编写高性能高并发的 TCP、UDP、Unix Socket、HTTP、 WebSocket 等服务,让 PHP 不再局限于 Web 领域。Swoole4 协程的成熟将 PHP 带入了前所未有的时期, 为性能的提升提供了独一无二的可能性。Swoole 可以广泛应用于互联网、移动通信、云计算、 网络游戏、物联网(IOT)、车联网、智能家居等领域。使用 PHP + Swoole 可以使企业 IT 研发团队的效率大大提升,更加专注于开发创新产品。


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();

开源、高性能、生产力

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

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

联系我们

联系我们

官方公众号

官方公众号

源代码

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。