diff --git a/scripts/diagnose.bat b/scripts/diagnose.bat new file mode 100644 index 0000000..7f78c6c --- /dev/null +++ b/scripts/diagnose.bat @@ -0,0 +1,78 @@ +@echo off +setlocal EnableDelayedExpansion +chcp 65001 >nul 2>&1 + +echo. +echo ============================================================ +echo Matab Startup Diagnostics +echo ============================================================ +echo. + +REM --- [1] Service Status --- +echo [1] Service Status: +for %%S in (MatabPHPCgi MatabAutostart) do ( + sc query %%S 2>nul | find "RUNNING" >nul + if !errorlevel! equ 0 ( + echo %%S [RUNNING] + ) else ( + sc query %%S 2>nul | find "STOPPED" >nul + if !errorlevel! equ 0 ( + echo %%S [STOPPED] + ) else ( + echo %%S [NOT INSTALLED] + ) + ) +) +echo. + +REM --- [2] Port Check --- +echo [2] Port Availability: +powershell -NoProfile -Command ^ + "foreach($p in @(8000,9001)){try{$t=New-Object Net.Sockets.TcpClient;$t.Connect('127.0.0.1',$p);$t.Close();Write-Host (' Port ' + $p + ' [OPEN]')}catch{Write-Host (' Port ' + $p + ' [CLOSED]')}}" +echo. + +REM --- [3] Nginx health (no PHP) --- +echo [3] Nginx response time (no PHP): +powershell -NoProfile -Command ^ + "try{$sw=[Diagnostics.Stopwatch]::StartNew();$r=Invoke-WebRequest 'http://localhost:8000/nginx-health' -TimeoutSec 5 -UseBasicParsing -ErrorAction Stop;$sw.Stop();Write-Host (' ' + $sw.ElapsedMilliseconds + ' ms (status ' + $r.StatusCode + ')')}catch{Write-Host ' FAILED - nginx not responding'}" +echo. + +REM --- [4] First PHP request timing --- +echo [4] First PHP request time (cold = slow, warm = fast): +powershell -NoProfile -Command ^ + "$sw=[Diagnostics.Stopwatch]::StartNew(); try{ $r=Invoke-WebRequest 'http://localhost:8000/admin/login' -TimeoutSec 30 -UseBasicParsing -MaximumRedirection 5 -ErrorAction SilentlyContinue; $sw.Stop(); $ms=$sw.ElapsedMilliseconds; $label=if($ms -lt 800){'[FAST]'}elseif($ms -lt 3000){'[OK - warming up]'}else{'[SLOW - OPcache cold]'}; Write-Host (' ' + $ms + ' ms status=' + $r.StatusCode + ' ' + $label) }catch{ $sw.Stop(); Write-Host (' FAILED after ' + $sw.ElapsedMilliseconds + ' ms err=' + $_.Exception.Message) }" +echo. + +REM --- [5] Second PHP request timing (should be faster) --- +echo [5] Second PHP request time (OPcache should kick in): +powershell -NoProfile -Command ^ + "$sw=[Diagnostics.Stopwatch]::StartNew(); try{ $r=Invoke-WebRequest 'http://localhost:8000/admin/login' -TimeoutSec 30 -UseBasicParsing -MaximumRedirection 5 -ErrorAction SilentlyContinue; $sw.Stop(); $ms=$sw.ElapsedMilliseconds; $label=if($ms -lt 500){'[FAST - OPcache working]'}elseif($ms -lt 1500){'[OK]'}else{'[SLOW - problem]'}; Write-Host (' ' + $ms + ' ms status=' + $r.StatusCode + ' ' + $label) }catch{ $sw.Stop(); Write-Host (' FAILED after ' + $sw.ElapsedMilliseconds + ' ms err=' + $_.Exception.Message) }" +echo. + +REM --- [6] PHP process count --- +echo [6] PHP worker processes: +powershell -NoProfile -Command ^ + "$procs=Get-Process php-cgi -ErrorAction SilentlyContinue;if($procs){Write-Host (' ' + $procs.Count + ' php-cgi processes running (expected: 9 = 1 master + 8 children)')}else{Write-Host ' No php-cgi processes found!'}" +echo. + +REM --- [7] OPcache file cache --- +echo [7] OPcache file cache on disk: +powershell -NoProfile -Command ^ + "if(Test-Path 'C:\tmp\php-opcache'){$files=(Get-ChildItem 'C:\tmp\php-opcache' -Recurse -File -ErrorAction SilentlyContinue).Count;$size=[math]::Round((Get-ChildItem 'C:\tmp\php-opcache' -Recurse -File -ErrorAction SilentlyContinue|Measure-Object -Property Length -Sum).Sum/1MB,1);Write-Host (' ' + $files + ' files, ' + $size + ' MB cached')}else{Write-Host ' Directory not found (C:\tmp\php-opcache)'}" +echo. + +REM --- [8] Warmup task status --- +echo [8] MatabWarmup scheduled task: +powershell -NoProfile -Command ^ + "try{$t=Get-ScheduledTask -TaskName 'MatabWarmup' -ErrorAction Stop;$info=Get-ScheduledTaskInfo -TaskName 'MatabWarmup' -ErrorAction SilentlyContinue;$last=if($info.LastRunTime){$info.LastRunTime.ToString('yyyy-MM-dd HH:mm:ss')}else{'never'};Write-Host (' State: ' + $t.State + ' | Last run: ' + $last + ' | Last result: ' + $info.LastTaskResult)}catch{Write-Host ' Task not found - run install.bat'}" +echo. + +echo ============================================================ +echo Interpretation: +echo - If [4] ^> 3000ms and [5] ^< 1000ms: OPcache warming up normally +echo - If both [4] and [5] are slow: PHP or DB issue +echo - If port 9001 CLOSED: MatabPHPCgi service failed +echo - If nginx-health fails but port 8000 open: nginx config error +echo ============================================================ +echo. +pause diff --git a/scripts/matab-autostart.xml b/scripts/matab-autostart.xml index f4e13ba..380e190 100644 --- a/scripts/matab-autostart.xml +++ b/scripts/matab-autostart.xml @@ -8,6 +8,7 @@ %BASE%\nginx Tcpip MatabPHPCgi + AboveNormal diff --git a/scripts/matab-phpcgi.xml b/scripts/matab-phpcgi.xml index 346a8bf..14a635c 100644 --- a/scripts/matab-phpcgi.xml +++ b/scripts/matab-phpcgi.xml @@ -9,6 +9,7 @@ Tcpip + AboveNormal diff --git a/scripts/nginx/conf/nginx.conf b/scripts/nginx/conf/nginx.conf index d9efb4f..e93b42a 100644 --- a/scripts/nginx/conf/nginx.conf +++ b/scripts/nginx/conf/nginx.conf @@ -35,9 +35,17 @@ http { application/xml image/svg+xml; + # FastCGI connection pool — reuse TCP connections to php-cgi instead of + # opening a new one per request (reduces latency on every PHP request) + upstream php_fpm { + server 127.0.0.1:9001; + keepalive 16; + } + server { listen 8000; - server_name localhost 127.0.0.1; + listen [::]:8000; + server_name localhost 127.0.0.1 ::1; root "D:/git/matab-panel/public"; index index.php; @@ -46,16 +54,24 @@ http { open_file_cache_min_uses 2; open_file_cache_errors on; + # Lightweight health-check endpoint — no PHP, used by warmup script + location = /nginx-health { + access_log off; + return 200 "ok"; + add_header Content-Type text/plain; + } + location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { - fastcgi_pass 127.0.0.1:9001; + fastcgi_pass php_fpm; fastcgi_index index.php; fastcgi_read_timeout 120; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; + fastcgi_keep_conn on; fastcgi_buffering on; fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; diff --git a/scripts/nginx/conf/nginx.conf.template b/scripts/nginx/conf/nginx.conf.template index 9d2a2c7..ee02032 100644 --- a/scripts/nginx/conf/nginx.conf.template +++ b/scripts/nginx/conf/nginx.conf.template @@ -35,9 +35,17 @@ http { application/xml image/svg+xml; + # FastCGI connection pool — reuse TCP connections to php-cgi instead of + # opening a new one per request (reduces latency on every PHP request) + upstream php_fpm { + server 127.0.0.1:9001; + keepalive 16; + } + server { listen 8000; - server_name localhost 127.0.0.1; + listen [::]:8000; + server_name localhost 127.0.0.1 ::1; root "{{PUBLIC_DIR}}"; index index.php; @@ -46,16 +54,24 @@ http { open_file_cache_min_uses 2; open_file_cache_errors on; + # Lightweight health-check endpoint — no PHP, used by warmup script + location = /nginx-health { + access_log off; + return 200 "ok"; + add_header Content-Type text/plain; + } + location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { - fastcgi_pass 127.0.0.1:9001; + fastcgi_pass php_fpm; fastcgi_index index.php; fastcgi_read_timeout 120; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; + fastcgi_keep_conn on; fastcgi_buffering on; fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; diff --git a/scripts/warmup.bat b/scripts/warmup.bat index f208749..850a85a 100644 --- a/scripts/warmup.bat +++ b/scripts/warmup.bat @@ -1,13 +1,13 @@ @echo off setlocal EnableDelayedExpansion -echo [Warmup] Waiting for Matab web server on port 8000... +echo [Warmup] Waiting for nginx on port 8000... powershell -NoProfile -Command ^ - "$ok=0; for($i=0;$i -lt 120;$i++){try{$t=New-Object Net.Sockets.TcpClient;$t.Connect('127.0.0.1',8000);$t.Close();$ok=1;break}catch{Start-Sleep -Milliseconds 500}}; if(!$ok){Write-Host '[Warmup] Timeout - server not ready.'; exit 1}" + "$ok=0; for($i=0;$i -lt 120;$i++){try{$r=(Invoke-WebRequest 'http://localhost:8000/nginx-health' -TimeoutSec 2 -UseBasicParsing -ErrorAction Stop).StatusCode; if($r -eq 200){$ok=1;break}}catch{Start-Sleep -Milliseconds 500}}; if(!$ok){Write-Host '[Warmup] Timeout - server not ready.'; exit 1}" if %errorlevel% neq 0 exit /b 1 -echo [Warmup] Firing 10 parallel requests to warm up all 8 PHP workers... +echo [Warmup] Firing parallel requests to warm up all 8 PHP workers... powershell -NoProfile -Command ^ - "$urls='http://localhost:8000/','http://localhost:8000/matab/login'; $jobs=@(); 1..10|ForEach-Object{$u=$urls[($_ %% 2)]; $jobs+=Start-Job -ScriptBlock{param($u)try{Invoke-WebRequest $u -TimeoutSec 60 -UseBasicParsing -ErrorAction SilentlyContinue|Out-Null}catch{}} -ArgumentList $u}; $jobs|Wait-Job|Out-Null; $jobs|Remove-Job" + "$urls=@('http://localhost:8000/admin/login','http://localhost:8000/admin','http://localhost:8000/'); $jobs=@(); 1..16|ForEach-Object{$u=$urls[($_ %% $urls.Count)]; $jobs+=Start-Job -ScriptBlock{param($u)try{Invoke-WebRequest $u -TimeoutSec 60 -UseBasicParsing -ErrorAction SilentlyContinue|Out-Null}catch{}} -ArgumentList $u}; $jobs|Wait-Job|Out-Null; $jobs|Remove-Job" echo [Warmup] PHP OPcache warmed up successfully.