程圖,便於之後回憶下react
總結幾點以下:緩存
首先主進程監聽pipe_master事件,swoole
子進程監聽pipe_worker事件異步
經過主進程派生的線程 tcp
swReactorThread *thread = swServer_get_thread(serv, reactor_id);oop
swReactor *reactor = &thread->reactor;spa
reactor主要監聽的句柄有accept的new_fd,以及主進程的pipe_master管道fd.net
reactor->setHandle(reactor, SW_FD_CLOSE, swReactorThread_onClose); reactor->setHandle(reactor, SW_FD_UDP, swReactorThread_onPackage);
/** * receive data from worker process pipe */
reactor->setHandle(reactor, SW_FD_PIPE, swReactorThread_onPipeReceive);
當子進程處理完數據要發送給客戶端的時候,就會往pipe_worker寫數據,此時會觸發pipe_master的讀操做線程
將獲取的數據直接發送給客戶端,若是寫入失敗,就會將數據寫入到conn->out_buffer中進行緩存,而且會add
if (reactor->set(reactor, fd, SW_EVENT_TCP | SW_EVENT_WRITE | SW_EVENT_READ) < 0 && (errno == EBADF || errno == ENOENT))
add的這個事件意味着會觸發下面所介紹的
/** * [ReactorThread] worker pipe can write. */
reactor->setHandle(reactor, SW_FD_PIPE | SW_EVENT_WRITE, swReactorThread_onPipeWrite);
thread->reactor.add(&thread->reactor, pipe_fd, SW_FD_PIPE | SW_EVENT_WRITE);
其中//上面介紹的swReactorThread_onPipeReceive寫入失敗後會觸發 reactor->setHandle(reactor, SW_FD_TCP | SW_EVENT_WRITE, swReactorThread_onWrite);
//tcp receive設計
//Thread mode must copy the data. //will free after onFinish if (serv->open_eof_check) {
將數據緩存在conn->in_buffer字段中 reactor->setHandle(reactor, SW_FD_TCP, swReactorThread_onReceive_buffer_check_eof); } else if (serv->open_length_check) {
數據緩存在conn->object字段中 reactor->setHandle(reactor, SW_FD_TCP, swReactorThread_onReceive_buffer_check_length); } else if (serv->open_http_protocol) {
數據緩存在conn->object字段中 reactor->setHandle(reactor, SW_FD_TCP, swReactorThread_onReceive_http_request); } else { reactor->setHandle(reactor, SW_FD_TCP, swReactorThread_onReceive_no_buffer); }
第一個觸發點就是當主進程
ret = serv->reactor_threads[reactor_id].reactor.add(&(serv->reactor_threads[reactor_id].reactor), new_fd, SW_FD_TCP | SW_EVENT_READ);
swReactorThread_onReceive_http_request等而後介紹子進程的pipe_worker
SwooleG.main_reactor->add(SwooleG.main_reactor, pipe_worker, SW_FD_PIPE);
/** * receive data from reactor */
SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_PIPE, swWorker_onPipeReceive);
主進程accept數據後就寫入pipe_master從而觸發子進程的
SW_EVENT_PACKAGE_END
當
/** * pipe can write. */
SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_PIPE | SW_EVENT_WRITE, swWorker_onPipeWrite);
而後添加句柄SwooleG.main_reactor->add(SwooleG.main_reactor, pipefd, SW_FD_PIPE | SW_EVENT_WRITE);
其中swoole有ontask的執行任務功能,在我看來和上述的子進程模式同樣,只不過單獨開闢了一堆子進程來處理所謂你須要執行「任務」功能而設計,在我看來事相同實現方式處理不一樣需求
factory->notify(&serv->factory, ¬ify_ev);
上面介紹了不少將數據緩存的位置好比conn->in_buffer, conn->object, thread->buffer_pipe, p->worker_buffer,其中前兩個你們須要注意的是conn是具體某個鏈接,而且是對外的,由於因爲外界鏈接咱們沒法預計,因此用了異步模型,爲了區分每一個鏈接過來的數據就必須用惟一的conn來關聯,後兩組是每組進程一個緩存池,由於後兩組是管道通訊,在咱們完整拿到了某個conn的數據,以及完整的要發送client完整數據,對咱們來講是可控的,因此就能夠一會兒發送出去,保證這批發送時同一個鏈接的數據,不會有不一樣鏈接數據交叉的狀況,因此就要求咱們管道之間通訊必須保證是同一個鏈接的完整數據,不然緩衝區就亂了,這也是爲何數據包能夠分爲start,和end的緣由,由於必定發過來是同一個鏈接數據 ,
read(event->fd, &task, sizeof(task)
這樣寫應該是有考慮吧,我是百思不得其解,不知道誰能解答一下
核心四個文件Server.c FactoryProcess.c Worker.c RectorThread.c
factory->object = object; factory->dispatch = swFactoryProcess_dispatch;
/**
factory->finish = swFactoryProcess_finish;
可是主進程是從新賦值的,這點須要注意
//主進程須要設置爲直寫模式 factory->finish = swFactory_finish;其中關閉鏈接在此實現
/** * worker main loop */
SwooleG.main_reactor->add(SwooleG.main_reactor, pipe_worker, SW_FD_PIPE);
SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_PIPE, swWorker_onPipeReceive);
//write事件爲了write失敗發送緩衝區而創建的事件p->worker_buffer SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_PIPE | SW_EVENT_WRITE, swWorker_onPipeWrite);
/** * proxy模式 * 在單獨的n個線程中接受維持TCP鏈接 */
reactor->setHandle(reactor, SW_FD_CLOSE, swReactorThread_onClose); reactor->setHandle(reactor, SW_FD_UDP, swReactorThread_onPackage);
//線程接受work輸出給client的內容 reactor->setHandle(reactor, SW_FD_PIPE, swReactorThread_onPipeReceive); reactor->setHandle(reactor, SW_FD_PIPE | SW_EVENT_WRITE, swReactorThread_onPipeWrite);
//write事件爲了write失敗發送緩衝區而創建的事件conn_buffer
reactor->setHandle(reactor, SW_FD_TCP | SW_EVENT_WRITE, swReactorThread_onWrite);
//下面是線程接受accept的fd套接字
reactor->setHandle(reactor, SW_FD_TCP, swReactorThread_onReceive_buffer_check_eof);
reactor->setHandle(reactor, SW_FD_TCP, swReactorThread_onReceive_buffer_check_length); reactor->setHandle(reactor, SW_FD_TCP, swReactorThread_onReceive_http_request); reactor->setHandle(reactor, SW_FD_TCP, swReactorThread_onReceive_no_buffer); http://blog.csdn.net/xiaolei1982/article/details/41853583