• swoole流程图


    程图,便于以后回忆下

    总结几点如下:

    首先主进程监听pipe_master事件,

    子进程监听pipe_worker事件

    通过主进程派生的线程 

    swReactorThread *thread = swServer_get_thread(serv, reactor_id);

    swReactor *reactor = &thread->reactor;

    reactor主要监听的句柄有accept的new_fd,以及主进程的pipe_master管道fd

    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, &notify_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
  • 相关阅读:
    令我印象最深刻的三个老师
    硬盘大于2T安装CentOS7.X时要注意分区
    Linux网卡配置
    Python13:文件操作
    Python12:集合
    Python11:字典
    Python10:String字符串
    Python09:元组
    Python08:列表
    Python07:模块初识
  • 原文地址:https://www.cnblogs.com/sandea/p/11770640.html
Copyright © 2020-2023  润新知