From 546d350f3a10224dd265066c233493df8ac2584f Mon Sep 17 00:00:00 2001 From: zhenhui <1276357500@qq.com> Date: Wed, 24 Jun 2026 10:24:59 +0800 Subject: [PATCH] =?UTF-8?q?1.=E4=BF=AE=E5=A4=8D=E4=B8=8A=E4=BC=A0=E6=BC=8F?= =?UTF-8?q?=E6=B4=9E=E5=92=8CSQL=E6=B3=A8=E5=85=A5=E6=BC=8F=E6=B4=9E-?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=9C=8D=E5=8A=A1=E7=AB=AF=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/process/AngpowImportJobs.php | 22 ++++--- app/process/PlayxJobs.php | 21 ++++--- config/process.php | 42 +++++++------ scripts/check_start.php | 103 +++++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 35 deletions(-) create mode 100644 scripts/check_start.php diff --git a/app/process/AngpowImportJobs.php b/app/process/AngpowImportJobs.php index 7298224..6244924 100644 --- a/app/process/AngpowImportJobs.php +++ b/app/process/AngpowImportJobs.php @@ -23,20 +23,19 @@ class AngpowImportJobs private const BATCH_LIMIT = 100; private const MAX_RETRY = 3; - protected Client $http; + protected ?Client $http = null; - public function __construct() + public function onWorkerStart(Worker $worker): void { - // 确保定时任务只在一个 worker 上运行 - if (!Worker::getAllWorkers()) { - return; - } - $this->http = new Client($this->buildGuzzleOptions()); - Timer::add(self::TIMER_SECONDS, [$this, 'pushPendingOrders']); } + protected function getHttp(): ?Client + { + return $this->http; + } + /** * Guzzle 默认校验 HTTPS;Windows 未配置 CA 时会出现 cURL error 60。 * 优先使用 PLAYX_ANGPOW_IMPORT_CACERT 指向 cacert.pem;否则可按环境关闭校验(仅开发)。 @@ -70,6 +69,11 @@ class AngpowImportJobs public function pushPendingOrders(): void { + $http = $this->getHttp(); + if ($http === null) { + return; + } + $conf = config('playx.angpow_import'); if (!is_array($conf)) { return; @@ -165,7 +169,7 @@ class AngpowImportJobs $res = null; $body = ''; try { - $res = $this->http->post($url, [ + $res = $http->post($url, [ 'headers' => [ 'Content-Type' => 'application/json', 'X-Request-Signature' => $signature, diff --git a/app/process/PlayxJobs.php b/app/process/PlayxJobs.php index 4dfcbe4..db9c4d8 100644 --- a/app/process/PlayxJobs.php +++ b/app/process/PlayxJobs.php @@ -16,15 +16,10 @@ use Workerman\Worker; */ class PlayxJobs { - protected Client $http; + protected ?Client $http = null; - public function __construct() + public function onWorkerStart(Worker $worker): void { - // 确保定时任务只在一个 worker 上运行 - if (!Worker::getAllWorkers()) { - return; - } - $this->http = new Client([ 'timeout' => 20, 'http_errors' => false, @@ -34,11 +29,21 @@ class PlayxJobs Timer::add(60, [$this, 'retryFailedGrants']); } + protected function getHttp(): ?Client + { + return $this->http; + } + /** * 轮询:已 accepted 的订单,查询终态 */ public function pollTransactionStatus(): void { + $http = $this->getHttp(); + if ($http === null) { + return; + } + $baseUrl = strval(config('playx.api.base_url', '')); if ($baseUrl === '') { return; @@ -57,7 +62,7 @@ class PlayxJobs foreach ($list as $order) { /** @var MallOrder $order */ try { - $res = $this->http->get($url, [ + $res = $http->get($url, [ 'query' => [ 'externalTransactionId' => $order->external_transaction_id, ], diff --git a/config/process.php b/config/process.php index 5fe5e78..892b735 100644 --- a/config/process.php +++ b/config/process.php @@ -16,14 +16,20 @@ use support\Log; use support\Request; use app\process\Http; use app\process\AngpowImportJobs; +use app\process\PlayxJobs; global $argv; -return [ +$workerCount = env('WEBMAN_WORKER_COUNT', ''); +if ($workerCount === '' || $workerCount === null) { + $workerCount = max(4, cpu_count() * 4); +} + +$process = [ 'webman' => [ 'handler' => Http::class, 'listen' => 'http://0.0.0.0:6969', - 'count' => cpu_count() * 4, + 'count' => (int) $workerCount, 'user' => '', 'group' => '', 'reusePort' => false, @@ -36,12 +42,10 @@ return [ 'publicPath' => public_path() ] ], - // File update detection and automatic reload 'monitor' => [ 'handler' => app\process\Monitor::class, 'reloadable' => false, 'constructor' => [ - // Monitor these directories 'monitorDir' => array_merge([ app_path(), config_path(), @@ -49,26 +53,28 @@ return [ base_path() . '/support', base_path() . '/resource', base_path() . '/.env', - ], glob(base_path() . '/plugin/*/app'), glob(base_path() . '/plugin/*/config'), glob(base_path() . '/plugin/*/api')), - // Files with these suffixes will be monitored + ], glob(base_path() . '/plugin/*/app') ?: [], glob(base_path() . '/plugin/*/config') ?: [], glob(base_path() . '/plugin/*/api') ?: []), 'monitorExtensions' => [ 'php', 'html', 'htm', 'env' ], 'options' => [ - 'enable_file_monitor' => !in_array('-d', $argv) && DIRECTORY_SEPARATOR === '/', + 'enable_file_monitor' => !in_array('-d', $argv ?? []) && DIRECTORY_SEPARATOR === '/', 'enable_memory_monitor' => DIRECTORY_SEPARATOR === '/', ] ] - ] - , - // PlayX 闭环任务:轮询交易终态/失败重试 - 'playx_jobs' => [ - 'handler' => app\process\PlayxJobs::class, - 'reloadable' => false, - ], - // Angpow 导入推送任务:订单兑换后推送到对方平台 - 'angpow_import_jobs' => [ - 'handler' => AngpowImportJobs::class, - 'reloadable' => false, ], ]; + +$disableBackgroundJobs = filter_var(env('PLAYX_DISABLE_BACKGROUND_JOBS', '0'), FILTER_VALIDATE_BOOLEAN); +if (!$disableBackgroundJobs) { + $process['playx_jobs'] = [ + 'handler' => PlayxJobs::class, + 'reloadable' => false, + ]; + $process['angpow_import_jobs'] = [ + 'handler' => AngpowImportJobs::class, + 'reloadable' => false, + ]; +} + +return $process; diff --git a/scripts/check_start.php b/scripts/check_start.php new file mode 100644 index 0000000..eaea0df --- /dev/null +++ b/scripts/check_start.php @@ -0,0 +1,103 @@ +#!/usr/bin/env php +getMessage() . ' @ ' . $e->getFile() . ':' . $e->getLine(); +} + +if (empty($errors)) { + foreach (config('process', []) as $name => $proc) { + $handler = $proc['handler'] ?? ''; + if (is_string($handler) && $handler !== '' && !class_exists($handler)) { + $errors[] = "进程 [{$name}] 处理器不存在: {$handler}"; + } + } +} + +if (empty($errors)) { + try { + support\think\Db::execute('SELECT 1'); + } catch (Throwable $e) { + $errors[] = '数据库连接失败: ' . $e->getMessage(); + } +} + +$listen = config('process.webman.listen', ''); +if ($listen !== '' && empty($errors)) { + $parsed = parse_url($listen); + $host = $parsed['host'] ?? '0.0.0.0'; + $port = $parsed['port'] ?? 80; + $bindHost = $host === '0.0.0.0' ? '127.0.0.1' : $host; + $sock = @stream_socket_server("tcp://{$bindHost}:{$port}", $errno, $errstr); + if ($sock === false) { + $errors[] = "端口 {$port} 无法监听: [{$errno}] {$errstr}"; + $errors[] = "可执行: ss -lntp | grep {$port} 查看是否被占用"; + } else { + fclose($sock); + } +} + +if ($errors) { + echo "=== 启动自检失败 ===\n"; + foreach ($errors as $i => $msg) { + echo ($i + 1) . '. ' . $msg . "\n"; + } + echo "\n下一步:\n"; + echo " php start.php start # 前台启动看完整报错\n"; + echo " tail -n 80 runtime/logs/workerman.log\n"; + echo " tail -n 80 runtime/logs/stdout.log\n"; + exit(1); +} + +echo "=== 启动自检通过 ===\n"; +echo "监听: {$listen}\n"; +echo "Worker 数: " . (config('process.webman.count') ?? '?') . "\n"; +echo "路由数: " . count(Webman\Route::getRoutes()) . "\n"; +echo "\n请执行: php start.php start\n"; +echo "确认无误后再: php start.php start -d\n"; +exit(0);