使用场景
使用 kodbox 进行 NAS 文件管理, 开始还好好的, 下载一个 gho 系统镜像 一下子把 NAS 服务器干死, 反馈给可道云官方, 并没有实际效果, 还让我了解两款产品 (可道云,filebrowser) 的构成 = =
无语之下, 自行解决
先看看效果吧
处理前 -Cpu 提供 4 个 全部爆红
最终效果 -CPU 波澜不惊
解决方案
增加 NGINX 配置
#NGINX 大文件下载加速 location /dresource { alias /mnt/user/Resource;# 此处修改对应挂载的下载目录 internal; # 设置只允许 nginx 内部处理 用户无法直接直接下载文件 } #NGINX 大文件下载加速 END
注: 此处我看百度很多都是 root /mnt/user/Resource 此时 nginx 会访问 /mnt/user/Resource/dresource 去找文件 alias 则 nginx 会访问 /mnt/user/Resource 此目录
搞了一会儿 404 才发现这个问题
PHP 代码逻辑处理
原来代码类似如下 直接通过 PHP 来读取文件 导致读取 IO 过高 最终 CPU 也干死了
/* 原来代码类似如下直接通过 PHP 来读取文件 file_get_contents(); fread(); */
修改为如下代码即可 简单方便快捷 香喷喷
$filePath = '/mnt/user/Resource/text.txt';// 绝对路径 $filePathMap = $filePath; $httpSpeedFileMap = '/mnt/user/Resource:/dresource;';//$GLOBALS["config"]["settings"]["upload"]["httpSendFileMap"]; 后面为 kodbox 替换变量 $arr = explode(';', $httpSpeedFileMap); foreach ($arr as $item){$itemArr = explode(':', $item); //>> 获取服务器配置的路径映射 $filePathMap = str_replace($itemArr[0], $itemArr[1], $filePathMap); } ////////////////////////////////// header("X-Accel-Redirect:" . $filePathMap);// 此时地址应该为 /dresource/test.txt
此处还可以返回 header 头部 来控制下载速度 X-Accel-Limit-Rate 或者
location /dresource { limit_rate_after 500k; limit_rate 50k; }
注:
Kodbox 可以在 \PathDriverBase::fileOut
方法中 strtolower($_SERVER["SERVER_SOFTWARE"])
下方 if 判断中 增加以上代码
system_option 增加配置 httpSendFileMap=/mnt/user/Resource:/dresource; httpSendFile=1\userIndex::initSetting
方法中取消屏蔽 $upload['httpSendFile'] = $sysOption['httpSendFile'] == '1'
在此代码下方增加一行$upload['httpSendFileMap'] = $sysOption['httpSendFileMap'];
kodbox 修改位置 index.class.php
\userIndex::initSetting
private function initSetting(){if(!defined('STATIC_PATH')){define('STATIC_PATH',$GLOBALS['config']['settings']['staticPath']);
}
$sysOption = Model('SystemOption')->get();
$upload = &$GLOBALS['config']['settings']['upload'];
if(isset($sysOption['chunkSize'])){ // 没有设置则使用默认;
$upload['chunkSize'] = floatval($sysOption['chunkSize']);
$upload['ignoreName'] = trim($sysOption['ignoreName']);
$upload['chunkRetry'] = intval($sysOption['chunkRetry']);
///////////////////////// 修改这里
$upload['httpSendFile'] = $sysOption['httpSendFile'] == '1'; // 前端默认屏蔽;
$upload['httpSendFileMap'] = $sysOption['httpSendFileMap']; // 前端默认屏蔽;
/////////////////////////
// 上传限制扩展名, 限制单文件大小;
$role = Action('user.authRole')->userRoleAuth();
if($role && $role['info']){$roleInfo = $role['info'];
// if(isset($roleInfo['ignoreExt'])){// $upload['ignoreExt'] = $roleInfo['ignoreExt'];
// }
美化代码
//>> 载入文件
$code = file_get_contents($fileName);
//>> 创建解析器
$parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
//>> 节点
$traverser = new NodeTraverser();
try {$start = microtime(true);
echo $fileName . " 开始解析 ".PHP_EOL;
//>>
// 解析代码
$ast = $parser->parse($code);
echo $fileName . " 解析完成 ".PHP_EOL;
//>> 获取节点
$satrt_ast = $traverser->traverse($ast);
echo $fileName . " 节点获取完成 ".PHP_EOL;
$contentCode = (new PhpParser\PrettyPrinter\Standard())->prettyPrint($satrt_ast);
echo $fileName . " 代码美化完成 ".PHP_EOL;
$contentCode = "<?php" . "\n" . $contentCode;
$this->writeFile($fileName, $contentCode);
echo $fileName . " 格式化成功 耗时:".(microtime(true) - $start).PHP_EOL;
} catch (Error $error) {echo "Parse error: {$error->getMessage()}\n";
return;
}
修改位置 2:\PathDriverBase::fileOut
$softWare = strtolower($_SERVER["SERVER_SOFTWARE"]);
if ($driveType && $softWare && $httpSendFile) {
////////////////////////////////// 增加我这个代码 具体变量名我自己定义的 其他自行处理
$filePathMap = $filePath;
$httpSpeedFileMap = $GLOBALS["config"]["settings"]["upload"]["httpSendFileMap"];
$arr = explode(';', $httpSpeedFileMap);
foreach ($arr as $item){$itemArr = explode(':', $item);
//>> 获取服务器配置的路径映射
$filePathMap = str_replace($itemArr[0], $itemArr[1], $filePathMap);
}
//////////////////////////////////
if (strstr($softWare, "nginx")) {
//down-resource
header("X-Accel-Redirect: " . $filePathMap);
} else {if (strstr($softWare, "apache")) {header("X-Sendfile: " . $filePathMap);
} else {if (strstr($softWare, "http")) {header("X-LIGHTTPD-send-file: " . $filePathMap);
}
}
}
if ($