做者:施洪寶php
swoole是面向生產環境的php異步網絡通訊引擎, php開發人員能夠利用swoole開發出高性能的server服務。swoole的server部分, 內容不少, 也涉及不少的知識點, 本文僅對其server進行簡單的概述, 具體的實現細節在後續的文章中再進行詳細介紹。html
int socketpair(int domain, int type, int protocol, int sv[2]); //domain表示協議簇 //type表示類型 //protocol表示協議, SOCK_STREAM表示流協議(相似tcp), SOCK_DGRAM表示數據報協議(相似udp) //sv用於存儲創建的套接字對, 也就是兩個套接字文件描述符 //成功返回0, 不然返回-1, 能夠從errno獲取錯誤信息
<?php //建立server $serv = new Swoole\Server('0.0.0.0', 9501, SWOOLE_PROCESS, SWOOLE_SOCK_TCP); //設置server的參數 $serv->set(array( 'reactor_num' => 2, //reactor thread num 'worker_num' => 3, //worker process num )); //設置事件回調 $serv->on('connect', function ($serv, $fd){ echo "Client:Connect.\n"; }); $serv->on('receive', function ($serv, $fd, $reactor_id, $data) { $serv->send($fd, 'Swoole: '.$data); $serv->close($fd); }); $serv->on('close', function ($serv, $fd) { echo "Client: Close.\n"; }); //啓動server $serv->start();
//php 代碼中$serv->start(); 會調用函數, 進行server start int swServer_start(swServer *serv); // 該函數首先進行必要的參數檢查 static int swServer_start_check(swServer *serv); // 其中有, if (serv->worker_num < serv->reactor_num) { serv->reactor_num = serv->worker_num; }//也就是說reactor_num <= worker_num //以後執行factory start, 也就是swFactoryProcess_start函數, 該函數會fork出manager進程, manager進程進而fork出worker進程以及task_worker進程 if (factory->start(factory) < 0) { return SW_ERR; } //而後主進程的主線程生成reactor線程 if (serv->factory_mode == SW_MODE_BASE) { ret = swReactorProcess_start(serv); } else { ret = swReactorThread_start(serv); }
static int swFactoryProcess_start(swFactory *factory); //swFactoryProcess_start會調用swManager_start生成manager進程 int swManager_start(swServer *serv); // manager進程會fork出worker進程以及task_worker進程
//主線程執行swReactorThread_start, 建立出reactor線程 int swReactorThread_start(swServer *serv);
swoole process模式結構以下圖所示,react
//包頭 typedef struct _swDataHead { int fd; uint32_t len; int16_t from_id; uint8_t type; uint8_t flags; uint16_t from_fd; #ifdef SW_BUFFER_RECV_TIME double time; #endif } swDataHead; //reactor線程向worker進程發送的數據, 也就是worker進程收到的數據包 typedef struct { swDataHead info; char data[SW_IPC_BUFFER_SIZE]; } swEventData; //worker進程向reactor線程發送的數據, 也就是reactor線程收到的數據包 typedef struct { swDataHead info; char data[0]; } swPipeBuffer;
//主線程執行epoll_ctl將fd(新接受的鏈接)加入到reactor線程的監聽隊列中 epoll_ctl(epfd, fd, ...); //對應的reactor線程若是正在執行 epoll_wait(epfd, ...);
//fork manager進程 #0 0x00007ffff67dae64 in fork () from /lib64/libc.so.6 #1 0x00007ffff553888a in swoole_fork () at /root/code/swoole-src/src/core/base.c:186 #2 0x00007ffff556afb8 in swManager_start (serv=serv@entry=0x1353f60) at /root/code/swoole-src/src/server/manager.cc:164 #3 0x00007ffff5571dde in swFactoryProcess_start (factory=0x1353ff8) at /root/code/swoole-src/src/server/process.c:198 #4 0x00007ffff556ef8b in swServer_start (serv=0x1353f60) at /root/code/swoole-src/src/server/master.cc:651 #5 0x00007ffff55dc808 in zim_swoole_server_start (execute_data=<optimized out>, return_value=0x7fffffffac50) at /root/code/swoole-src/swoole_server.cc:2946 #6 0x00000000007bb068 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /root/php-7.3.3/Zend/zend_vm_execute.h:980 #7 execute_ex (ex=0x7ffff7f850a8) at /root/php-7.3.3/Zend/zend_vm_execute.h:55485 #8 0x00000000007bbf58 in zend_execute (op_array=op_array@entry=0x7ffff5e7b340, return_value=return_value@entry=0x7ffff5e1d030) at /root/php-7.3.3/Zend/zend_vm_execute.h:60881 #9 0x0000000000737554 in zend_execute_scripts (type=type@entry=8, retval=0x7ffff5e1d030, retval@entry=0x0, file_count=file_count@entry=3) at /root/php-7.3.3/Zend/zend.c:1568 #10 0x00000000006db4d0 in php_execute_script (primary_file=primary_file@entry=0x7fffffffd050) at /root/php-7.3.3/main/main.c:2630 #11 0x00000000007be2f5 in do_cli (argc=2, argv=0x1165cd0) at /root/php-7.3.3/sapi/cli/php_cli.c:997 #12 0x000000000043fc1f in main (argc=2, argv=0x1165cd0) at /root/php-7.3.3/sapi/cli/php_cli.c:1389 // pthread_create reactor線程 #0 0x00007ffff552e960 in pthread_create@plt () from /usr/local/lib/php/extensions/no-debug-non-zts-20180731/swoole.so #1 0x00007ffff5576959 in swReactorThread_start (serv=0x1353f60) at /root/code/swoole-src/src/server/reactor_thread.c:883 #2 0x00007ffff556f006 in swServer_start (serv=0x1353f60) at /root/code/swoole-src/src/server/master.cc:670 #3 0x00007ffff55dc808 in zim_swoole_server_start (execute_data=<optimized out>, return_value=0x7fffffffac50) at /root/code/swoole-src/swoole_server.cc:2946 #4 0x00000000007bb068 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /root/php-7.3.3/Zend/zend_vm_execute.h:980 #5 execute_ex (ex=0x7fffffffab10) at /root/php-7.3.3/Zend/zend_vm_execute.h:55485 #6 0x00000000007bbf58 in zend_execute (op_array=op_array@entry=0x7ffff5e7b340, return_value=return_value@entry=0x7ffff5e1d030) at /root/php-7.3.3/Zend/zend_vm_execute.h:60881 #7 0x0000000000737554 in zend_execute_scripts (type=type@entry=8, retval=0x7ffff5e1d030, retval@entry=0x0, file_count=file_count@entry=3) at /root/php-7.3.3/Zend/zend.c:1568 #8 0x00000000006db4d0 in php_execute_script (primary_file=primary_file@entry=0x7fffffffd050) at /root/php-7.3.3/main/main.c:2630 #9 0x00000000007be2f5 in do_cli (argc=2, argv=0x1165cd0) at /root/php-7.3.3/sapi/cli/php_cli.c:997 #10 0x000000000043fc1f in main (argc=2, argv=0x1165cd0) at /root/php-7.3.3/sapi/cli/php_cli.c:1389
//base 模式下的啓動 #0 0x00007ffff67dae64 in fork () from /lib64/libc.so.6 #1 0x00007ffff553888a in swoole_fork () at /root/code/swoole-src/src/core/base.c:186 #2 0x00007ffff5558557 in swProcessPool_spawn (pool=pool@entry=0x7ffff2d2a308, worker=0x7ffff2d2a778) at /root/code/swoole-src/src/network/process_pool.c:392 #3 0x00007ffff5558710 in swProcessPool_start (pool=0x7ffff2d2a308) at /root/code/swoole-src/src/network/process_pool.c:227 #4 0x00007ffff55741cf in swReactorProcess_start (serv=0x1353f60) at /root/code/swoole-src/src/server/reactor_process.cc:176 #5 0x00007ffff556f21d in swServer_start (serv=0x1353f60) at /root/code/swoole-src/src/server/master.cc:666 #6 0x00007ffff55dc808 in zim_swoole_server_start (execute_data=<optimized out>, return_value=0x7fffffffac50) at /root/code/swoole-src/swoole_server.cc:2946 #7 0x00000000007bb068 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /root/php-7.3.3/Zend/zend_vm_execute.h:980 #8 execute_ex (ex=0x7ffff2d2a308) at /root/php-7.3.3/Zend/zend_vm_execute.h:55485 #9 0x00000000007bbf58 in zend_execute (op_array=op_array@entry=0x7ffff5e7b340, return_value=return_value@entry=0x7ffff5e1d030) at /root/php-7.3.3/Zend/zend_vm_execute.h:60881 #10 0x0000000000737554 in zend_execute_scripts (type=type@entry=8, retval=0x7ffff5e1d030, retval@entry=0x0, file_count=file_count@entry=3) at /root/php-7.3.3/Zend/zend.c:1568 #11 0x00000000006db4d0 in php_execute_script (primary_file=primary_file@entry=0x7fffffffd050) at /root/php-7.3.3/main/main.c:2630 #12 0x00000000007be2f5 in do_cli (argc=2, argv=0x1165cd0) at /root/php-7.3.3/sapi/cli/php_cli.c:997 #13 0x000000000043fc1f in main (argc=2, argv=0x1165cd0) at /root/php-7.3.3/sapi/cli/php_cli.c:1389