初识EasySwoole框架

EasySwoole是啥?EasySwoole 是一款基于Swoole Server 开发的常驻内存型的分布式PHP框架,专为API而生,摆脱传统PHP运行模式在进程唤起和文件加载上带来的性能损失。 -·-  全文结构 -·-** Swoole框架的选择1、Swoole框架的选择*在开篇《Cygwin:Windows系统下的Linux开发环境》中讲到了Swoole是一个PHP的协程高性能网络通信引擎,使用C/C++语言编写,提供了多种通信协议的网络服务器和客户端模块。 它可以方便快速的实现 TCP/UDP服务、高性能Web及WebSocket服务、物联网、实时通讯、游戏、微服务等,使PHP不再局限于传统的Web领域。 Swoole 是按照PHP的标准扩展构建的。使用phpize来生成编译检测脚本,./configure 来做编译配置检测,make进行编译,make install进行安装。 对于初学者来说,一上来就直接学习PHP扩展(swoole),估计会有点懵。所以在这里选择一个基于Swoole开发的框架来进行学习。 基于Swoole的开源框架有很多,如Swoft、EasySwoole、Hyperf,另外ThinkPHP、LaravelS也都对Swoole进行了支持。 在具体的框架选择上因人(项目)而异,Swoft框架很全面,其注释路由AOP(面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术)实体Bean等都明显源自于Java,写代码时有明显的Java风格,对于Java转PHP的开发者来说可能比较友好。 Swoft官方地址:https://www.swoft.org/ Hyperf,是Swoft开发组中的几位的成员出来开发的一个框架,也是拥有了Swoft优秀的基因基础上,但不再强制注释,集成大量企业级开发的组件,完善丰富的文档,完善的项目测试用例。 Hyperf官方地址:https://www.hyperf.io/ EasySwoole是我个人比较喜欢的,它不像Laravel或者Swoft那样重,但是足够灵活好用。在数据库方面支持来自Laravel的Eloquent、来自ThinkPHP5的think-orm等可选,模板引擎也支持来自Laravel的blade、来自ThinkPHP5的think-template和老牌的smarty。 EasySwoole的开发过程基本上和ThinkPHP框架使用的方式差不多,如果你有ThinkPHP开发基础,且开发的项目不是很复杂,那么EasySwoole是一个不错的选择! 2、EasySwoole框架简介*EasySwoole 是一款基于Swoole开发的常驻内存型的分布式PHP框架,专为API而生,摆脱传统PHP运行模式在进程唤起和文件加载上带来的性能损失。 官方地址:https://www.easyswoole.com/。 Easyswoole的前身EasyPHP-Swoole,后更名为Easyswoole,目前更新到3.x版本。腾讯公司的IEG部门、WEGAME部门、网宿科技(国内CDN厂家)、360金融、360小游戏(Actor)、 9377小游戏、厦门美图网、蝉大师等公司都在使用。 EasySwoole 高度封装了Swoole而依旧维持Swoole原有特性,支持同时混合监听HTTP、自定义TCP、UDP协议,支持多线程,EventLoop,事件驱动,异步,Worker进程组,Task异步任务,毫秒定时器,SSL/TLS隧道加密 EventLoop API,让用户可以直接操作底层的事件循环,将socket,stream,管道等Linux文件加入到事件循环中。 同时支持分布式微服务及RPC,另外还提供协程微信公众号与小程序SDK协程协程版微信、支付宝支付SDK在内的各种开箱即用的常用组件。让开发者以最低的学习成本和精力编写出多进程,可异步,高可用的应用服务。 在编写代码规范上EasySwoole采用驼峰法,项目中类名称与类文件(文件夹)命名,均为大驼峰,如:AppClass,变量与类方法为小驼峰,如:appValue。 EasySwoole的基础运行环境:PHP 版本大于等于7.1;Swoole 拓展版本大于等于 4.4.15;pcntl 拓展的任意版本;使用 Composer 作为依赖管理工具;使用 Linux / FreeBSD / MacOS 这三类操作系统(Windows系统安装Cygwin也可以模拟出Linux环境,参见《Cygwin:Windows系统下的Linux开发环境》)。 接下来,进入基础运行环境的搭建。 3、EasySwoole基础环境的搭建*3.1、检查PHP版本打开shell命令窗口,输入php -v,查看PHP版本,确保版本大于等于7.1。 3.2、安装swoole1、首先进入swoole的github下载地址,如果没有特殊需求,请选择最新版本开始下载https://github.com/swoole/swo... 2、选择gz压缩包下载,下载后复制到cygwin安装目录下的home目录下 3、点击cygwin快捷键进入虚拟终端并解压home目录下的刚下载的swoole安装包到/usr/local/swoole下(如果目录不存在,可以在/usr/local/目录下手动创建swoole),命令行: tar xzvf /home/swoole-src-4.5.2.tar.gz  -C /usr/local/swoole/ ...

