Внутренний сервер
OxPHP запускает отдельный HTTP-сервер на выделенном порту для проверок работоспособности, метрик Prometheus и просмотра конфигурации в реальном времени. Он полностью изолирован от основного слушателя приложения: без TLS, без ограничения частоты запросов, без идентификаторов запросов и без обработки событий.
Как это работает
Задайте в INTERNAL_ADDR адрес для прослушивания (например, 127.0.0.1:9090), и OxPHP запустит второй HTTP-слушатель на этом адресе. Внутренний сервер предоставляет встроенные эндпоинты, перечисленные ниже:
/health— сводный статус в формате JSON/health/liveness,/healthz(псевдоним) — проба liveness/health/readiness,/readyz(псевдоним) — проба readiness/health/startup,/startupz(псевдоним) — проба startup/metrics— экспозиция Prometheus/config— активная конфигурация сервера в формате JSON
Плагины могут регистрировать дополнительные эндпоинты с префиксом /__<plugin>/. Во время корректного завершения работы внутренний сервер остаётся доступным, пока основной сервер не завершит слив соединений.
Внутренний сервер запускается только при явно заданном INTERNAL_ADDR. Без него эндпоинты health, metrics и config недоступны по HTTP.
Конфигурация
| Переменная | По умолчанию | Описание |
|---|---|---|
INTERNAL_ADDR |
(не задано) | Адрес внутреннего сервера. Не запускается, если не задан. Значение только с портом (:9090 или 9090) привязывается к 127.0.0.1; используйте явный 0.0.0.0:9090, чтобы открыть доступ за пределами хоста. Пример: 127.0.0.1:9090 |
INTERNAL_ALLOW_IPS |
(не задано) | Список разрешений из CIDR/IP через запятую. Узлы вне списка получают 403 на путях /metrics, /config и /__<plugin>/; пробы работоспособности остаются доступны всегда. Не задано/пусто = разрешить всё. Loopback не подразумевается — укажите 127.0.0.1/32, чтобы сохранить доступ с localhost. Некорректный список прерывает запуск |
Эндпоинты
GET /health
Возвращает статус работоспособности в формате JSON. Используйте его для проб readiness и liveness в Kubernetes.
200 OK — все системы исправны:
{
"status": "ok",
"uptime_secs": 3612,
"total_requests": 48203,
"active_connections": 7,
"executor_healthy": true,
"plugins": {
"otel": "ok"
}
}503 Service Unavailable — плагин сообщил о сбое:
{
"status": "degraded",
"uptime_secs": 3612,
"total_requests": 48203,
"active_connections": 7,
"executor_healthy": true,
"plugins": {
"otel": "failed"
}
}Объект plugins перечисляет все загруженные плагины с их статусом работоспособности: "ok", "degraded" или "failed". Эндпоинт возвращает 503, когда любой плагин сообщает "failed" или исполнитель скриптов неисправен (executor_healthy: false). Плагины со статусом "degraded" присутствуют в теле JSON, но HTTP-статус остаётся 200.
GET /metrics
Возвращает совместимые с Prometheus метрики в текстовом формате (text/plain; version=0.0.4; charset=utf-8). Всегда возвращает 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
...Полный список доступных метрик см. в разделе Метрики.
GET /config
Возвращает активную конфигурацию сервера в формате JSON. Всегда возвращает 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": {}
}Пути к файлам TLS-сертификата и ключа никогда не выводятся (доступен только булев флаг tls_enabled), а internal_addr и error_pages_dir вычищаются из отдаваемого ответа — это топология развёртывания и пути в файловой системе, которые помогают злоумышленнику и не нужны сборщикам метрик.
Эндпоинты плагинов
Плагины могут регистрировать собственные эндпоинты с префиксом /__<plugin_name>/. Например, плагин с именем otel может предоставлять /__otel/status. Эти эндпоинты доступны только в том случае, если соответствующий плагин загружен и зарегистрировал обработчик.
Любой путь, не соответствующий встроенному эндпоинту или эндпоинту плагина, возвращает 404 Not Found.
Интеграция с Kubernetes
Проба readiness
Используйте /health, чтобы управлять тем, направляет ли Kubernetes трафик на под:
readinessProbe:
httpGet:
path: /health
port: 9090
initialDelaySeconds: 2
periodSeconds: 5Когда /health возвращает 503, Kubernetes удаляет под из списка эндпоинтов Service. Трафик возобновляется, как только эндпоинт снова возвращает 200.
Проба liveness
Используйте тот же эндпоинт, чтобы перезапускать поды, которые перестают отвечать:
livenessProbe:
httpGet:
path: /health
port: 9090
initialDelaySeconds: 5
periodSeconds: 10
failureThreshold: 3Проба startup
Для приложений с медленным запуском (крупные фреймворки, тяжёлые автозагрузчики):
startupProbe:
httpGet:
path: /health
port: 9090
initialDelaySeconds: 1
periodSeconds: 2
failureThreshold: 15Безопасность
Внутренний сервер не имеет аутентификации по bearer-токену; доступ определяется тем, к чему он привязан, и переменной INTERNAL_ALLOW_IPS. Чтобы защитить его:
- Привяжите к localhost —
INTERNAL_ADDRтолько с портом (:9090) уже привязывается к127.0.0.1; явный127.0.0.1:9090оставляет порт доступным только изнутри контейнера или хоста - Задайте
INTERNAL_ALLOW_IPS, когда слушатель должен быть доступен за пределами хоста — список разрешений из CIDR/IP, который возвращает403на путях/metrics,/configи путях плагинов узлам вне списка, тогда как пробы работоспособности остаются доступны. Loopback не подразумевается, поэтому добавьте127.0.0.1/32, если вам всё ещё нужен доступ с localhost. Сервер выдаёт предупреждение при запуске, если слушатель открыт за пределами хоста без заданного списка разрешений - Не публикуйте как Kubernetes Service — объявите порт как
containerPort, но не создавайте для него Service. Пробы Kubernetes обращаются к портам контейнера напрямую - Используйте сетевые политики — ограничивайте доступ на сетевом уровне, если порт всё же нужно открыть
Эндпоинт /config раскрывает операционные детали (корень документов, ограничения частоты запросов, число воркеров, значения таймаутов). Пути TLS, internal_addr и error_pages_dir вычищаются, но подумайте, должно ли остальное быть доступно снаружи пода.
Пример Docker
Для быстрого просмотра можно опубликовать внутренний порт; в продакшене привязывайте внутренний сервер к localhost и используйте пробы 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:9090Устранение неполадок
Эндпоинты health, metrics и config недоступны
INTERNAL_ADDR не задан.
Исправление: Добавьте переменную окружения:
INTERNAL_ADDR=0.0.0.0:9090/health возвращает 503, но приложение работает
Загруженный плагин сообщает PluginHealth::Failed. Проверьте объект plugins в ответе health, чтобы определить, какой плагин даёт сбой:
curl -s http://localhost:9090/health | jq '.plugins'Не удаётся достучаться до внутреннего сервера снаружи контейнера
Сервер привязан к 127.0.0.1, который доступен только изнутри контейнера.
Исправление: Измените на 0.0.0.0 для внешнего доступа или используйте пробы Kubernetes, которые обращаются к контейнеру напрямую.
Метрики не показывают режим воркеров или асинхронные метрики
Метрики режима воркеров появляются только при включённом режиме воркеров (WORKER_MODE_ENABLED=true). Асинхронные метрики появляются только при ASYNC_WORKERS > 0 и когда хотя бы одна задача была отправлена или отклонена.
Смотрите также
- Метрики — полный справочник метрик Prometheus
- Проверки работоспособности — подробное поведение проверок работоспособности
- Справочник конфигурации — все переменные окружения
- Корректное завершение работы — последовательность завершения работы и жизненный цикл внутреннего сервера