Swoole:PHP 協(xié)程框架

Swoole 使 PHP 開(kāi)發(fā)人員可以編寫高性能高并發(fā)的 TCP、UDP、Unix Socket、HTTP、 WebSocket 等服務(wù),讓 PHP 不再局限于 Web 領(lǐng)域。Swoole4 協(xié)程的成熟將 PHP 帶入了前所未有的時(shí)期, 為性能的提升提供了獨(dú)一無(wú)二的可能性。Swoole 可以廣泛應(yīng)用于互聯(lián)網(wǎng)、移動(dòng)通信、云計(jì)算、 網(wǎng)絡(luò)游戲、物聯(lián)網(wǎng)(IOT)、車聯(lián)網(wǎng)、智能家居等領(lǐng)域。使用 PHP + Swoole 可以使企業(yè) IT 研發(fā)團(tuán)隊(duì)的效率大大提升,更加專注于開(kāi)發(fā)創(chuàng)新產(chǎn)品。


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

開(kāi)源、高性能、生產(chǎn)力

如果您有基于 Swoole 的優(yōu)秀項(xiàng)目希望展示在官網(wǎng),請(qǐng)掃描微信二維碼聯(lián)系我們

ShopXO開(kāi)源商城
ShopXO企業(yè)級(jí)免費(fèi)開(kāi)源電商系統(tǒng)!求實(shí)進(jìn)取、創(chuàng)新專注、自主研發(fā)、國(guó)內(nèi)領(lǐng)先企業(yè)級(jí)電商系統(tǒng)解決方案。遵循MIT開(kāi)源協(xié)議發(fā)布,無(wú)需授權(quán)、可商用、可二次開(kāi)發(fā)、滿足99%的電商運(yùn)營(yíng)需求。支持PC+H5、支付寶小程序、微信小程序、百度小程序、頭條&抖音小程序、QQ小程序、APP等...支持多倉(cāng)庫(kù)、多商戶、線下門店模式運(yùn)營(yíng)(組件插件化、即插即用),可視化DIY拖拽裝修。多端統(tǒng)一客服系統(tǒng)采用Swoole高性能WebSocket構(gòu)建。
電商系統(tǒng) CRMEB Pro
CRMEB Pro采用Tp6 + Swoole+redis高性能框架開(kāi)發(fā);是一款高性能、高并發(fā)、高可用的私域客戶關(guān)系管理(CRM)+營(yíng)銷電商(EB)系統(tǒng);助力品牌商家實(shí)現(xiàn)公域引流轉(zhuǎn)化私域沉淀,全渠道智能化經(jīng)營(yíng)。系統(tǒng)基于異步事件驅(qū)動(dòng)和協(xié)程的并行網(wǎng)絡(luò)通信引擎,充分利用了底層的epoll / kqueue實(shí)現(xiàn)網(wǎng)絡(luò)事件請(qǐng)求處理;通過(guò) Swoole協(xié)程異步處理數(shù)據(jù),徹底解決了PHP高并發(fā)處理問(wèn)題;通過(guò)集群部署,進(jìn)一步提升系統(tǒng)性能。是品牌電商系統(tǒng)的第一選擇!
Markdown文檔系統(tǒng)
軟擎文檔系統(tǒng)是基于 Swoole + Rangine 框架開(kāi)發(fā)的開(kāi)源版 MarkDown 文檔管理系統(tǒng),不同于 docsify.js 等前端文檔系統(tǒng),本文檔系統(tǒng)是偏后端的文檔系統(tǒng),對(duì)于廣大PHPer來(lái)說(shuō)更加友好。支持多用戶協(xié)同操作,管理員審核發(fā)布等功能。 讓您的工作更高效,更智慧。
MoChat
MoChat - 基于 Hyperf 框架的國(guó)內(nèi)首款完全開(kāi)源的 PHP 企業(yè)微信管理系統(tǒng)
Ain't Queue 異步隊(duì)列
Ain't Queue 借助 Swoole 提供的便捷多進(jìn)程 API 和 CSP 編程能力實(shí)現(xiàn)了主進(jìn)程+監(jiān)控進(jìn)程+多工作進(jìn)程的進(jìn)程模型,并且提供了各類事件自定義注冊(cè)的能力(隊(duì)列監(jiān)控、快照記錄、任務(wù)中間件等)。默認(rèn)使用 Redis 驅(qū)動(dòng),全原子操作,可延時(shí)可重試,自帶漂亮的儀表盤,穩(wěn)定可靠,已經(jīng)在公司生產(chǎn)環(huán)境使用。
實(shí)時(shí)視頻語(yǔ)音 (Webrtc)
基于 Swoole4 高性能協(xié)程的 demo 級(jí)實(shí)時(shí)視頻和語(yǔ)音通話方案,采用 webrtc 協(xié)議,并已經(jīng)做好 p2p 打洞,中繼服務(wù)器,演示地址:https://webrtc.dingjw.com/room.php?cid=2
店滴云開(kāi)源框架
店滴云是針對(duì)多商戶業(yè)務(wù)開(kāi)發(fā)的一套管理cms,支持多運(yùn)營(yíng)主體,單運(yùn)營(yíng)主體運(yùn)營(yíng)開(kāi)發(fā)。基于世界上最好的語(yǔ)言php和yii開(kāi)發(fā),深度集成swoole,滿足需要http/tcp/mqtt等多種協(xié)議的業(yè)務(wù)場(chǎng)景,官方提供智能門鎖,智能開(kāi)關(guān)成熟的解決方案。采用最新的vue開(kāi)發(fā)技術(shù)作為中后臺(tái)管理,多終端開(kāi)發(fā)框架uniapp打造,旨在讓開(kāi)發(fā)更有趣味和成就感,希望可以助力更多的中小企業(yè)實(shí)現(xiàn)業(yè)績(jī)?cè)鲩L(zhǎng),技術(shù)創(chuàng)新和持續(xù)發(fā)展。官方依賴于店滴云先后開(kāi)發(fā)了疫情大數(shù)據(jù)監(jiān)測(cè),企業(yè)外呼,im客服,多商戶分銷,外賣點(diǎn)餐,政企黨建等系統(tǒng)。
魔獸世界
魔獸模擬游戲服務(wù)器,項(xiàng)目采用 PHP 開(kāi)發(fā),TCP 長(zhǎng)連接基于 Swoole,支持鑒權(quán),角色的創(chuàng)建,地圖的加載,NPC 和生物的構(gòu)建及各種眼花繚亂的物品和技能等等
PHP 微服務(wù)(Micro Service)
Hyperf 是基于 Swoole 4.4+ 實(shí)現(xiàn)的高性能、高靈活性的 PHP 協(xié)程框架,內(nèi)置協(xié)程服務(wù)器及大量常用的組件,性能較傳統(tǒng)基于 PHP-FPM 的框架有質(zhì)的提升,提供超高性能的同時(shí),也保持著極其靈活的可擴(kuò)展性,標(biāo)準(zhǔn)組件均基于 PSR 標(biāo)準(zhǔn)實(shí)現(xiàn),基于強(qiáng)大的依賴注入設(shè)計(jì),保證了絕大部分組件或類都是可替換與可復(fù)用的
ThinkCMF
ThinkCMF 是一款基于 ThinkPHP+Mysql 開(kāi)發(fā)的 CMS,完美支持 Swoole,框架自身提供基礎(chǔ)的管理功能,而開(kāi)發(fā)者可以根據(jù)自身的需求以應(yīng)用的形式進(jìn)行擴(kuò)展。每個(gè)應(yīng)用都能獨(dú)立的完成自己的任務(wù),也可通過(guò)系統(tǒng)調(diào)用其他應(yīng)用進(jìn)行協(xié)同工作。在這種運(yùn)行機(jī)制下,開(kāi)發(fā)商場(chǎng)應(yīng)用的用戶無(wú)需關(guān)心開(kāi)發(fā) SNS 應(yīng)用時(shí)如何工作的,但他們之間又可通過(guò)系統(tǒng)本身進(jìn)行協(xié)調(diào),大大的降低了開(kāi)發(fā)成本和溝通成本
MyCMS
MyCMS 是一款基于 Laravel 開(kāi)發(fā)開(kāi)源免費(fèi)的商城博客 CMS 建站系統(tǒng),通過(guò)集成 Swoole 大幅度提升系統(tǒng)的性能,功能和性能兼得
Swoole Worker
Swoole Worker是基于Swoole4開(kāi)發(fā)的一款分布式長(zhǎng)連接開(kāi)發(fā)框架。常駐內(nèi)存,協(xié)程,高性能高并發(fā);分布式部署,橫向擴(kuò)容,使得能支持龐大的連接數(shù);無(wú)感知安全重啟,無(wú)縫升級(jí)代碼;接口豐富,支持單個(gè)發(fā)送,分組發(fā)送,群發(fā)廣播等接口。
Yasd
Yasd 是一個(gè) Swoole 調(diào)試器,類似 Xdebug,完美支持協(xié)程,支持?jǐn)帱c(diǎn)調(diào)試、單步追蹤、watch 變量
物聯(lián)網(wǎng)(IOT)解決方案
MQTT 是一個(gè)客戶端服務(wù)端架構(gòu)的發(fā)布 / 訂閱模式的消息傳輸協(xié)議。它的設(shè)計(jì)思想是輕巧、開(kāi)放、簡(jiǎn)單、規(guī)范,易于實(shí)現(xiàn)。這些特點(diǎn)使得它對(duì)很多場(chǎng)景來(lái)說(shuō)都是很好的選擇,特別是對(duì)于受限的環(huán)境如機(jī)器與機(jī)器的通信(M2M)以及物聯(lián)網(wǎng)環(huán)境(IoT)。可以使用 Swoole 作為 MQTT 服務(wù)端或客戶端,實(shí)現(xiàn)一套完整物聯(lián)網(wǎng)(IOT)解決方案
xlswriter
xlswriter是一個(gè) PHP C 擴(kuò)展,支持 Swoole 協(xié)程環(huán)境,可用于在 Excel 2007+ XLSX 文件中讀取數(shù)據(jù),插入多個(gè)工作表,寫入文本、數(shù)字、公式、日期、圖表、圖片和超鏈接。
分布式定時(shí)任務(wù) (Swoole Crontab)
基于 Swoole 的定時(shí)器程序,支持秒級(jí)處理,完全兼容 crontab 語(yǔ)法,且支持秒的配置,可使用數(shù)組規(guī)定好精確操作時(shí)間,Web 界面管理,增刪改查任務(wù),完整的權(quán)限控制
PaySDK
PHP 集成支付 SDK ,集成了支付寶、微信支付的支付接口和其它相關(guān)接口的操作。支持 php-fpm 和 Swoole,所有框架通用。
基于 Swoole 的多進(jìn)程隊(duì)列系統(tǒng)
基于 Swoole 的多進(jìn)程隊(duì)列系統(tǒng),Manager 進(jìn)程管理子進(jìn)程,Master 進(jìn)程監(jiān)聽(tīng)隊(duì)列分發(fā)任務(wù),Worker 進(jìn)程執(zhí)行任務(wù), 多進(jìn)程、低延時(shí)(最低毫秒級(jí))、高可用、低資源占用、可多服務(wù)器分布式部署。可與 Laravel、ThinkPHP 等框架配合使用。默認(rèn) Redis 驅(qū)動(dòng),原子性操作,支持延時(shí)投遞、錯(cuò)誤重試、自定義超時(shí),支持后臺(tái)守護(hù)運(yùn)行,無(wú)需其余進(jìn)程管理工具。提供多種命令,方便管理及查詢進(jìn)程狀態(tài)、任務(wù)狀態(tài)。
LaravelS
LaravelS 是 Swoole 和 Laravel/Lumen 之間開(kāi)箱即用的適配器,內(nèi)置 HTTP/WebSocket Server,支持 TCP/UDP Server、自定義進(jìn)程、異步的事件監(jiān)聽(tīng)、異步任務(wù)、毫秒級(jí)定時(shí)任務(wù)、平滑Reload等特性,讓 Laravel 如虎添翼。
ZooKeeper
基于 Swoole 協(xié)程的PHP ZooKeeper客戶端
斗地主
基于 Swoole + Hyperf 框架開(kāi)發(fā) demo 級(jí)的斗地主游戲,實(shí)現(xiàn)斗地主游戲服務(wù)端邏輯,并采用原生 js 和 WebSocket 實(shí)現(xiàn)簡(jiǎn)單的客戶端打牌邏輯,可以做到簡(jiǎn)單的玩斗地主游戲
HyperfCMS
HyperfCMS 是基于 Swoole+Hyperf 框架前后端分離架構(gòu)的一套開(kāi)源且完美的建站系統(tǒng),擁有簡(jiǎn)單大氣設(shè)計(jì)、友好的交互體驗(yàn)、清晰明了的代碼規(guī)范。組件化的封裝應(yīng)用,編寫復(fù)雜的管理應(yīng)用,效率是質(zhì)的提升、時(shí)間成倍縮短,人員可以減半,事半功倍。可以提供定制化服務(wù)!
HCMS
Hcms 是一個(gè)基于 Hyperf 框架的項(xiàng)目開(kāi)發(fā)管理系統(tǒng) , 在Hyperf超高速且靈活的特性加持下,構(gòu)建一個(gè)快速開(kāi)發(fā)、模塊復(fù)用的項(xiàng)目開(kāi)發(fā)管理系統(tǒng)。
Mysql Proxy(Mysql中間件)
一個(gè)基于 MySQL 協(xié)議,Swoole 開(kāi)發(fā)的 MySQL 數(shù)據(jù)庫(kù)連接池,支持讀寫分離支持?jǐn)?shù)據(jù)庫(kù)連接池,能夠有效解決 PHP 帶來(lái)的數(shù)據(jù)庫(kù)連接瓶頸,支持 SQL92 標(biāo)準(zhǔn),采用協(xié)程調(diào)度,遵守 MySQL 原生協(xié)議,跨語(yǔ)言,跨平臺(tái)的通用中間件代理,支持 MySQL 事務(wù),完美兼容 MySQL5.5 - 8.0