June 20, 2020 · 1 min · jiezi

Swoole4x之协程变量访问安全与协程连接池实现

访问安全问题为什么说有访问安全问题呢?传统地,在php的的环境中,很少有Phper遇到所谓变量安全访问问题。举个例子,代码大约如下: class db{ protected static $instance; protected $dbCon; function __construct() { /* * 我们这里用stdclass来模拟一个数据库连接 */ $this->dbCon = new \stdClass(); } public static function getInstance() { if(!isset(self::$instance)){ self::$instance = new db(); } return self::$instance; } function dbCon() { return $this->dbCon; }}$con = db::getInstance()->dbCon();$con->key = 'new';var_dump($con->key);这个是在fpm模式下,很常见的数据库连接单例模式的使用。乍一看没有问题,但实际上,在协程环境下,会出现连接跨协程使用问题,举例如下 go(function (){ go(function (){ db::getInstance()->dbCon()->key = 'one'; //假设这sql执行了1s \co::sleep(1); var_dump(db::getInstance()->dbCon()->key); }); go(function (){ db::getInstance()->dbCon()->key = 'two'; //假设这sql执行了0.1s \co::sleep(0.1); var_dump(db::getInstance()->dbCon()->key); });});我们会发现,以上代码当中,协程2的数据污染到了协程1的数据,那么因此这样肯定是不行的。 上下文管理器为了解决这个问题,我们引入协程上下文管理这样的概念,由此来实现每个协程环境内的数据隔离。 class dbContext{ private $container = []; private static $instance; public static function getInstance() { if(!isset(self::$instance)){ self::$instance = new dbContext(); } return self::$instance; } function dbCon() { $cid = \co::getCid(); if(!isset($this->container[$cid])){ $this->container[$cid] = new stdClass(); defer(function (){ $this->destroy(); }); } return $this->container[$cid]; } function destroy() { $cid = \co::getCid(); if(!isset($this->container[$cid])){ unset($this->container[$cid]); } }}go(function (){ go(function (){ dbContext::getInstance()->dbCon()->key = 'one'; //假设这sql执行了1s \co::sleep(1); var_dump(dbContext::getInstance()->dbCon()->key); }); go(function (){ dbContext::getInstance()->dbCon()->key = 'two'; //假设这sql执行了0.1s \co::sleep(0.1); var_dump(dbContext::getInstance()->dbCon()->key); });});以上代码中,我们用每个协程的id,来作为每个协程栈的数据token,用了defer方法,实现了每个协程退出的时候的数据自动清理,从而避免了内存泄露。 ...

June 24, 2019 · 1 min · jiezi

PHP物联网开发利器之Actor并发模型

PHP不适合做物联网服务端吗?在传统的思维中,经常会有人告诉你,php不适合用来做物联网服务端,让你换java,node,go等其他语言,是的,没错传统意义上的php,确实很难做物联网服务器,因为它实在太蹩脚了,当然,这也不是意味着彻底就不能做。举个例子,当你想实现一个TCP服务器的时候,你可能需要写出原理大约如下的代码: for ($i = 0;$i <= 1;$i++){ $pid = pcntl_fork(); if($pid){ if($i == 0){ $server = stream_socket_server("tcp://127.0.0.1:9501", $errno, $errstr, STREAM_SERVER_BIND); }else if($i == 1){ $tickTime = time()+3600; while (1){ usleep(1); if($tickTime == time()){ //do my tick func } } } }}以上代码的意义等于在一个进程中创建一个TCP 服务端,另外一个进程中死循环来做时间检测,从而实现定时器逻辑。这样看起来,确实很蹩脚,而且对于编程基础普遍比较薄弱的PHPer来说,这真的很难维护。当然这个时候,就会有人说,这不是还有Workerman吗,是的,确实还有Workerman,Workerman就是高度封装了上述代码原理,帮助你专心于实现代码逻辑的一个PHP多进程框架,因此说PHP不时候做物联网,其实这是谬论。当然这个时候可能又会有人说,go语言有协程,你用Workerman当出现阻塞数据库调用的时候,那效率就非常的差,很难出现高并发,这么说没错,但是实际上,我们可以尽可能的用多进程去弥补这个不足,也就是堆机器。当然,如果你真的想锱铢必较,没关系,这个时候我们就可以拿出我们的杀器,那就是Swoole4.x的协程。 Swoole做TCP服务器举个例子,如下代码: $server = new swoole_server("127.0.0.1", 9501);$server->on('workerstart',function ($ser,$workerId){ if($workerId == 0){ swoole_timer_tick(1000,function (){ }); }});$server->on('connect', function ($server, $fd){ echo "connection open: {$fd}\n";});$server->on('receive', function ($server, $fd, $reactor_id, $data) { $server->send($fd, "Swoole: {$data}"); $server->close($fd);});$server->on('close', function ($server, $fd) { echo "connection close: {$fd}\n";});$server->start();我们就可以很快的创建出一个多进程的协程TCP服务器,而且在各个回调函数内,均自动创建协程环境,我们可以在协程回调内,去调用协程的数据库API,这样就避免了因为阻塞数据库调用而导致无法处理其他客户端请求的问题。然而尽管如此,很多人可能都没有思考过,如何优雅的写出自己的物联网服务器。举个例子,我们常见的互联网设备管理服务中,大约可能出现如下代码: ...

June 9, 2019 · 2 min · jiezi

Swoole4x探究之多进程TCP协程服务实现

有研究过Workman框架的同学就会发现,其实workman最核心的,就是用了php socket拓展加上pcntl拓展来实现其底层的网络服务和多进程调度。那我们今天就来探讨如何使用Swoole的CoroutineSocket模块来实现自己的tcp服务。我们先编写一段小的测试代码,test.php 代码如下 $socket = new Co\Socket(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 9601Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.asdreply at 1559713416Connection closed by foreign host以上说明我们已经成功建立了一个简单的TCP服务器。而有细心的同学就会发现,以上代码如果我在recv后,有一些数据库行为发生,那我该TCP服务器在同一时间就仅仅只能accept链接并处理一个链接的事情,并发能力接近于1。因此我们可以做一点小小的改进,如下: $socket = new Co\Socket(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协程服务器。 ...

June 5, 2019 · 1 min · jiezi

Swoole难上手?从EasySwoole开始

前言我一生的文章都会放在这里,我的博客,我希望每一行代码,每一段文字都能帮助你。https://github.com/CrazyCodes…大家好,我是CrazyCodes,我没有消失,最近在准备考试,所以文章出的比较慢,请见谅有些童鞋感觉对Swoole不从下手,也不知在什么业务上使用它,看它这么火却学不会也是挺让人捉急的一件事情。Swoole:面向生产环境的 PHP 异步网络通信引擎啥是异步网络通信?异步通信简单点来说,就是一个人和一群人的关系,一个人去做十件事,需要一件一件去做,一群人去做10件事,可以分配每个人做每件事。我们用Swoole可以做什么?聊天室并发的处理 (读大文件)异步MySQL异步Redis等等当然不去做,只在看,很难理解为何选择使用Swoole去做这些。从现在开始,我们暂时不关心上面的这些概念,啥话都不说,就是干EasySwooleEasySwoole ? 名副其实,作者为了让开发者更便捷的使用Swoole 而封装的开发框架,地址在下方EasySwoole https://www.easyswoole.com/使用EasySwoole你会发现有很多很难理解的概念及用法。没关系,跟着我,慢慢来~安装EasySwoole的环境要求保证 PHP 版本大于等于 7.1保证 Swoole 拓展版本大于等于 4.3.0需要 pcntl 拓展的任意版本使用 Linux / FreeBSD / MacOS 这三类操作系统使用 Composer 作为依赖管理工具如果你感觉以上要求太苛刻,你可以选择使用Docker快速部署一套开发环境或者使用更简单的 homestead在使用EasySwoole之前我们要安装Swoole,Swoole是PHP扩展,我们可以通过pecl install swoole快速安装,或者使用源码编译的形式安装安装完扩展后,接下来我们就使用万能composer来安装EasySwoolecomposer require easyswoole/easyswoole=3.xphp vendor/bin/easyswoole install服务管理EasySwoole(Swoole)与其他框架不同,他不擅长开发Web,请将目标定位在后端服务上。以下内容为引用官方文档php easyswoole start Hello World以下为官方文档内容 https://www.easyswoole.com/Ma…在项目根目录下创建如下的目录结构,这个目录是编写业务逻辑的应用目录,编辑 Index.php 文件,添加基础控制器的代码project 项目部署目录———————————-├─App 应用目录│ └─HttpController 应用的控制器目录│ └─Index.php 默认控制器文件———————————-<?phpnamespace App\HttpController;use EasySwoole\Http\AbstractInterface\Controller;class Index extends Controller{ function index() { // TODO: Implement index() method. $this->response()->write(‘hello world’); }}然后编辑根目录下的 composer.json 文件,注册应用的命名空间{ “autoload”: { “psr-4”: { “App\”: “App/” } }, “require”: { “easyswoole/easyswoole”: “3.x-dev” }}最后执行 composer dumpautoload 命令更新命名空间,框架已经可以自动加载 App 目录下的文件了,此时框架已经安装完毕,可以开始编写业务逻辑# 更新命名空间映射composer dumpautoload# 启动框架php easyswoole start启动框架后,访问 http://localhost:9501即可看到 Hello World 。组件EasySwoole提供了很多实用的组件包括控制台组件定时器触发器日志处理等等…致谢从下一章开始,我们逐步使用EasySwoole的各项功能并开发一个简单的并发版爬虫系统,感谢你看到这里,希望本文可以帮到你,谢谢 ...

March 7, 2019 · 1 min · jiezi