# 在php-fpm或apache中使用swoole
swoole中絕大部分的模塊只能用于CLI命令行環境,只有同步阻塞的swoole_client可以用于php-fpm或apache環境。
[TOC=2,3]
## **同步swoole_client**
~~~php
$client = new swoole_client(SWOOLE_SOCK_TCP); //同步阻塞
$client->connect('127.0.0.1', 9501) or die("connect failed\n");
$client->send(str_repeat("A", 600));
$data = $client->recv(700, 0) or die("recv failed\n");
echo "recv: " . $data . "\n";
~~~
## **在php-fpm/apache中創建長連接**
~~~php
$cli = new swoole_client(SWOOLE_TCP | SWOOLE_KEEP);
~~~
加入SWOOLE_KEEP標志后,創建的TCP連接在PHP請求結束或者調用`$cli->close`時并不會關閉。下一次執行connect調用時會復用上一次創建的連接。長連接保存的方式默認是以ServerHost:ServerPort為key的。可以再第3個參數內指定key。
* SWOOLE_KEEP只允許用于同步客戶端
* $swoole_client->close(true)用于關閉長連接
> swoole_client在unset時會自動調用close方法關閉socket
> SWOOLE_KEEP長連接模式在1.6.12后可用,長連接的$key參數在1.7.5后增加
## **在php-fpm/apache中使用task功能**
AsyncTask是swoole提供一套生產者消費者模型,可以方便地將一個慢速任務投遞到隊列,由進程池異步地執行。task功能目前只能在swoole_server中使用。1.9.0版本提供了RedisServer框架,可以基于RedisServer和Task實現一個Server程序,在php-fpm或apache中直接調用Redis擴展就可以使用swoole的task功能了。
創建RedisServer
~~~
use Swoole\Redis\Server;
$server = new Server("127.0.0.1", 9501, SWOOLE_BASE);
$server->set(array(
'task_worker_num' => 32,
'worker_num' => 1,
));
$server->setHandler('LPUSH', function ($fd, $data) use ($server) {
$taskId = $server->task($data);
if ($taskId === false)
{
return Server::format(Server::ERROR);
}
else
{
return Server::format(Server::INT, $taskId);
}
});
$server->on('Finish', function() {
});
$server->on('Task', function ($serv, $taskId, $workerId, $data) {
//處理任務
});
$server->start();
~~~
* 如果是本機調用可以監聽UnixSocket,局域網內調用需要使用IP:PORT
* Task中$data就是客戶端投遞的數據
* 其他語言也可以使用Redis客戶端投遞任務
* 可以根據Task任務執行的速度調節task_worker_num控制啟動的進程數量,這些進程是由swoole底層負責管理的,在發生致命錯誤或進程退出后底層會重新創建新的任務進程
**投遞任務**
php-fpm/apache中投遞任務
~~~php
$redis = new Redis;
$redis->connect('127.0.0.1', 9501);
$taskId = $redis->lpush("myqueue", json_encode(array("hello", "swoole")));
~~~
注意這個RedisServer并不是一臺真正的Redis服務器,它只支持LPUSH一個指令。
## **在php-fpm/apache中使用swoole_client_select實現并行處理**
swoole_client的并行處理中用了select來做IO事件循環。
函數原型:
~~~
int swoole_client_select(array &$read, array &$write, array &$error, float $timeout);
~~~
* swoole_client_select接受4個參數,$read, $write, $error 分別是可讀/可寫/錯誤的文件描述符。
* 這3個參數必須是數組變量的引用。數組的元素必須為swoole_client對象。 1.8.6或更高版本可以支持swoole_process對象
* $timeout參數是select的超時時間,單位為秒,接受浮點數。
* 調用成功后,會返回事件的數量,并修改$read/$write/$error數組。使用foreach遍歷數組,然后執行$item->recv/$item->send來收發數據。或者調用$item->close()或unset($item)來關閉socket。
* swoole_client_select返回0表示在規定的時間內,沒有任何IO可用,select調用已超時。
swoole_client用法
~~~php
$clients = array();
for($i=0; $i< 20; $i++)
{
$client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC); //同步阻塞
$ret = $client->connect('127.0.0.1', 9501, 0.5, 0);
if(!$ret)
{
echo "Connect Server fail.errCode=".$client->errCode;
}
else
{
$client->send("HELLO WORLD\n");
$clients[$client->sock] = $client;
}
}
while (!empty($clients))
{
$write = $error = array();
$read = array_values($clients);
$n = swoole_client_select($read, $write, $error, 0.6);
if ($n > 0)
{
foreach ($read as $index => $c)
{
echo "Recv #{$c->sock}: " . $c->recv() . "\n";
unset($clients[$c->sock]);
}
}
}
~~~
- swoole簡介
- swoole功能概述
- 序章
- 開發必讀
- 1 環境搭建
- 1.1 環境搭建
- 1.2 搭建Echo服務器
- 2 初識Swoole
- 2.1 Worker進程
- 2.2 TaskWorker進程
- 2.3 Timer定時器
- 2.4 Process進程
- 2.5 Table內存表
- 2.6 多端口監聽
- 2.7 sendfile文件支持
- 2.8 SSL支持
- 2.9 熱重啟
- 2.10 http_server
- 附錄*server配置
- 附錄*server函數
- 附錄*server屬性
- 附錄*server回調函數
- 附錄*server高級特性
- 心跳檢測
- 3 Swoole協議
- 3.1 EOF協議
- 3.2 固定包頭協議
- 3.3 Http協議
- 3.4 WebSocket協議
- 3.5 MTQQ協議
- 內置http_server
- 內置websocket_server
- Swoole\Redis\Server
- 4 Swoole異步IO
- 4.1 AsyncIO
- 異步文件系統IO
- swoole_async_readfile
- swoole_async_writefile
- swoole_async_read
- swoole_async_write
- 5 swoole異步客戶端
- ws_client
- http_client
- mysql_client
- redis_client
- tcp_client
- http2_client
- 6 swoole協程
- Swoole\Coroutine\Http\Client
- Swoole\Coroutine\MySQL
- Swoole\Coroutine\Redis
- Coroutine\PostgreSQL
- Swoole\Coroutine\Client
- Swoole\Coroutine\Socket
- Swoole\Coroutine\Channel
- Coroutine
- Swoole\Coroutine::create
- Swoole\Coroutine::resume
- Swoole\Coroutine::suspend
- Swoole\Coroutine::sleep
- Coroutine::getaddrinfo
- Coroutine::gethostbyname
- swoole_async_dns_lookup_coro
- Swoole\Coroutine::getuid
- getDefer
- setDefer
- recv
- Coroutine::stats
- Coroutine::fread
- Coroutine::fget
- Coroutine::fwrite
- Coroutine::readFIle
- Coroutine::writeFIle
- Coroutine::exec
- 7 swoole_process
- process::construct
- process::start
- process::name
- process::signal
- process::setaffinity
- process::exit
- process::kill
- process::daemon
- process->exec
- process::wait
- process::alarm
- 8 swoole定時器
- swoole_timer_tick
- swoole_timer_after
- swoole_timer_clear
- 9 swoole_event
- swoole_event_add
- swoole_event_set
- swoole_event_del
- swoole_event_wait
- swoole_event_defer
- swoole_event_write
- swoole_event_exit
- swoole提供的function
- 常見問題
- 客戶端鏈接失敗原因
- 如何設置進程數
- 如何實現異步任務
- 如何選擇swoole三種模式
- php中哪些函數是阻塞的
- 是否可以共用1個redis或mysql連接
- 如何在回調函數中訪問外部的變量
- 為什么不要send完后立即close
- 不同的Server程序實例間如何通信
- MySQL的連接池、異步、斷線重連
- 在php-fpm或apache中使用swoole
- 學習Swoole需要掌握哪些基礎知識
- 在phpinfo中有在php-m中沒有
- 同步阻塞與異步非阻塞選擇
- CURL發送POST請求服務器端超時
- 附錄
- 預定義常量
- 內核參數調優
- php四種回調寫法
- 守護進程程序常用數據結構
- swoole生命周期
- swoole_server中內存管理機制
- 使用jemalloc優化swoole內存分配性能
- Reactor、Worker、Task的關系
- Manager進程
- Swoole的實現
- Reactor線程
- 安裝擴展
- swoole-worker手冊
- swoole相關開源項目
- 寫在后面的話
- 版本更新記錄
- 4.0