摘要:有研究过框架的同学就会发现,其实最核心的,就是用了拓展加上拓展来实现其底层的网络服务和多进程调度。我们在模式下,测试起五个进程主进程要等待回收我们,这样就很简单的实现了一个多进程的协程服务。
有研究过Workman框架的同学就会发现,其实workman最核心的,就是用了php socket拓展加上pcntl拓展来实现其底层的网络服务和多进程调度。那我们今天就来探讨如何使用Swoole的CoroutineSocket模块来实现自己的tcp服务。
我们先编写一段小的测试代码,test.php 代码如下
$socket = new CoSocket(AF_INET, SOCK_STREAM, 0); $socket->bind("127.0.0.1", 9601); $socket->listen(128); go(function () use ($socket) { while(true) { $client = $socket->accept(-1); $data = $client->recv(64,10); var_dump("Recv:".$data); $client->sendAll("reply at ".time()); $client->close(); } });
我们执行
php test.php
并新建一个cmd控制台,用telnet模拟tcp客户端,可以看到如下结果:
telnet 127.0.0.1 9601 Trying 127.0.0.1... Connected to localhost. Escape character is "^]". asd reply at 1559713416 Connection closed by foreign host
以上说明我们已经成功建立了一个简单的TCP服务器。而有细心的同学就会发现,以上代码如果我在recv后,有一些数据库行为发生,那我该TCP服务器在同一时间就仅仅只能accept链接并处理一个链接的事情,并发能力接近于1。因此我们可以做一点小小的改进,如下:
$socket = new CoSocket(AF_INET, SOCK_STREAM, 0); $socket->bind("127.0.0.1", 9601); $socket->listen(128); go(function () use ($socket) { while(true) { $client = $socket->accept(-1); go(function () use ($client){ $data = $client->recv(64,10); var_dump("Recv:".$data); //模拟数据库耗时,假定我们的数据库也是用协程api co::sleep(1); $client->sendAll("reply at ".time()); $client->close(); }); } });
我们利用协程,把连接accept后的逻辑,全部放到另外一个子协程当中处理,让我们的TCP服务器可以继续accept连接,也就提高了我们的并发能力。然而,在实际的编程中,我们不可能做到完全的百分百协程API,而且我的机器也是多核心的处理器,那么此刻我如何尽可能的利用我的CPU呢?因此我们可以利用端口复用的特性和Swoole的Process来构建一个多进程TCP协程服务器。
引入Process因为在本章节中,对Swoole Process的封装不是我们关心的,因此我们这里直接使用EasySwoole封装好的进程组件。
composer require easyswoole/component
实现我的Process Class,代码如下
use CoSocket; use EasySwooleComponentProcessAbstractProcess; class Server extends AbstractProcess { protected function run($arg) { $socket = new Socket(AF_INET, SOCK_STREAM, 0); //关键在这里,允许复用 $socket->setOption(SOL_SOCKET,SO_REUSEPORT,true); $socket->setOption(SOL_SOCKET,SO_REUSEADDR,true); $socket->bind("127.0.0.1", 9601); $socket->listen(128); go(function () use ($socket) { while(true) { $client = $socket->accept(-1); go(function () use ($client){ $data = $client->recv(64,10); var_dump("Recv:".$data); //模拟数据库耗时,假定我们的数据库也是用协程api co::sleep(1); $client->sendAll("reply at ".time()); $client->close(); }); } }); } }
我们在以上代码中,加入了允许端口复用的选项,否则在多进程模式下,会导致监听失败。我们在cli模式下,测试起五个进程
for ($i = 1;$i < 5;$i++){ $p = new Server("TcpServer.{$i}"); $p->getProcess()->start(); } //主进程要等待回收 while($ret = SwooleProcess::wait()) { echo "PID={$ret["pid"]} "; }
我们,这样就很简单的实现了一个多进程的TCP协程服务。总而言之,Swoole 4.x的协程能力,还是很强大的,让PHPer可以以最小的代价来实现一个高性能的TCP服务,而不是需要去学习新的一门语言,若需要更多的完善代码,可以参考http://easyswoole.com/ 这个框架的项目代码,如果有喜欢的同学,可以随意点个 star ,github地址 https://github.com/easy-swool...
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/31663.html
摘要:访问安全问题为什么说有访问安全问题呢传统地,在的的环境中,很少有遇到所谓变量安全访问问题。上下文管理器为了解决这个问题,我们引入协程上下文管理这样的概念,由此来实现每个协程环境内的数据隔离。 访问安全问题 为什么说有访问安全问题呢?传统地,在php的的环境中,很少有Phper遇到所谓变量安全访问问题。举个例子,代码大约如下: class db { protected stati...
摘要:然而尽管如此,很多人可能都没有思考过,如何优雅的写出自己的物联网服务器。 PHP不适合做物联网服务端吗? 在传统的思维中,经常会有人告诉你,php不适合用来做物联网服务端,让你换java,node,go等其他语言,是的,没错传统意义上的php,确实很难做物联网服务器,因为它实在太蹩脚了,当然,这也不是意味着彻底就不能做。举个例子,当你想实现一个TCP服务器的时候,你可能需要写出原理大约...
摘要:协程与信箱得益于,我们可以基于的协程与快速实现一个信箱模式调度。样例代码比如在一个聊天室中,我们可以定义一个房间模型。 什么是Actor? Actor对于PHPer来说,可能会比较陌生,写过Java的同学会比较熟悉,Java一直都有线程的概念(虽然PHP有Pthread,但不普及),它是一种非共享内存的并发模型,每个Actor内的数据独立存在,Actor之间通过消息传递的形式进行交互调...
摘要:年月日,在上海举行的第六届中国开发者大会上,腾讯开源项目首次全面发布版本,阅文集团高级开发工程师梁晨对如何通过构建高性能框架做了经验分享。分享内容作为腾讯开源的框架,在发布之后即受到开源领域的关注。阅文集团本身也有一块新的业务在使用。 2018年5月19日,在上海举行的第六届中国PHP开发者大会(PHPCon)上,腾讯开源项目TARS首次全面发布PHP版本,阅文集团高级开发工程师梁晨对...
摘要:协程完全有用户态程序控制,所以也被成为用户态的线程。目前支持协程的语言有很多,例如等。协程之旅前篇结束,下一篇文章我们将深入分析原生协程部分的实现。 写在最前 Swoole协程经历了几个里程碑,我们需要在前进的道路上不断总结与回顾自己的发展历程,正所谓温故而知新,本系列文章将分为协程之旅前、中、后三篇。 前篇主要介绍协程的概念和Swoole几个版本协程实现的主要方案技术; 中篇主...
阅读 1342·2021-09-24 10:26
阅读 3655·2021-09-06 15:02
阅读 603·2019-08-30 14:18
阅读 575·2019-08-30 12:44
阅读 3118·2019-08-30 10:48
阅读 1936·2019-08-29 13:09
阅读 1992·2019-08-29 11:30
阅读 2278·2019-08-26 13:36