
У меня есть приложение, которое прослушивает соединения на порту, но я иногда отключаю его для обновлений и т. п. Мне бы хотелось настроить систему так, чтобы если эта программа запущена, запросы на этот порт отправлялись приложению, но если она не запущена, запросы направлялись в какое-то другое приложение (которое может возвращать сообщение «временно недоступно»). Как проще всего это сделать?
У меня нет прав root на целевой машине, поэтому я бы предпочел избегать таких вещей, как iptables
. Я рассматривал вспомогательное приложение, которое не делает ничего, кроме маршрутизации соединений к двум другим приложениям, но я надеюсь, что есть более простой способ
решение1
Ваш вопрос подразумевает, что обе программы будут работать попеременно на одной и той же машине, привязанной к одному и тому же порту. Это плохая идея. Вы столкнетесь с проблемой TIME_WAIT
(она же 2MSL), если попробуете это.Эта статьяописывает проблему. (Она ориентирована на Windows, но большая часть того, о чем там говорится, применима к любому стеку TCP/IP.)
API сокетов BSD предоставляет способ обойти эту защиту ( setsockopt(SO_REUSEADDR)
), но это не тот случай, когда это оправдано.
Вместо этого решите проблему так же, как это делают специалисты по высокой доступности: поставьтеобратный проксимежду миром и вашим «реальным» внутренним сервером.
В мире HTTP одним из популярных решений этой проблемы являетсяnginx. Вы можете настроить его так, чтобы, пока сервер back-end не работает, он обслуживал статический контент клиентов. Если ваш протокол выглядит как HTTP, IMAP или POP, возможно, вы можете использовать nginx как есть. Если нет, вы можете создать собственный прокси-сервер.
Вероятно, вам понадобится два порта TCP, чтобы это работало. Прокси-сервер привязывается к номеру порта, обращенного к публичному IP-адресу. Ваш внутренний сервер привязывается к вторичному порту, только на интерфейсе localhost. Таким образом, трафик может попасть из публичной сети на внутренний сервер только через прокси-сервер.
Вы можете обойтись привязкой обоих к одному и тому же порту, если обе программы написаны так, чтобы это разрешать. Например, если ваш публичный IP-адрес — , 1.2.3.4
а ваш публичный порт службы — 2345
, обе программы могут привязываться к порту, 2345
если обратный прокси-сервер привязывается только к IP-адресу 1.2.3.4
, а «реальный» сервер — только к 127.0.0.1
. Если любой из них привязывается к INADDR_ANY
(0.0.0.0), вам нужны разные порты.
Это решает проблему 2MSL, поскольку ваши клиенты всегда общаются с одной и той же программой, прокси-сервером. Сетевой стек никогда не будет путаться в том, что делать с любыми случайными пакетами, подхваченными за время 2MSL.
Разновидностью обратного прокси являетсябалансировщик нагрузки, и это также может сработать здесь. Балансировщик нагрузки предназначен для интеллектуальной маршрутизации трафика на разные машины. Этот тип прокси имел бы смысл, если бы вы думали, что вашему приложению когда-нибудь понадобится горизонтальное масштабирование. Вы бы выбрали балансировщик нагрузки, который знает, как отправлять трафик на специальный хост «service down», когда все обычные серверы приложений не работают.
Основная проблема варианта решения балансировщика нагрузки заключается в том, что универсальный балансировщик нагрузки может слепо предполагать, что все внутренние службы, которые он проксирует, используют один и тот же номер порта, отличаясь только IP. Однако вы можете получить более гибкий балансировщик нагрузки или получить несколько IP для вашего общего сервера.