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, ¬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
swoole流程图的更多相关文章
- swoole详解
1.swoole结构图 2.swoole流程图 3.详细流程图 3.1.Master:处理核心事件驱动(主进程)3.2.Reactor: 处理TCP连接,收发数据的线程.Swoole的主线程在Acce ...
- 使用php+swoole对client数据实时更新(下)
上一篇提到了swoole的基本使用,现在通过几行基本的语句来实现比较复杂的逻辑操作: 先说一下业务场景.我们目前的大多数应用都是以服务端+接口+客户端的方式去协调工作的,这样的好处在于不论是处在何种终 ...
- 使用php+swoole对client数据实时更新(二) (转)
上一篇提到了swoole的基本使用,现在通过几行基本的语句来实现比较复杂的逻辑操作: 先说一下业务场景.我们目前的大多数应用都是以服务端+接口+客户端的方式去协调工作的,这样的好处在于不论是处在何种终 ...
- nginx、swoole高并发原理初探
阅前热身 为了更加形象的说明同步异步.阻塞非阻塞,我们以小明去买奶茶为例. 同步与异步 同步与异步的重点在消息通知的方式上,也就是调用结果通知的方式. 同步:当一个同步调用发出去后,调用者要一直等待调 ...
- swoole深入学习 2. tcp Server和tcp Client
这节来学习Swoole最基础的Server和Client.会通过创建一个tcp Server来讲解. server <?php class Server { private $serv; pub ...
- 基于SWOOLE的分布式SOCKET消息服务器架构
消息服务器使用socket,为避免服务器过载,单台只允许500个socket连接,当一台不够的时候,扩充消息服务器是必然,问题来了,如何让链接在不同消息服务器上的用户可以实现消息发送呢? 要实现消息互 ...
- 分布式ID生成器PHP+Swoole实现(上) - 实现原理
1.发号器介绍 什么是发号器? 全局唯一ID生成器,主要用于分库分表唯一ID,分布式系统数据的唯一标识. 是否需要发号器? 1)是否需要全局唯一. 分布式系统应该不受单点递增ID限制,中心式的会涉及到 ...
- Swoole引擎原理的快速入门干货
更多内容,欢迎关注微信公众号:全菜工程师小辉~ 过去一年使用PHP和Java两种技术栈完成了一个游戏服务器项目.由于项目中有高频的网络请求,所以PHP技术栈尝试使用Swoole引擎(基于事件的高性能异 ...
- swoole与php协程实现异步非阻塞IO开发
“协程可以在遇到阻塞的时候中断主动让渡资源,调度程序选择其他的协程运行.从而实现非阻塞IO” 然而php是不支持原生协程的,遇到阻塞时如不交由异步进程来执行是没有任何意义的,代码还是同步执行的,如下所 ...
随机推荐
- sqlserver数据,将一行某一列字符串的值用“_”分割分别填充到这一行的其他列
分割字符到列DECLARE @a VARCHAR(10)SET @a ='00G-2-1102'SELECT CHARINDEX('-',@a,CHARINDEX('-',@a))SELECT CHA ...
- Python爬虫系列:五、正则表达式
1.了解正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑. 正则表达式 ...
- Java开发环境之Solr
查看更多Java开发环境配置,请点击<Java开发环境配置大全> 玖章:Solr安装教程 1)官网下载Solr安装包 http://lucene.apache.org/solr/downl ...
- maven学习笔记四(聚合和继承)
聚合 现在假如,我创建了3个maven项目, user-core.2.user-log,3.user-service 这个时候,假如我们要打包这些项目,要一个一个来,会很麻烦.那么我们有没有更好的办法 ...
- Linux忘记root密码,进入单用户模式,切换运行级别,切换用户
切换用户指令 su - 用户名 当高权限用户切换到低权限用户的时候不需要密码 反之低权限切换到高权限用户需要高权限用户的密码 用exit可以退出当前用户,回到上一个用户 而且它的退出是一层一层退出的: ...
- Linux一些服务的启动命令
http:服务service httpd start 启动 service httpd restart 重新启动 service httpd stop 停止服务 启动ssh服务 # /etc/init ...
- 逆向破解之160个CrackMe —— 006
CrackMe —— 006 160 CrackMe 是比较适合新手学习逆向破解的CrackMe的一个集合一共160个待逆向破解的程序 CrackMe:它们都是一些公开给别人尝试破解的小程序,制作 c ...
- Android Handler机制彻底梳理
Android的消息机制其实也就是Handler相关的机制,对于它的使用应该熟之又熟了,而对于它的机制的描述在网上也一大堆[比如15年那会在网上抄了一篇https://www.cnblogs.com/ ...
- Java调用Kotlin程序深度解析
异常: 在之前我们已经学习在Kotlin中的所有异常都是运行期的,而不像Java分为运行期和非运行期,下面用代码来演示一下,先建一个Java的异常: 然后在Kotlin中来调用一下该Java中的方法 ...
- 【转】libgo
原文:https://blog.csdn.net/libaineu2004/article/details/80554870 ------------------------------------- ...