Вопрос или проблема
У меня есть следующий виртуальный хост на apache2, действующий как обратный прокси для сервера websockify в настройке novnc.
<VirtualHost *:80>
ServerName stream.kiosk-vm
<Location "/">
Redirect permanent "https://%{HTTP_HOST}%{REQUEST_URI}"
</Location>
</VirtualHost>
<VirtualHost *:443>
ServerName stream.kiosk-vm
SSLEngine On
SSLCertificateFile /etc/ssl/certs/localhost.crt
SSLCertificateKeyFile /etc/ssl/private/localhost.key
ProxyRequests Off
#Синтаксическая ошибка, но это в документации??
# ProxyWebsocketIdleTimeout 86400000
#Это, похоже, исправляет, но слишком общее
Timeout 86400000
#Это ничего не делает.
# ProxyTimeout 86400000
#Это тоже не...
# ProxyPass /websockify ws://localhost:5801/websockify connectiontimeout=86400000 timeout=86400000 keepalive=On
ProxyPass /websockify ws://localhost:5801/websockify
ProxyPassReverse /websockify ws://localhost:5801/websockify
ProxyPass / http://localhost:5801/
ProxyPassReverse / http://localhost:5801/
<Proxy *>
AuthType Basic
AuthName "Restricted Access"
AuthBasicProvider file
AuthUserFile /etc/apache2/htpasswd/stream_users
Require valid-user
AllowOverride None
</Proxy>
ErrorLog /var/log/apache2/stream_error.log
CustomLog /var/log/apache2/stream_access.log combined
</VirtualHost>
Include /etc/apache2/conf.d/*.conf
Все работает хорошо, но я заметил, что когда экран был статичным и клиент бездействовал, соединение websocket закрывалось apache ровно через 1 минуту. Пытаясь это исправить, я попробовал несколько параметров в разных местах:
- ProxyWebsocketIdleTimeout: Казался идеальным параметром для этого случая, но в моем случае возвращает синтаксическую ошибку…
- Timeout: Выполняет задачу, но кажется слишком общим и применяется ко всем запросам
- ProxyTimeout: В моем случае ничего не делал. Отключение через 1 минуту простаивания.
- connectiontimeout=86400000 timeout=86400000 keepalive=On в ProxyPass: также казался многообещающим, так как предназначен только для запросов websocket, но для меня ничего не сделал.
Если Timeout был не установлен, ничего другого не работало. Если Timeout установлен на большое число, все остальные параметры ничего не меняют.
Итак… Что мне делать в этом случае? Можно просто использовать большой общий параметр Timeout? Почему специфичные не работают?
Я нашел множество похожих вопросов здесь и на stackoverflow, но многие из них остаются без ответа или рекомендуют использование ProxyWebsocketIdleTimeout или других параметров, которые не работали для меня…
Оставляю здесь дополнительную информацию о моей настройке, надеюсь, это поможет:
kiosk-vm:~ # apachectl -M
AH00558: httpd-prefork: Невозможно надежно определить полностью квалифицированное доменное имя сервера, используется ::1. Установите директиву 'ServerName' глобально, чтобы подавить это сообщение
Загруженные модули:
core_module (статический)
so_module (статический)
http_module (статический)
mpm_prefork_module (статический)
unixd_module (статический)
systemd_module (статический)
actions_module (shared)
alias_module (shared)
auth_basic_module (shared)
authn_core_module (shared)
authn_file_module (shared)
authz_host_module (shared)
authz_groupfile_module (shared)
authz_core_module (shared)
authz_user_module (shared)
autoindex_module (shared)
cgi_module (shared)
dir_module (shared)
env_module (shared)
expires_module (shared)
include_module (shared)
log_config_module (shared)
mime_module (shared)
negotiation_module (shared)
setenvif_module (shared)
ssl_module (shared)
socache_shmcb_module (shared)
userdir_module (shared)
reqtimeout_module (shared)
headers_module (shared)
deflate_module (shared)
filter_module (shared)
http2_module (shared)
proxy_module (shared)
proxy_http_module (shared)
proxy_wstunnel_module (shared)
kiosk-vm:~ # apachectl -V
Версия сервера: Apache/2.4.51 (Linux/SUSE)
Сборка сервера: 2024-11-13 05:45:31.000000000 +0000
Магическое число модуля сервера: 20120211:118
Загружен сервер: APR 1.6.3, APR-UTIL 1.6.1
Собран с использованием: APR 1.6.3, APR-UTIL 1.6.1
Архитектура: 64-разрядная
MPM сервера: prefork
потоков: нет
форков: да (переменное количество процессов)
Сервер собран с использованием....
-D APR_HAS_SENDFILE
-D APR_HAS_MMAP
-D APR_HAVE_IPV6 (IPv4-маршрутизированные адреса включены)
-D APR_USE_PROC_PTHREAD_SERIALIZE
-D APR_USE_PTHREAD_SERIALIZE
-D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
-D APR_HAS_OTHER_CHILD
-D AP_HAVE_RELIABLE_PIPED_LOGS
-D DYNAMIC_MODULE_LIMIT=256
-D HTTPD_ROOT="/srv/www"
-D SUEXEC_BIN="/usr/sbin/suexec"
-D DEFAULT_PIDLOG="/run/httpd.pid"
-D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
-D DEFAULT_ERRORLOG="/var/log/apache2/error_log"
-D AP_TYPES_CONFIG_FILE="/etc/apache2/mime.types"
-D SERVER_CONFIG_FILE="/etc/apache2/httpd.conf"
kiosk-vm:~ # apachectl -S
AH00558: httpd-prefork: Невозможно надежно определить полностью квалифицированное доменное имя сервера, используется ::1. Установите директиву 'ServerName' глобально, чтобы подавить это сообщение
Конфигурация VirtualHost:
*:80 является NameVirtualHost
сервер по умолчанию data.kiosk-vm (/etc/apache2/vhosts.d/data.conf:2)
порт 80 имя хоста data.kiosk-vm (/etc/apache2/vhosts.d/data.conf:2)
порт 80 имя хоста kiosk-vm (/etc/apache2/vhosts.d/root.conf:2)
порт 80 имя хоста stream.kiosk-vm (/etc/apache2/vhosts.d/stream.conf:1)
*:443 является NameVirtualHost
сервер по умолчанию data.kiosk-vm (/etc/apache2/vhosts.d/data.conf:10)
порт 443 имя хоста data.kiosk-vm (/etc/apache2/vhosts.d/data.conf:10)
порт 443 имя хоста kiosk-vm (/etc/apache2/vhosts.d/root.conf:10)
порт 443 имя хоста stream.kiosk-vm (/etc/apache2/vhosts.d/stream.conf:8)
ServerRoot: "/srv/www"
Main DocumentRoot: "/srv/www/htdocs"
Main ErrorLog: "/var/log/apache2/error_log"
Mutex ssl-stapling: с использованием по умолчанию
Mutex proxy: с использованием по умолчанию
Mutex ssl-cache: с использованием по умолчанию
Mutex default: dir="/run/" механизм по умолчанию
Mutex mpm-accept: с использованием по умолчанию
Mutex ssl-stapling-refresh: с использованием по умолчанию
PidFile: "/run/httpd.pid"
Define: SYSCONFIG
Define: SSL
Define: HTTP2
Define: SYSTEMD
Define: DUMP_VHOSTS
Define: DUMP_RUN_CFG
User: name="wwwrun" id=470
Group: name="www" id=474
Ответ или решение
Ваша проблема с разрывом соединения WebSocket после 60 секунд бездействия, вероятно, связана с настройками конфигурации Apache2. Давайте разберемся с основными аспектами и возможными решениями этой задачи, учитывая специфику вашего сценария.
Общая проблема
Подключения WebSocket отличаются от стандартных HTTP-соединений, поскольку они требуют постоянного открытого канала между клиентом и сервером. Apache в роли реверс-прокси может закрывать эти соединения, основываясь на таймаутах, если они не настроены должным образом. Обратите внимание на следующие моменты:
-
ProxyWebsocketIdleTimeout: данная опция предназначена для управления таймаутом WebSocket в специфических реализациях Apache. Часто возникновение синтаксической ошибки означает, что или данная директива не поддерживается вашей сборкой Apache, или она требует определенной версии модуля.
-
Timeout: данная опция является общесистемной и применяется ко всем типам соединений. Установка её на высокое значение решает проблему, но это может негативно сказаться на производительности других компонентов вашего веб-приложения.
-
ProxyTimeout и другие параметры в ProxyPass могут не оказывать ожидаемого эффекта из-за особенностей обработки WebSocket-соединений или неправильной конфигурации модулей.
Рекомендации
-
Убедитесь, что все необходимые модули загружены. Поскольку
proxy_wstunnel_module
загружен, убедитесь также, что версия Apache поддерживает нужные параметры. Возможно, вам стоит обновить ваш модуль или сервер до актуальной версии. -
Проверьте конфигурацию WebSocket и расширений: посмотрите документацию для вашей версии Apache, чтобы понять, какие параметры из последних доступны и поддерживаются.
-
Используйте Keep-Alive: попробуйте настроить keep-alive не только на соединениях HTTP, но и на самом сервере WebSocket. Это может удерживать соединение в активном состоянии.
-
Тестируйте на актуальной сборке Apache: обновите сервер или попробуйте поднять другое тестовое окружение с последней версией Apache, так как многие параметры становятся доступными и более стабильными в последних выпусках.
SEO-оптимизация и контекст
Этот ответ предназначен для удовлетворения запроса пользователя, который сталкивается с техническими проблемами при конфигурации Apache в роли реверс-прокси для WebSocket-соединений на платформе novnc. Чёткое понимание и настройка конфигураций поможет вам избежать разрывов из-за неправильного таймаута. Это особенно важно для обеспечения устойчивости и производительности приложений, работающих через веб-сокеты.
Постарайтесь следовать рекомендациям и избегать использование чрезмерно общих настроек таймаутов, которые могут затруднить работу сервера и снизить его производительность.