之前测试各种业务时都是正常的,偏偏今天在写程序安装引导时遇到502或者直接无响应问题,不知道是我哪里代码的问题,说一下我遇到的情况,麻烦大佬们看看哪里导致的!
1.没有任何报错信息(可能是Nginx代理转发的问题,但我用的免费版宝塔,没有防火墙)
2.一样的代码,我之前的thinkphp6.1程序虽然响应慢一点,但不会出现这个问题(最多SQL语句写入错误)
3.其他业务操作都是正常,只有安装执行SQL的时候会出现, CPU的负载也会被拉起来
4.无响应或者502一般是3、4次到20来次都出现过没有规律,不像是SQL语句错误导致
502报错截图
无响应截图一
无响应截图二
命令行调试截图
Webman运行状态
服务器负载占用截图
/**
* 执行安装控制器主方法 502或者无响应就是这个请求出现的
*/
public function onInstall()
{
$dbOptions = Cache::get('install.db');
if (!is_array($dbOptions)) {
$dbOptions = input('post.database');
}
$sql_step = input('post.sql_step/d', 0);
// 链接数据库
try {
$this->getPdoDb($dbOptions);
} catch (\Throwable $th) {
// 捕获DbException 此处注意DbException只能用Exception捕获
$code = $th->getCode();
if ($code == 2002) {
return $this->error('数据库链接错误, 数据库地址填写错误');
} elseif ($code == 1045) {
return $this->error('数据库链接错误, 账号或密码错误');
} elseif ($code == 1049) {
return $this->error('数据库链接错误, 数据库名称对应的数据库不存在');
}
return $this->error('数据库链接错误,' . $th->getMessage(), null, [
'list' => [],
'log' => [],
'ok' => 0,
'result' => ['sql_step' => $sql_step++],
]);
}
$this->pdo = null;
// 执行数据库写入
$sqlFile = dirname(__DIR__) . '/data/install.sql';
if (!is_file($sqlFile)) {
return $this->error('数据库安装文件[app/' . module() . '/data/install.sql]不存在,请检查程序完整性', '', ['ok' => 0, 'list' => [], 'log' => [], 'sqlFile' => str_replace(root_path(), '', $sqlFile)]);
}
$list = $log = [];
for ($i = 0; $i < $this->write_num; $i++) {
$sql = $this->getInstallSql(++$sql_step, $dbOptions['dbprefix'] ?? 'cmypro_');
$res = $this->doInstallSql($sql_step, $sql);
if ($res['empty'] != 1) {
$list[] = $res;
$log[] = $this->resMsg($res, $res['success'] === true);
}
}
if ($sql_step >= $this->sql_num) {
// 执行到最后一步,更新管理员和配置信息等
$data = Cache::get('install.data');
$res = $this->updateAdmin($data);
$list[] = $res;
$log[] = $this->resMsg($res, $res['success'] === true);
$res = $this->updateWebsite($data);
$list[] = $res;
$log[] = $this->resMsg($res, $res['success'] === true);
$this->updateAdminPath();
$res = $this->insertVersionInfo();
$list[] = $res;
$log[] = $this->resMsg($res, $res['success'] === true);
return $this->success('共' . $this->sql_num . '条, 数据写入成功', null, ['ok' => 1, 'list' => $list, 'log' => $log, 'sql_num' => $this->sql_num, 'sql_all' => $this->sql_all]);
}
return $this->success('当前执行完毕', '', ['list' => $list, 'log' => $log, 'ok' => 0, 'result' => $res, 'sql_step' => $sql_step, 'sql_num' => $this->sql_num, 'write_num' => $this->write_num, 'next_array' => array_slice(self::$sql_array, ($sql_step > 0 ? $sql_step : 0), $this->write_num)]);
}
/**
* 获取当前执行语句
*
* @param integer $sql_step 当前步骤
* @param string $prefix 数据表前缀
* @return string
*/
private function getInstallSql($sql_step = 0, $prefix = 'cmypro')
{
static $sql_array = null;
$file = dirname(__DIR__) . '/data/install.sql';
if (empty($sql_array) || filemtime($file) > $this->sqlFileMtime) {
$sql = file_get_contents($file);
$this->sqlFileMtime = filemtime($file);
$this->sql_all = $sql = preg_replace('/;[\s]+\n/', ";\n", $sql);
$sql_array = explode(";\n", $sql);
$sql_array = array_filter($sql_array, function ($value) {
return trim($value) != '';
});
self::$sql_array = $sql_array = array_map(function ($value) use ($prefix) {
return $this->sql_split($value, $prefix);
}, $sql_array);
}
$this->sql_num = count($sql_array);
if (isset($sql_array[$sql_step])) {
return $sql_array[$sql_step];
}
return '';
}
/**
* SQL语句处理
*
* @param string $sql
* @param string $prefix
* @return string
*/
private function sql_split($sql, $prefix): string
{
try {
// 统一换行符为\n
$sql = str_replace(["\r\n", "\r"], "\n", $sql);
// 保留MySQL条件注释(如/*!50001 ... */)
$sql = preg_replace_callback('/\/\*!\d{5}.*?\*\//s', function ($matches) {
return str_replace("\n", " ", $matches[0]); // 防止换行破坏注释结构
}, $sql);
// 删除普通注释(改进正则避免破坏条件注释)
$sql = preg_replace([
'/\/\*.*?\*\//s', // /*...*/
'/\s*-- .*$/m', // -- 注释
'/\s*#.*$/m' // # 注释
], ['', "\n", "\n"], $sql);
// 安全替换表前缀(处理特殊字符)
foreach ($this->table_prefix as $key => $table_prefix) {
$oldPrefix = preg_quote($table_prefix, '/');
$sql = preg_replace([
"/`{$oldPrefix}([a-zA-Z0-9_]+)`/",
"/(\s){$oldPrefix}([a-zA-Z0-9_]+)(\s)/"
], [
'`' . $prefix . '$1`',
'$1' . $prefix . '$2$3'
], $sql);
}
// 处理存储引擎和字符集(更精确的匹配)
$sql = preg_replace([
'/\bTYPE\s*=\s*(InnoDB|MyISAM|MEMORY)\b/i',
'/\s*DEFAULT\s+CHARSET\s*=\s*[a-zA-Z0-9_]+/i'
], [
'ENGINE=$1',
' DEFAULT CHARSET=utf8mb4'
], $sql);
// 清理多余空白(保留换行用于语句分割)
$sql = preg_replace([
'/\n{3,}/', // 多个空行变单行
'/\s{2,}/', // 多个空格变单空格
'/\s*;\s*$/m' // 行尾分号清理
], [
"\n\n",
' ',
';'
], $sql);
} catch (\Throwable $th) {
$this->outJson(['msg' => $th->getMessage(), 'sql' => $sql]);
}
return $sql;
}
/**
* 链接Pdo数据库检查数据库信息是否正确
*
* @param array $dbOptions 数据库配置信息
* @return \PDO
*/
private function getPdoDb(array $dbOptions = [])
{
$dbhost = $dbOptions['dbhost'] ?? '127.0.0.1';
$dbname = $dbOptions['dbname'] ?? 'root';
$dbuser = $dbOptions['dbuser'] ?? 'root';
$dbpwd = $dbOptions['dbpwd'] ?? '123456';
$dbport = $dbOptions['dbport'] ?? '3306';
// 数据库类型
$type = config('think-orm.default', 'mysql');
$pdo = null;
$option = $type . ":host=" . $dbhost;
if ($dbport) {
$option .= ";port=" . $dbport;
}
if ($dbname) {
$option .= ";dbname={$dbname}";
}
// PDO配置
$pdoAttr = [
//设置数据库字段保持不变
PDO::ATTR_CASE => PDO::CASE_NATURAL,
//关闭pdo模拟功能
PDO::ATTR_EMULATE_PREPARES => false,
//开启缓存查询
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
];
$this->pdo = new PDO($option, $dbuser, $dbpwd, $pdoAttr);
$this->pdo->exec("set names 'utf8mb4'");
return $pdo;
}
/**
* 执行写入SQL
*
* @param integer $sql_step
* @param string $sql
* @return array
*/
private function doInstallSql($sql_step = 0, $sql = '')
{
if (trim($sql) == '') {
return [
'sql_step' => $sql_step,
'sql' => $sql,
'empty' => 1,
'title' => '无效操作',
'content' => 'SQL语句为空! ',
'sql_num' => $this->sql_num - 1,
'success' => false,
];
}
$tableName = '';
if (preg_match('/TABLE IF NOT EXISTS `([\w]+)`/i', $sql, $match1)) {
$tableName = $match1[1];
}
$tableTitle = '';
if (preg_match("/CHARSET=utf8mb4 COMMENT='(.*?)'/i", $sql, $match2)) {
$tableTitle = $match2[1];
}
if (!$tableName && !$tableTitle) {
if (preg_match("/insert into `([\w]+)`/i", $sql, $match3)) {
$tableName = $match3[1];
$type = 'insert';
// 说明是insert语句
$ret = [
'sql_step' => $sql_step,
'sql' => $sql,
'title' => '插入到表>>' . ($tableName ?: '未知'),
'content' => '',
'sql_num' => $this->sql_num - 1,
'success' => false,
];
} else {
$type = 'insert';
$ret = [
'sql_step' => $sql_step,
'sql' => $sql,
'title' => '其他写入',
'content' => '',
'sql_num' => $this->sql_num - 1,
'success' => false,
];
}
} else {
$type = 'table';
$ret = [
'sql_step' => $sql_step,
'sql' => $sql,
'title' => '创建表>>' . ($tableTitle ?: $tableName),
'content' => '',
'sql_num' => $this->sql_num - 1,
'success' => false,
];
}
try {
$ret['success'] = true;
$ret['content'] = $type == 'table' ? '创建成功' : '插入成功';
\support\think\Db::query($sql);
// $this->pdo->query($sql);
} catch (\Throwable $th) {
// 捕获DbException 此处注意DbException只能用\Exception捕获
$ret['success'] = false;
if ($type == 'table') {
$ret['content'] = '创建失败,' . $th->getMessage();
} else {
$ret['content'] = '插入失败,' . $th->getMessage();
}
}
$ret['empty'] = 0;
return $ret;
}
没有报错信息,直接返回502或者无响应
没有报错信息,直接返回502或者无响应
webman版本:v2.1.2
swoole版本:v5.1.4
Nginx版本: 1.26.1
think-orm: webman/think-orm最新版
用的老大的教程,那个宝塔安装的Nginx转发模式
# Ws服务
location ^~ /sysgateway {
proxy_pass http://127.0.0.1:23111;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
break;
}
# 将请求转发到webman
location ^~ / {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_http_version 1.1;
proxy_set_header Connection "";
if (!-f $request_filename){
proxy_pass http://127.0.0.1:8787;
}
}
# 拒绝访问 plugins 目录
location ^~ /plugins {
return 404;
}
# 拒绝访问所有以 .php 结尾的文件
location ~ $ {
return 404;
}
# 允许访问 .well-known 目录
location ~ ^/.well-known/ {
allow all;
}
# 拒绝访问所有以 . 开头的文件或目录
location ~ /. {
return 404;
}
运行
strace -ttp cpu高的进程pid
看下进程在干什么
[root@ser3167469738 ~]# strace -ttp 28790
strace: Process 28790 attached
17:44:17.525174 epoll_wait(4,
然后没了
我再次执行请求后这下有了
strace -ttp 32093
strace: Process 32093 attached
18:04:04.292868 epoll_wait(4, 0x2508720, 32, -1) = -1 EINTR (Interrupted system call)
18:04:16.109971 --- SIGUSR1 {si_signo=SIGUSR1, si_code=SI_USER, si_pid=30956, si_uid=0} ---
18:04:16.110067 sendto(5, "\n", 1, 0, NULL, 0) = 1
18:04:16.110201 rt_sigreturn({mask=[]}) = -1 EINTR (Interrupted system call)
18:04:16.110273 epoll_wait(4, [{EPOLLIN, {u32=6, u64=6}}], 32, -1) = 1
18:04:16.110335 recvfrom(6, "\n", 1024, 0, NULL, NULL) = 1
18:04:16.110402 recvfrom(6, 0x7f50f57e1ac0, 1024, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
18:04:16.110697 epoll_wait(4, [], 32, 10) = 0
18:04:16.125669 epoll_wait(4, [], 32, 0) = 0
18:04:16.125912 close(3) = 0
18:04:16.129317 munmap(0x7f51053aa000, 4096) = 0
18:04:16.130086 rt_sigaction(SIGALRM, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.130179 rt_sigprocmask(SIG_UNBLOCK, [ALRM], NULL, 8) = 0
18:04:16.130227 rt_sigaction(SIGINT, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.130278 rt_sigprocmask(SIG_UNBLOCK, [INT], NULL, 8) = 0
18:04:16.130333 rt_sigaction(SIGTERM, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.130389 rt_sigprocmask(SIG_UNBLOCK, [TERM], NULL, 8) = 0
18:04:16.130434 rt_sigaction(SIGHUP, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.130484 rt_sigprocmask(SIG_UNBLOCK, [HUP], NULL, 8) = 0
18:04:16.130529 rt_sigaction(SIGTSTP, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.130579 rt_sigprocmask(SIG_UNBLOCK, [TSTP], NULL, 8) = 0
18:04:16.130624 rt_sigaction(SIGQUIT, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.130686 rt_sigprocmask(SIG_UNBLOCK, [QUIT], NULL, 8) = 0
18:04:16.130732 rt_sigaction(SIGUSR1, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.130782 rt_sigprocmask(SIG_UNBLOCK, [USR1], NULL, 8) = 0
18:04:16.130827 rt_sigaction(SIGUSR2, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.130888 rt_sigprocmask(SIG_UNBLOCK, [USR2], NULL, 8) = 0
18:04:16.130947 rt_sigaction(SIGABRT, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.130998 rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0
18:04:16.131053 rt_sigaction(SIGIO, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.131104 rt_sigprocmask(SIG_UNBLOCK, [IO], NULL, 8) = 0
18:04:16.131149 rt_sigaction(SIGPIPE, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.131198 rt_sigprocmask(SIG_UNBLOCK, [PIPE], NULL, 8) = 0
18:04:16.131465 close(0) = 0
18:04:16.131614 rt_sigaction(SIGIO, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.131692 rt_sigaction(SIGABRT, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.131744 rt_sigaction(SIGUSR2, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.131795 rt_sigaction(SIGHUP, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.131854 rt_sigaction(SIGINT, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.131916 rt_sigaction(SIGTERM, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.131975 rt_sigaction(SIGTSTP, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.132025 rt_sigaction(SIGQUIT, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.132074 rt_sigaction(SIGUSR1, {sa_handler=0xc5f366, sa_mask=~[ILL TRAP ABRT BUS FPE KILL SEGV CONT STOP TSTP TTIN TTOU SYS RTMIN RT_1], sa_flags=SA_RESTORER|SA_INTERRUPT|SA_SIGINFO, sa_restorer=0x7f50ffa2e400}, NULL, 8) = 0
18:04:16.132127 epoll_ctl(4, EPOLL_CTL_DEL, 6, 0x7ffd7afe6800) = 0
18:04:16.132179 close(5) = 0
18:04:16.132228 close(6) = 0
18:04:16.132274 close(4) = 0
18:04:16.137123 munmap(0x7f50f2a00000, 2621440) = 0
18:04:16.141725 munmap(0x7f50f3400000, 2097152) = 0
18:04:16.141841 munmap(0x7f50f3800000, 2097152) = 0
18:04:16.141935 munmap(0x7f50f3600000, 2097152) = 0
18:04:16.142031 munmap(0x7f50f2e00000, 2097152) = 0
18:04:16.142109 munmap(0x7f50f3000000, 2097152) = 0
18:04:16.142185 munmap(0x7f50f3a00000, 2097152) = 0
18:04:16.142352 munmap(0x7f50f3200000, 2097152) = 0
18:04:16.146071 munmap(0x7f50f5c08000, 2262696) = 0
18:04:16.146167 munmap(0x7f50f5a02000, 2118296) = 0
18:04:16.146252 munmap(0x7f50f57e2000, 2226024) = 0
18:04:16.146335 munmap(0x7f50f55b7000, 2272984) = 0
18:04:16.146423 munmap(0x7f50f5e31000, 2706920) = 0
18:04:16.146511 munmap(0x7f50f60c6000, 2159504) = 0
18:04:16.146583 munmap(0x7f50f62d6000, 9289816) = 0
18:04:16.146733 munmap(0x7f50f86ab000, 2168472) = 0
18:04:16.146824 munmap(0x7f50f8492000, 2196680) = 0
18:04:16.148325 munmap(0x7f5105315000, 196608) = 0
18:04:16.176576 munmap(0x7f50f2200000, 2097152) = 0
18:04:16.187702 munmap(0x7f50f2400000, 2097152) = 0
18:04:16.198696 munmap(0x7f50f2800000, 2097152) = 0
18:04:16.199213 munmap(0x7f50f3c00000, 2097152) = 0
18:04:16.199302 munmap(0x7f50f2600000, 2097152) = 0
18:04:16.210697 munmap(0x7f50f4400000, 2097152) = 0
18:04:16.211137 munmap(0x7f50f2000000, 2097152) = 0
18:04:16.211394 munmap(0x7f50fee00000, 2097152) = 0
18:04:16.212485 munmap(0x7f5105223000, 659456) = 0
18:04:16.212574 munmap(0x7f510536e000, 135168) = 0
18:04:16.213715 exit_group(0) = ?
18:04:16.215678 +++ exited with 0 +++
老大我找到问题了,我安装引导需要写入数据库信息,更新了.env文件,然后webman调试模式下会监听文件并重启进程,然后我这个情况刚好撞上了,不过我想问的是为啥重启进程后第一个请求会没有响应或者出现502,是因为Nginx转发的问题么
可能是因为请求没完成进程重启了导致,正常情况下进程会等待业务处理完毕后执行退出,但是有一些特别情况,例如请求很慢达到限定值2秒(可通过
Worker::$stopTimeout=10
更改)时进程被强行kill掉。还有使用了协程时因为整个进程是非阻塞的,收到信号后会立刻处理,执行退出,你的情况可能是用了协程导致。另外代码可以控制文件更新reload时机,
如果是要更新多个文件或者需要选择reload时机可以通过上面代码控制。
好的,谢谢老大