当前位置:首页 > CMS教程 > 其它CMS > 列表

详解PHP框架EasySwoole

发布:smiling 来源: PHP粉丝网  添加日期:2022-05-03 09:16:44 浏览: 评论:0 

EasySwoole是一款常驻内存型的分布式swoole框架,专为API而生,支持同时混合监听HTTP、WebSocket、自定义TCP、UDP协议,且拥有丰富的组件,例如协程 连接池、TP风格的协程ORM、协程微信SDK等诸多组件。让开发者编写出多进程,可异步,高可用的应用服务。

安装

使用 Composer 安装

composer require easyswoole/easyswoole=3.xphp vendor/bin/easyswoole install

启动框架

php easyswoole start

nginx转发

  1. server { 
  2.  root /data/wwwroot/; 
  3.  server_name local.easyswoole.com; 
  4.     
  5.  location / { 
  6.  proxy_http_version 1.1; 
  7.  proxy_set_header Connection "keep-alive"
  8.  proxy_set_header X-Real-IP $remote_addr
  9.  if (!-e $request_filename) { 
  10.  proxy_pass http://127.0.0.1:9501; 
  11.  } 
  12.  if (!-f $request_filename) { 
  13.  proxy_pass http://127.0.0.1:9501; 
  14.  } 
  15.  } 

proxy_set_header X-Real-IP $remote_addr; 获取真实IP地址

运行

  1. project              项目部署目录 
  2.  
  3. ---------------------------------- 
  4.  
  5. ├─App        应用目录 
  6.  
  7. │  └─HttpController      应用的控制器目录 
  8.  
  9. │     └─Index.php    默认控制器文件 
  10.  
  11. ---------------------------------- 

Index.php

  1. <?php 
  2. namespace App\HttpController; 
  3. use EasySwoole\Http\AbstractInterface\Controller; 
  4. class Index extends Controller 
  5.  function index() 
  6.  { 
  7.  // TODO: Implement index() method. 
  8.  $this->response()->write('hello world'); 
  9.  } 

编辑根目录下的composer.json 文件

注册应用的命名空间

  1.  "autoload": { 
  2.  "psr-4": { 
  3.  "App\\": "App/" 
  4.  } 
  5.  }, 
  6.  "require": { 
  7.  "easyswoole/easyswoole""3.x-dev" 
  8.  } 

意思就是设置自动加载

最后执行composer dumpautoload

命令更新命名空间,可以开始编写业务逻辑

# 更新命名空间映射

composer dumpautoload

# 启动框架

php easyswoole start

目录结构

  1. project                   项目部署目录 
  2.  
  3. ├─App                     应用目录(可以有多个) 
  4.  
  5. │  ├─HttpController       控制器目录 
  6.  
  7. │  │  └─Index.php         默认控制器 
  8.  
  9. │  └─Model                模型文件目录 
  10.  
  11. ├─Log                     日志文件目录 
  12.  
  13. ├─Temp                    临时文件目录 
  14.  
  15. ├─vendor                  第三方类库目录 
  16.  
  17. ├─composer.json           Composer架构 
  18.  
  19. ├─composer.lock           Composer锁定 
  20.  
  21. ├─EasySwooleEvent.php     框架全局事件 
  22.  
  23. ├─easyswoole              框架管理脚本 
  24.  
  25. ├─easyswoole.install      框架安装锁定文件 
  26.  
  27. ├─dev.php                 开发配置文件 
  28.  
  29. ├─produce.php             生产配置文件 

生命周期

详解PHP框架EasySwoole

详解PHP框架EasySwoole

配置文件说明

  1. <?php 
  2.  /** 
  3.  * Created by PhpStorm. 
  4.  * User: yf 
  5.  * Date: 2019-01-01 
  6.  * Time: 20:06 
  7.  */ 
  8.  return [ 
  9.  'SERVER_NAME' => "EasySwoole",//服务名 
  10.  'MAIN_SERVER' => [ 
  11.  'LISTEN_ADDRESS' => '0.0.0.0',//监听地址 
  12.  'PORT' => 9501,//监听端口 
  13.  'SERVER_TYPE' => EASYSWOOLE_WEB_SERVER, //可选为 EASYSWOOLE_SERVER  EASYSWOOLE_WEB_SERVER EASYSWOOLE_WEB_SOCKET_SERVER 
  14.  'SOCK_TYPE' => SWOOLE_TCP,//该配置项当为SERVER_TYPE值为TYPE_SERVER时有效 
  15.  'RUN_MODEL' => SWOOLE_PROCESS,// 默认Server的运行模式 
  16.  'SETTING' => [// Swoole Server的运行配置( 完整配置可见[Swoole文档](https://wiki.swoole.com/wiki/page/274.html) ) 
  17.  'worker_num' => 8,//运行的  worker进程数量 
  18.  'max_request' => 5000,// worker 完成该数量的请求后将退出,防止内存溢出 
  19.  'task_worker_num' => 8,//运行的 task_worker 进程数量 
  20.  'task_max_request' => 1000,// task_worker 完成该数量的请求后将退出,防止内存溢出 
  21.  'reload_async' => true,//设置异步重启开关。设置为true时,将启用异步安全重启特性,Worker进程会等待异步事件完成后再退出。 
  22.  'task_enable_coroutine' => true//开启后自动在onTask回调中创建协程 
  23.  ] 
  24.  ], 
  25.  'TEMP_DIR' => null,//临时文件存放的目录 
  26.  'LOG_DIR' => null,//日志文件存放的目录 
  27.  'CONSOLE' => [//console控制台组件配置 
  28.  'ENABLE' => true,//是否开启 
  29.  'LISTEN_ADDRESS' => '127.0.0.1',//监听地址 
  30.  'PORT' => 9500,//监听端口 
  31.  'USER' => 'root',//验权用户名 
  32.  'PASSWORD' => '123456'//验权用户名 
  33.  ], 
  34.  'FAST_CACHE' => [//fastCache组件 
  35.  'PROCESS_NUM' => 0,//进程数,大于0才开启 
  36.  'BACKLOG' => 256,//数据队列缓冲区大小 
  37.  ], 
  38.  'DISPLAY_ERROR' => true,//是否开启错误显示 
  39.  ]; 

配置操作类

EasySwoole\Config 类

toArray 方法获取全部配置,load 方法重载全部配置

如果设置了修改,需要更新配置的意思

  1. <?php 
  2. $instance = \EasySwoole\EasySwoole\Config::getInstance(); 
  3. // 获取配置 按层级用点号分隔 
  4. $instance->getConf('MAIN_SERVER.SETTING.task_worker_num'); 
  5. // 设置配置 按层级用点号分隔 
  6. $instance->setConf('DATABASE.host''localhost'); 
  7. // 获取全部配置 
  8. $conf = $instance->getConf(); 
  9. // 用一个数组覆盖当前配置项 
  10. $conf['DATABASE'] = [ 
  11.  'host' => '127.0.0.1'
  12.  'port' => 13306 
  13. ]; 
  14. $instance->load($conf); 

添加用户配置项

  1. 'MYSQL' => [ 
  2.  'host' => '192.168.75.1'
  3.  'port' => '3306'
  4.  'user' => 'root'
  5.  'timeout' => '5'
  6.  'charset' => 'utf8mb4'
  7.  'password' => 'root'
  8.  'database' => 'cry'
  9.  'POOL_MAX_NUM' => '20'
  10.  'POOL_TIME_OUT' => '0.1'
  11. ], 
  12. /*################ REDIS CONFIG ##################*/ 
  13. 'REDIS' => [ 
  14.  'host' => '127.0.0.1'
  15.  'port' => '6379'
  16.  'auth' => ''
  17.  'POOL_MAX_NUM' => '20'
  18.  'POOL_MIN_NUM' => '5'
  19.  'POOL_TIME_OUT' => '0.1'

生产与开发配置分离

默认为开发模式,加载 dev.php

生成

php easyswoole start produce

DI注入配置

也就是依赖注入

  1. <?php 
  2. Di::getInstance()->set(SysConst::ERROR_HANDLER,function (){});//配置错误处理回调 
  3. Di::getInstance()->set(SysConst::SHUTDOWN_FUNCTION,function (){});//配置脚本结束回调 
  4. Di::getInstance()->set(SysConst::HTTP_CONTROLLER_NAMESPACE,'App\\HttpController\\');//配置控制器命名空间 
  5. Di::getInstance()->set(SysConst::HTTP_CONTROLLER_MAX_DEPTH,5);//配置http控制器最大解析层级 
  6. Di::getInstance()->set(SysConst::HTTP_EXCEPTION_HANDLER,function (){});//配置http控制器异常回调 
  7. Di::getInstance()->set(SysConst::HTTP_CONTROLLER_POOL_MAX_NUM,15);//http控制器对象池最大数量 

动态配置

每次开始了,是上一次的进程,比如你打开了旧版,现在更新了新版,但是旧版还是开着,没有重启动,也就是一直旧版,现在有个动态配置,表示可以平滑的修改

  1. <?php 
  2.  Config::getInstance()->setDynamicConf('test_config_value', 0);//配置一个动态配置项 
  3.  $test_config_value_1 = Config::getInstance()->getDynamicConf('test_config_value');//获取一个配置 
  4.  Config::getInstance()->delDynamicConf('test_config_value');//删除一个配置 

服务管理脚本

php easyswoole

install       安装easySwoole

start         启动easySwoole

stop          停止easySwoole(守护模式下使用)

reload        重启easySwoole(守护模式下使用)

help          查看命令的帮助信息

easyswoole help -start

守护模式启动

php easyswoole start d

线上

php easyswoole start produce

停止

php easyswoole stop

重启服务

php easyswoole reload 只重启task进程

php easyswoole reload all  重启task + worker进程

文件热加载

由于 swoole 常驻内存的特性,修改文件后需要重启worker进程才能将被修改的文件重新载入内存中

解决:Process的方式实现文件变动自动进行服务重载

新建文件 App/Process/HotReload.php 并添加如下内容,也可以放在其他位置,请对应命名空间

  1. <?php 
  2. namespace App\Process; 
  3. use EasySwoole\Component\Process\AbstractProcess; 
  4. use EasySwoole\EasySwoole\ServerManager; 
  5. use EasySwoole\Utility\File; 
  6. use Swoole\Process; 
  7. use Swoole\Table; 
  8. use Swoole\Timer; 
  9. /** 
  10.  * 暴力热重载 
  11.  * Class HotReload 
  12.  * @package App\Process 
  13.  */ 
  14. class HotReload extends AbstractProcess 
  15.  /** @var \swoole_table $table */ 
  16.  protected $table
  17.  protected $isReady = false; 
  18.  protected $monitorDir// 需要监控的目录 
  19.  protected $monitorExt// 需要监控的后缀 
  20.  /** 
  21.  * 启动定时器进行循环扫描 
  22.  */ 
  23.  public function run($arg
  24.  { 
  25.  // 此处指定需要监视的目录 建议只监视App目录下的文件变更 
  26.  $this->monitorDir = !emptyempty($arg['monitorDir']) ? $arg['monitorDir'] : EASYSWOOLE_ROOT . '/App'
  27.  // 指定需要监控的扩展名 不属于指定类型的的文件 无视变更 不重启 
  28.  $this->monitorExt = !emptyempty($arg['monitorExt']) && is_array($arg['monitorExt']) ? $arg['monitorExt'] : ['php']; 
  29.  if (extension_loaded('inotify') && emptyempty($arg['disableInotify'])) { 
  30.  // 扩展可用 优先使用扩展进行处理 
  31.  $this->registerInotifyEvent(); 
  32.  echo "server hot reload start : use inotify\n"
  33.  } else { 
  34.  // 扩展不可用时 进行暴力扫描 
  35.  $this->table = new Table(512); 
  36.  $this->table->column('mtime', Table::TYPE_INT, 4); 
  37.  $this->table->create(); 
  38.  $this->runComparison(); 
  39.  Timer::tick(1000, function () { 
  40.  $this->runComparison(); 
  41.  }); 
  42.  echo "server hot reload start : use timer tick comparison\n"
  43.  } 
  44.  } 
  45.  /** 
  46.  * 扫描文件变更 
  47.  */ 
  48.  private function runComparison() 
  49.  { 
  50.  $startTime = microtime(true); 
  51.  $doReload = false; 
  52.  $dirIterator = new \RecursiveDirectoryIterator($this->monitorDir); 
  53.  $iterator = new \RecursiveIteratorIterator($dirIterator); 
  54.  $inodeList = array(); 
  55.  // 迭代目录全部文件进行检查 
  56.  foreach ($iterator as $file) { 
  57.  /** @var \SplFileInfo $file */ 
  58.  $ext = $file->getExtension(); 
  59.  if (!in_array($ext$this->monitorExt)) { 
  60.  continue// 只检查指定类型 
  61.  } else { 
  62.  // 由于修改文件名称 并不需要重新载入 可以基于inode进行监控 
  63.  $inode = $file->getInode(); 
  64.  $mtime = $file->getMTime(); 
  65.  array_push($inodeList$inode); 
  66.  if (!$this->table->exist($inode)) { 
  67.  // 新建文件或修改文件 变更了inode 
  68.  $this->table->set($inode, ['mtime' => $mtime]); 
  69.  $doReload = true; 
  70.  } else { 
  71.  // 修改文件 但未发生inode变更 
  72.  $oldTime = $this->table->get($inode)['mtime']; 
  73.  if ($oldTime != $mtime) { 
  74.  $this->table->set($inode, ['mtime' => $mtime]); 
  75.  $doReload = true; 
  76.  } 
  77.  } 
  78.  } 
  79.  } 
  80.  foreach ($this->table as $inode => $value) { 
  81.  // 迭代table寻找需要删除的inode 
  82.  if (!in_array(intval($inode), $inodeList)) { 
  83.  $this->table->del($inode); 
  84.  $doReload = true; 
  85.  } 
  86.  } 
  87.  if ($doReload) { 
  88.  $count = $this->table->count(); 
  89.  $time = date('Y-m-d H:i:s'); 
  90.  $usage = round(microtime(true) - $startTime, 3); 
  91.  if (!$this->isReady == false) { 
  92.  // 监测到需要进行热重启 
  93.  echo "severReload at {$time} use : {$usage} s total: {$count} files\n"
  94.  ServerManager::getInstance()->getSwooleServer()->reload(); 
  95.  } else { 
  96.  // 首次扫描不需要进行重启操作 
  97.  echo "hot reload ready at {$time} use : {$usage} s total: {$count} files\n"
  98.  $this->isReady = true; 
  99.  } 
  100.  } 
  101.  } 
  102.  /** 
  103.  * 注册Inotify监听事件 
  104.  */ 
  105.  private function registerInotifyEvent() 
  106.  { 
  107.  // 因为进程独立 且当前是自定义进程 全局变量只有该进程使用 
  108.  // 在确定不会造成污染的情况下 也可以合理使用全局变量 
  109.  global $lastReloadTime
  110.  global $inotifyResource
  111.  $lastReloadTime = 0; 
  112.  $files = File::scanDirectory(EASYSWOOLE_ROOT . '/App'); 
  113.  $files = array_merge($files['files'], $files['dirs']); 
  114.  $inotifyResource = inotify_init(); 
  115.  // 为当前所有的目录和文件添加事件监听 
  116.  foreach ($files as $item) { 
  117.  inotify_add_watch($inotifyResource$item, IN_CREATE | IN_DELETE | IN_MODIFY); 
  118.  } 
  119.  // 加入事件循环 
  120.  swoole_event_add($inotifyResourcefunction () { 
  121.  global $lastReloadTime
  122.  global $inotifyResource
  123.  $events = inotify_read($inotifyResource); 
  124.  if ($lastReloadTime < time() && !emptyempty($events)) { // 限制1s内不能进行重复reload 
  125.  $lastReloadTime = time(); 
  126.  ServerManager::getInstance()->getSwooleServer()->reload(); 
  127.  } 
  128.  }); 
  129.  } 
  130.  public function onShutDown() 
  131.  { 
  132.  // TODO: Implement onShutDown() method. 
  133.  } 
  134.  public function onReceive(string $str
  135.  { 
  136.  // TODO: Implement onReceive() method. 
  137.  } 

添加好后在全局的 EasySwooleEvent.php 中,注册该自定义进程

  1. public static function mainServerCreate(EventRegister $register
  2.  $swooleServer = ServerManager::getInstance()->getSwooleServer(); 
  3.  $swooleServer->addProcess((new HotReload('HotReload', ['disableInotify' => false]))->getProcess()); 
  4. }

Tags: EasySwoole

分享到: