Serwer wewnętrzny
OxPHP uruchamia osobny serwer HTTP na dedykowanym porcie do kontroli stanu, metryk Prometheus oraz podglądu aktywnej konfiguracji. Pozostaje całkowicie odizolowany od głównego listenera aplikacji: bez TLS, bez ograniczania liczby żądań, bez ID żądań i bez przetwarzania zdarzeń.
Jak to działa
Ustaw INTERNAL_ADDR na adres nasłuchu (np. 127.0.0.1:9090), a OxPHP uruchomi drugi listener HTTP pod tym adresem. Serwer wewnętrzny udostępnia wbudowane endpointy wymienione poniżej:
/health— zbiorczy status w formacie JSON/health/liveness,/healthz(alias) — sonda liveness/health/readiness,/readyz(alias) — sonda readiness/health/startup,/startupz(alias) — sonda startup/metrics— ekspozycja Prometheus/config— aktywna konfiguracja serwera w formacie JSON
Wtyczki mogą rejestrować dodatkowe endpointy pod prefiksem /__<plugin>/. Podczas łagodnego zamknięcia serwer wewnętrzny pozostaje dostępny, dopóki główny serwer nie zakończy opróżniania połączeń.
Serwer wewnętrzny uruchamia się tylko wtedy, gdy INTERNAL_ADDR jest jawnie ustawiony. Bez niego endpointy health, metrics i config nie są dostępne przez HTTP.
Konfiguracja
| Zmienna | Wartość domyślna | Opis |
|---|---|---|
INTERNAL_ADDR |
(nieustawione) | Adres serwera wewnętrznego. Nie uruchamia się, gdy nieustawiony. Wartość zawierająca tylko port (:9090 lub 9090) wiąże się z 127.0.0.1; użyj jawnego 0.0.0.0:9090, aby udostępnić go poza hostem. Przykład: 127.0.0.1:9090 |
INTERNAL_ALLOW_IPS |
(nieustawione) | Lista dozwolonych adresów CIDR/IP rozdzielona przecinkami. Hosty spoza listy otrzymują 403 na ścieżkach /metrics, /config oraz /__<plugin>/; sondy stanu pozostają zawsze osiągalne. Nieustawione/puste = zezwól na wszystkie. Loopback nie jest domyślnie uwzględniony — wpisz 127.0.0.1/32, aby zachować dostęp z localhost. Nieprawidłowa lista przerywa uruchamianie |
Endpointy
GET /health
Zwraca status stanu w formacie JSON. Używaj go dla sond readiness i liveness w Kubernetes.
200 OK — wszystkie systemy sprawne:
{
"status": "ok",
"uptime_secs": 3612,
"total_requests": 48203,
"active_connections": 7,
"executor_healthy": true,
"plugins": {
"otel": "ok"
}
}503 Service Unavailable — wtyczka zgłosiła awarię:
{
"status": "degraded",
"uptime_secs": 3612,
"total_requests": 48203,
"active_connections": 7,
"executor_healthy": true,
"plugins": {
"otel": "failed"
}
}Obiekt plugins wymienia każdą załadowaną wtyczkę wraz z jej statusem stanu: "ok", "degraded" lub "failed". Endpoint zwraca 503, gdy dowolna wtyczka zgłasza "failed" lub gdy executor skryptów jest niesprawny (executor_healthy: false). Wtyczki "degraded" pojawiają się w ciele JSON, ale status HTTP pozostaje 200.
GET /metrics
Zwraca metryki zgodne z Prometheus w formacie tekstowym (text/plain; version=0.0.4; charset=utf-8). Zawsze zwraca 200.
curl http://localhost:9090/metrics# HELP oxphp_requests_total Total HTTP requests
# TYPE oxphp_requests_total counter
oxphp_requests_total 48203
# HELP oxphp_active_connections Current open connections
# TYPE oxphp_active_connections gauge
oxphp_active_connections 7
...Pełną listę dostępnych metryk znajdziesz w Metryki.
GET /config
Zwraca aktywną konfigurację serwera w formacie JSON. Zawsze zwraca 200.
curl -s http://localhost:9090/config | jq .{
"listen_addr": "0.0.0.0:80",
"document_root": "/var/www/html/public",
"entry_file": "/var/www/html/public/index.php",
"log_level": "info",
"executor_type": "sapi",
"php_workers": "8",
"tokio_workers": 4,
"queue_capacity": 1024,
"max_connections": 10000,
"drain_timeout_seconds": 30,
"header_timeout_seconds": 5,
"rate_limit": 100,
"rate_window_seconds": 60,
"tls_enabled": true,
"tls_min_version": "1.2",
"compression_level": 4,
"access_log": "all",
"max_query_body": 524288,
"worker_mode_enabled": false,
"worker_max_memory_mib": 0,
"static_max_age": 2592000,
"static_revalidate": false,
"async_workers": 0,
"async_queue_capacity": 0,
"async_max_fibers": 256,
"async_in_flight_cap": 0,
"trace_context": false,
"superglobals_enabled": true,
"trusted_proxies": false,
"plugins": {}
}Ścieżki do certyfikatu i klucza TLS nigdy nie są ujawniane (udostępniana jest tylko wartość logiczna tls_enabled), a internal_addr oraz error_pages_dir są usuwane z serwowanej odpowiedzi — to topologia wdrożenia i ścieżki w systemie plików, które pomagają atakującemu, a nie są potrzebne scraperom.
Endpointy wtyczek
Wtyczki mogą rejestrować własne endpointy pod prefiksem /__<plugin_name>/. Na przykład wtyczka o nazwie otel mogłaby udostępniać /__otel/status. Te endpointy są dostępne tylko wtedy, gdy odpowiednia wtyczka jest załadowana i zarejestrowała handler.
Każda ścieżka niepasująca do wbudowanego endpointu ani do endpointu wtyczki zwraca 404 Not Found.
Integracja z Kubernetes
Sonda readiness
Użyj /health, aby kontrolować, czy Kubernetes kieruje ruch do poda:
readinessProbe:
httpGet:
path: /health
port: 9090
initialDelaySeconds: 2
periodSeconds: 5Gdy /health zwraca 503, Kubernetes usuwa poda z listy endpointów Service. Ruch wznawia się, gdy endpoint ponownie zwróci 200.
Sonda liveness
Użyj tego samego endpointu, aby restartować pody, które przestają odpowiadać:
livenessProbe:
httpGet:
path: /health
port: 9090
initialDelaySeconds: 5
periodSeconds: 10
failureThreshold: 3Sonda startup
Dla aplikacji z wolnym rozruchem (duże frameworki, ciężkie autoloadery):
startupProbe:
httpGet:
path: /health
port: 9090
initialDelaySeconds: 1
periodSeconds: 2
failureThreshold: 15Bezpieczeństwo
Serwer wewnętrzny nie ma uwierzytelniania za pomocą tokenu bearer; dostęp jest kontrolowany przez to, gdzie się wiąże, oraz przez INTERNAL_ALLOW_IPS. Aby go zabezpieczyć:
- Powiąż z localhost —
INTERNAL_ADDRzawierający tylko port (:9090) już wiąże się z127.0.0.1; jawne127.0.0.1:9090sprawia, że port jest osiągalny tylko z wnętrza kontenera lub hosta - Ustaw
INTERNAL_ALLOW_IPS, gdy listener musi być osiągalny poza hostem — lista dozwolonych adresów CIDR/IP, która zwraca403na ścieżkach/metrics,/configoraz ścieżkach wtyczek hostom spoza niej, podczas gdy sondy stanu pozostają osiągalne. Loopback nie jest domyślnie uwzględniony, więc dodaj127.0.0.1/32, jeśli nadal potrzebujesz dostępu z localhost. Serwer ostrzega przy uruchamianiu, jeśli listener jest wystawiony poza hostem bez ustawionej listy dozwolonych - Nie udostępniaj jako Service w Kubernetes — zadeklaruj port jako
containerPort, ale nie twórz dla niego Service. Sondy Kubernetes mają bezpośredni dostęp do portów kontenera - Używaj polityk sieciowych — ogranicz dostęp na warstwie sieciowej, jeśli port musi być wystawiony
Endpoint /config ujawnia szczegóły operacyjne (document root, limity liczby żądań, liczby workerów, wartości limitów czasu). Ścieżki TLS, internal_addr oraz error_pages_dir są usuwane, ale zastanów się, czy reszta powinna być dostępna spoza poda.
Przykład Docker
Aby szybko rzucić okiem, możesz opublikować port wewnętrzny; w środowisku produkcyjnym powiąż serwer wewnętrzny z localhost i korzystaj z sond Kubernetes.
services:
app:
image: ghcr.io/oxphp/oxphp:0.10.0
ports:
- "80:80"
- "9090:9090"
environment:
- DOCUMENT_ROOT=/var/www/html/public
- INTERNAL_ADDR=0.0.0.0:9090services:
app:
image: ghcr.io/oxphp/oxphp:0.10.0
ports:
- "80:80"
environment:
- DOCUMENT_ROOT=/var/www/html/public
- INTERNAL_ADDR=127.0.0.1:9090Rozwiązywanie problemów
Endpointy health, metrics i config są niedostępne
INTERNAL_ADDR nie jest ustawiony.
Rozwiązanie: Dodaj zmienną środowiskową:
INTERNAL_ADDR=0.0.0.0:9090/health zwraca 503, ale aplikacja działa
Załadowana wtyczka zgłasza PluginHealth::Failed. Sprawdź obiekt plugins w odpowiedzi health, aby zidentyfikować, która wtyczka zawodzi:
curl -s http://localhost:9090/health | jq '.plugins'Nie można połączyć się z serwerem wewnętrznym spoza kontenera
Serwer jest powiązany z 127.0.0.1, który jest dostępny tylko z wnętrza kontenera.
Rozwiązanie: Zmień na 0.0.0.0 dla dostępu z zewnątrz lub użyj sond Kubernetes, które mają bezpośredni dostęp do kontenera.
Metryki nie pokazują metryk trybu worker ani async
Metryki trybu worker pojawiają się tylko wtedy, gdy tryb worker jest włączony (WORKER_MODE_ENABLED=true). Metryki async pojawiają się tylko wtedy, gdy ASYNC_WORKERS > 0 i co najmniej jedno zadanie zostało wysłane lub odrzucone.
Zobacz też
- Metryki — pełne odniesienie do metryk Prometheus
- Kontrole stanu — szczegółowe zachowanie kontroli stanu
- Odniesienie do konfiguracji — wszystkie zmienne środowiskowe
- Łagodne zamknięcie — sekwencja zamykania i cykl życia serwera wewnętrznego