聯(lián)系我們

聯(lián)系我們

官方公眾號(hào)

官方公眾號(hào)

源代碼

Swoole 特性

Swoole 使用 C/C++ 語(yǔ)言編寫,提供了 PHP 語(yǔ)言的異步多線程服務(wù)器、異步 TCP/UDP 網(wǎng)絡(luò)客戶端、異步 MySQL、異步 Redis、數(shù)據(jù)庫(kù)連接池、AsyncTask、消息隊(duì)列、毫秒定時(shí)器、異步文件讀寫、異步 DNS 查詢。 Swoole 內(nèi)置了 Http/WebSocket 服務(wù)器端/客戶端、Http2.0 服務(wù)器端。

除了異步 IO 的支持之外,Swoole 為 PHP 多進(jìn)程的模式設(shè)計(jì)了多個(gè)并發(fā)數(shù)據(jù)結(jié)構(gòu)和 IPC 通信機(jī)制,可以大大 簡(jiǎn)化多進(jìn)程并發(fā)編程的工作。其中包括了原子計(jì)數(shù)器、Table、Channel、Lock、進(jìn)程間通信 IPC 等豐富的功能特性。

Swoole4.0 支持了類似 Go 語(yǔ)言的協(xié)程,可以使用完全同步的代碼實(shí)現(xiàn)異步程序。PHP 代碼無(wú)需額外增加任何 關(guān)鍵詞,底層自動(dòng)進(jìn)行協(xié)程調(diào)度,實(shí)現(xiàn)異步 IO。