Swoole从入门到入土(9)——TCP服务器[协程风格]
上一篇,我们一起初步接触了协程。我相信只有一节的讨论,很多小伙伴对于“协程”与“线程”的区分可能还有点模糊。我们这里以两者的比较作为本篇开头,进行一番比较。
首先,“协程”与“线程”的任务调度机制不一样。“协程”重在“协调”,“线程”重在“抢占”。
举个例子:现在有一个任务,需要5个“子协程”同时进行处理,那么执行顺序是:子协程1执行->子协程1暂停->子协程2执行->子协程2暂停……顺序执行,直到结束。所以,协程的特点是某个协程让出时间片后,下一个协程会接上;如果这个协程还在阻塞中,会再次移交给下一个协程。这样往复执行,直到结束。
同样的,如果现在有一个任务,需要5个“线程”同时执行,那么执行顺序是,主线程同时开辟启动5个线程,这5个线程哪一个先执行,当先执行的线程让出时间片后,接下来由哪一个线程接上,这些完全听天由命。所以线程的执行才叫做“抢占式”,直到任务结束。
其次,“协程”与“线程”解决的事情不一样。“协程”解决的的是“并发”问题,“线程”解决的是“并行”问题。
举个栗子,我们的服务器需要支撑500人同时访问,以大名鼎鼎的TOMCAT为例,正常情况下会开辟300个线程进行处理。某个线程一旦接收了请求就会进行阻塞,在处理完成之前就不会再接收第二个请求,这就决定了这时TOMCAT只能“并行”支持300人同时访问,另外的200人只能收到500的报错。但是这里存在一个问题,500人的请求业务并不是全都是阻塞行为(访问数据库、读写文件等),所以我们完全可以在一个线程中开辟N个协程,一个线程同时接受N个请求,对于有阻塞的业务请求进行等待直到业务完成,对于没有阻塞的请求,我们就可以立即响应,这样就可以将“并发”从300,提高到300*N(N>=2)。
当然,从上面这个栗子,我们可以看出“协程”针对的是IO密集型的业务(多阻塞),而线程针对的是计算密集型的业务。但我们不能简单认为IO密集型业务,协程开得越多越好。因为对于IO的处理也需要IO资源,如果同时接受太多的需要IO请求,服务器对于IO的处理在超时时间范围内无法处理完,同样会出现超时错误。
有了以上的比较,我们对于“协程”与“线程”的比较应该是更加明晰了。接下来,我们就一起进入协程风格的TCP服务器话题。先看以下这段代码:
//多进程管理模块
$pool = new Swoole\Process\Pool(2);
//让每个OnWorkerStart回调都自动创建一个协程
$pool->set(['enable_coroutine' => true]);
$pool->on('workerStart', function ($pool, $id) {
//每个进程都监听9501端口
$server = new Swoole\Coroutine\Server('127.0.0.1', '9501' , false, true); //收到15信号关闭服务
Swoole\Process::signal(SIGTERM, function () use ($server) {
$server->shutdown();
}); //接收到新的连接请求 并自动创建一个协程
$server->handle(function (Swoole\Coroutine\Server\Connection $conn) {
while (true) {
//接收数据
$data = $conn->recv();
if (empty($data)) {
$conn->close();
break;
} //发送数据
$conn->send('hello'); \Co::sleep(1);
}
}); //开始监听端口
$server->start();
});
$pool->start();
这是一段完整的协程风格TCP服务器的代码,对于这段代码涉及到的技术点进行以下讨论。
1、关于Swoole\Process\Pool
对于协程代码,我们一般需要一个“协程容器”,来保证一组协程的完整性。在swoole中,创建“协程容器”的方法有两种(编者注:官网写的是三种,但这里不考虑将异步风格转为协程风格的方式):
1) 调用管理模块 Process 和 Process\Pool 的 start 方法,指定构造函数的 enable_coroutine 参数,此种启动方式会在进程启动的时候创建协程容器。
2) 手动创建协程容器,即调用Co\run() 函数,或者使用Coroutine\Scheduler(这两者是一样的,前者是后者的简易调用)。
对于TCP服务器,我们需要并发,需要多个进程进行管理,所以选择了Swoole\Process\Pool(这个进程池的使用,后续我们会详细讨论)。
对于Pool初使化后,在子进程创建时(onWorkerStart事件触发),内部实例化了协程化的TCP服务器。
当$pool->start()调用后,这时会创建出2个子进程(Pool构造函数中传入的子进程数量),所以创建后共有3个进程。主进程进入wait状态,对子进程进行管理,一旦子进程退出,就会再进行启动。这时我们可以把onWorkerStart事件的处理函数看成是一个大的协程容器。
2、Swoole\Coroutine\Server->__construct
Swoole\Coroutine\Server->__construct(string $host, int $port = 0, bool $ssl = false, bool $reuse_port = false);
$host:监听的地址,有三种格式:0.0.0.0/127.0.0.1: IPv4 地址 || ::/::1: IPv6 地址 || unix:/tmp/test.sock: UnixSocket 地址
$port:监听的端口【如果为 0 将由操作系统随机分配一个端口】
$ssl:是否开启 SSL 加密
$reuse_port:是否开启端口重用
Swoole\Coroutine\Server 是一个完全协程化的类,用于创建协程 TCP 服务器,支持 TCP 和 unixSocket 类型。它与 Server 模块不同之处在于以下两点:
1) 动态创建销毁,在运行时可以动态监听端口,也可以动态关闭服务器;
2) 处理连接的过程是完全同步的,程序可以顺序处理 Connect、Receive、Close 事件
3、Swoole\Coroutine\Server->handle:设置连接处理函数,必须在 start() 之前设置处理函数
Swoole\Coroutine\Server->handle(callable $fn);
$fn:设置连接处理函数
注意:
-服务器在 Accept(建立连接) 成功后,会自动创建协程并执行 $fn
-$fn 是在新的子协程空间内执行,因此在函数内无需再次创建协程
-$fn 接受一个参数,类型为 Swoole\Coroutine\Server\Connection 对象
-可以使用 exportSocket() 得到当前连接的 Socket 对象
示例:
$server->handle(function (Swoole\Coroutine\Server\Connection $conn) {
while (true) {
$data = $conn->recv();
}
});
4、关于粘包处理Swoole\Coroutine\Server->set
Swoole\Coroutine\Server->set(array $options);
用法与异步风格的TCP服务器完全一致,如果已经遗忘的小伙伴,请点击这里
示例:
$server->set([
'open_eof_split' => true,
'package_eof' => "abc"
]);
如果客户端发送,1234abc5678abc,则服务端就会recv到两条数据,分别是1234abc和5678abc。
关于协程风格的TCP服务器就介绍到这里。如果想要了解协程风格的类Swoole\Coroutine\Server、Swoole\Coroutine\Server\Connection、Swoole\Process\Pool请阅读官网,这部分非常直观没有什么太多难点。
--------------------------- 我是可爱的分割线 ----------------------------
最后博主借地宣传一下,漳州编程小组招新了,这是一个面向漳州青少年信息学/软件设计的学习小组,有意向的同学点击链接,联系我吧。
Swoole从入门到入土(9)——TCP服务器[协程风格]的更多相关文章
- 【Swoole】简单安装与创建TCP服务器
pecl install swoole PHP的异步.并行.高性能网络通信引擎,使用纯C语言编写,提供了php语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,异步Redis,数据 ...
- php的异步非阻塞swoole模块使用(一)实现简易tcp服务器--服务端
绑定tcp服务器的地址 $swserver = new swoole_server("127.0.0.1",9501); 设置tcp服务器装机容量(太危言耸听了-其实就是设置属性) ...
- Swoole 中使用通道(Channel)实现协程间通讯(消息队列)
通道 Coroutine\Channel 使用本地内存,不同的进程之间内存是隔离的. 只能在同一进程的不同协程内进行 push 和 pop 操作. Co::set(['hook_flags'=> ...
- flask服务器 + 协程 + 爬虫 + ui自动化
公司有个爬取的需求,要求持续性爬取,需要永久性地挂载到目标网站上,每天爬一次里面的数据.数据有下载表格的,我通过ui自动化点击拿到数据:还有一部分数据是几乎所有的图片信息,信息量近百万,这部分用scr ...
- HTTP从入门到入土(3)——TCP三次握手
TCP三次握手 客户端与服务器之间互相发送HTTP请求响应之前需要先进行TCP连接,因为HTTP是一个无连接.无状态协议,不存在连接的概念,只有请求和响应的概念.而请求和响应实际上只是数据包,他们需要 ...
- php的异步非阻塞swoole模块使用(一)实现简易tcp服务器--客户端
//实例化一个swoole客户端 $swclient = new swoole_client(SWOOLE_SOCK_TCP); //建立连接---如果连接无效则退出 )){ echo "连 ...
- Web服务器-并发服务器-协程 (3.4.2)
@ 目录 1.分析 2.代码 关于作者 1.分析 随着网站的用户量越来愈多,通过多进程多线程的会力不从心 使用协程可以缓解这一问题 只要使用gevent实现 2.代码 from socket impo ...
- Swoole 中使用 TCP 异步服务器、TCP 协程服务器、TCP 同步客户端、TCP 协程客户端
TCP 异步风格服务器 异步风格服务器通过监听事件的方式来编写程序.当对应的事件发生时底层会主动回调指定的函数. 由于默认开启协程化,在回调函数内部会自动创建协程,遇到 IO 会产生协程调度,异步风格 ...
- Swoole 中使用 WebSocket 异步服务器、WebSocket 协程服务器
WebSocket 异步风格服务器 WebSocket\Server 继承自 Http\Server,所以 Http\Server 提供的所有 API 和配置项都可以使用. # ws_server.p ...
- Swoole 中使用 HTTP 异步服务器、HTTP 协程服务器
HTTP 异步风格服务器 # http_server.php $http = new Swoole\Http\Server("0.0.0.0", 9501); // 设置服务器运行 ...
随机推荐
- css - 使用 " dl、dt、dd " 描述列表的形式 , 实现 【图片加下方文字】 的快速布局
上效果图 : 上代码 : <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...
- CSS 动画 : 创建 3D 立方体
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Qt5.9 UI设计(三)——添加UI、类及资源文件
前言 设计一个软件,最简单的方式就是把控件直接往UI上放,然后再把功能实现了.这样可以实现基本的功能,但是界面不能缩放,如果拖动软件改变界面的大小,界面上的控件就会乱成一团,或者是界面的控件压根就不会 ...
- 重写SpringCloudGateway路由查找算法,性能提升100倍!
如果你也在做SpringCloudGateway网关开发,希望这篇文章能给你带来一些启发 背景 先说背景,某油项目,通过SpringCloudGateway配置了1.6万个路由规则,实际接口调用过程中 ...
- [转帖]浪潮PM8222-SHBA、RAID 2GB PM8204、RAID 4GB PM8204,阵列卡配置方法
1.8222和8204对比 这几个型号的阵列卡都很相似,配置方法也基本一样 8204就是在8222上的基础上增加了缓存,可以通过下图对比 正面8204比8222多一个掉电保护接口 8204背面多了几个 ...
- [转帖]038-拯救大兵瑞恩之 TiDB 如何在 TiKV 损坏的情况下恢复
https://tidb.net/blog/4b5451bb?utm_source=tidb-community&utm_medium=referral&utm_campaign=re ...
- Prometheus+alertmanager实现告警的简单验证
Prometheus+alertmanager实现告警的简单验证 背景 学习源自: http://www.mydlq.club/article/126/ 上午没搞定, 中午睡不着,继续学习处理. 发现 ...
- Jmeter学习之四_kingbaseV8R6数据库的简单验证
Jmeter学习之四_kingbaseV8R6数据库的简单验证 背景 周一没去报道, 因为我忘记体检了... 继续在家进行学习提高自己. jmeter周末时开始看的. 今天想着继续研究一下对数据库的处 ...
- [转帖]FT-2000+/64 - Phytium
https://en.wikichip.org/wiki/phytium/feiteng/ft-2000%2B-64 Edit Values FT-2000+/64 General Info De ...
- [转帖]spec2017 安装和使用
https://zhuanlan.zhihu.com/p/534205632 SPEC成立于1988年,SPEC基准广泛用于评估计算机系统的性能.SPEC CPU套件通过测量几个程序(例如编译器GCC ...