安裝步驟以下(推薦把安裝文件下載到 /usr/local/src 目錄下): step 1: wget --no-check-certificate https://github.com/swoole/swoole-src/archive/v1.9.13.tar.gz step 2: tar zxf v1.9.13.tar.gz step 3: cd swoole-src-1.9.13 step 4: phpize step 5: ./configure --with-php-config=/usr/local/php/bin/php-config step 6: make && make install step 7: 修改 php.ini ,加入 extension=swoole.so ,而後重啓 php-fpm step 8: 執行 php --info | grep swoole 查看設置是否生效 ############################ 消費者,文件名《server.php》 ############################ <?php class Server { private $serv; private $logFile; public function __construct() { $this->serv = new swoole_server('0.0.0.0', 9501); // 容許全部IP訪問 $this->serv->set([ 'worker_num' => 4, // 通常設置爲服務器CPU數的1-4倍 'task_worker_num' => 1, // task進程的數量(通常任務都是同步阻塞的,能夠設置爲單進程單線程) 'daemonize' => true, // 以守護進程執行 'package_eof' => PHP_EOL, // 設置EOF 'open_eof_split' => true, // 按照EOF進行分包,防止TCP粘包 // 'task_ipc_mode' => 1, // 使用unix socket通訊,默認模式 // 'log_file' => '/data/log/queue.log' , // swoole日誌 // 數據包分發策略(dispatch_mode=1/3時,底層會屏蔽onConnect/onClose事件, // 緣由是這2種模式下沒法保證onConnect/onClose/onReceive的順序,非請求響應式的服務器程序,請不要使用模式1或3) // 'dispatch_mode' => 2, // 固定模式,根據鏈接的文件描述符分配worker。這樣能夠保證同一個鏈接發來的數據只會被同一個worker處理 ]); $this->logFile = dirname(__FILE__).'/log.txt'; // 以守護進程執行的時候,要絕對路徑 $this->serv->on('Receive', [$this, 'onReceive']); $this->serv->on('Task', [$this, 'onTask']); $this->serv->on('Finish', [$this, 'onFinish']); $this->serv->start(); } /** * 接收到數據時回調此函數,發生在worker進程中 * $server,swoole_server對象 * $fd,TCP客戶端鏈接的文件描述符 * $from_id,TCP鏈接所在的Reactor線程ID * $data,收到的數據內容,多是文本或者二進制內容 */ public function onReceive($serv, $fd, $from_id, $data ) { $str = "=========== onReceive ============ \n"; $str .= "Get Message From Client $fd:$data \n"; error_log($str, 3, $this->logFile); $serv->task( $data ); } /** * 在task_worker進程內被調用。worker進程可使用swoole_server_task函數向task_worker進程投遞新的任務。當前的Task進程在調用onTask回調函數時會將進程狀態切換爲忙碌, * 這時將再也不接收新的Task,當onTask函數返回時會將進程狀態切換爲空閒而後繼續接收新的Task。 * $task_id是任務ID,由swoole擴展內自動生成,用於區分不一樣的任務。$task_id和$src_worker_id組合起來纔是全局惟一的,不一樣的worker進程投遞的任務ID可能會有相同 * $src_worker_id來自於哪一個worker進程 * $data 是任務的內容 */ public function onTask($serv, $task_id, $src_worker_id, $data) { $data = trim($data); // 刪除EOF $array = json_decode( $data , true ); $str = "=========== onTask ============ \n"; $str .= var_export($array, 1); error_log($str, 3 , $this->logFile); return $array; } /** * 當worker進程投遞的任務在task_worker中完成時,task進程會經過swoole_server->finish()方法將任務處理的結果發送給worker進程 * $task_id是任務的ID * $data是任務處理的結果內容(也就是onTask()函數,中return的值) */ public function onFinish($serv, $task_id, $data) { $str = "=========== onFinish ============ \n"; $str .= "Task $task_id finish ! \n"; $str .= var_export($data, 1); error_log($str, 3, $this->logFile); } } $server = new Server(); ############################ 生產者,文件名《client.php》 ############################ <?php class Client { private function _sendData($data) { $client = new \swoole_client(SWOOLE_SOCK_TCP); $client->connect('127.0.0.1', 9501, 1); $client->send($data.PHP_EOL); // 加入PHP_EOL做爲結束分隔符(EOF) } public function run() { for($i=0; $i<10; $i++) { $data = [ 'time' => rand(1000, 9999), 'id' => $i ]; $jsonData = json_encode($data); // 每次循環都要開啓新的鏈接,不然隊列會出問題 $this->_sendData($jsonData); } } } ############################ 華麗的分割線 ############################ 先執行 php server.php (執行一次,會以守護進程運行) 而後再執行 php client.php # 內核參數調整(關鍵步驟) http://wiki.swoole.com/wiki/page/p-server/sysctl.html # swoole 離線手冊,裏面有更多的示例 https://github.com/smalleyes/swoole-chm