Как передать прослушивающий сокет TCP с минимальным временем простоя?

StackOverflow https://stackoverflow.com/questions/2206951

Вопрос

Пока этот вопрос помечен как EventMachine, универсальные решения для BSD-сокетов на любом языке также высоко ценятся.


Некоторая предыстория:

У меня есть приложение, прослушивающее TCP-сокет.Он запускается и завершается с помощью обычного скрипта инициализации в стиле System V.

Моя проблема в том, что ему требуется некоторое время для запуска, прежде чем он будет готов обслуживать TCP-сокет.Это не слишком долго, возможно, всего 5 секунд, но это на 5 секунд больше, чем нужно, когда перезапуск необходимо выполнить в течение рабочего дня.Также крайне важно, чтобы существующие соединения оставались открытыми и завершались в обычном режиме.

Причинами перезапуска приложения являются исправления, обновления и тому подобное.К сожалению, я оказываюсь в таком положении, что время от времени мне приходится заниматься подобными вещами на производстве.


Этот вопрос:

Я ищу способ аккуратно передать прослушивающий сокет TCP от одного процесса другому и в результате получить лишь долю секунды простоя.Я бы хотел, чтобы существующие соединения / сокеты оставались открытыми и завершали обработку в старом процессе, в то время как новый процесс начинает обслуживать новые connectinos.

Есть ли какой-нибудь проверенный способ сделать это с использованием BSD-sockets?(Бонусные баллы за решение EventMachine.)

Возможно, существуют библиотеки с открытым исходным кодом, реализующие это, которые я могу использовать как есть или использовать в качестве ссылки? (Опять же, решения, отличные от Ruby и не связанные с EventMachine, также приветствуются!)

Это было полезно?

Решение

Есть несколько способов сделать это без простоев, с соответствующими изменениями в серверной программе.

Один из них заключается в реализации возможности перезапуска на самом сервере, например, при получении определенного сигнала или другого сообщения.Затем программа выполнит свою новую версию, передав ей номер файлового дескриптора прослушивающего сокета, напримерв качестве аргумента.Этот сокет будет иметь FD_CLOEXEC установите флажок очистить (по умолчанию), чтобы он был унаследован.Поскольку другие сокеты будут по-прежнему обслуживаться исходным процессом и не должны передаваться новому процессу, флаг следует установить для них, напримериспользуя fcntl().После разветвления и выполнения нового процесса исходный процесс может продолжить работу и закрыть прослушивающий сокет без какого-либо прерывания работы службы, поскольку новый процесс теперь прослушивает этот сокет.

Альтернативным методом, если вы не хотите, чтобы старому серверу приходилось самому разветвлять и запускать новый сервер, было бы использование Unix-доменный сокет для связи между старым и новым серверным процессом.Новый серверный процесс может проверять наличие такого сокета в хорошо известном расположении файловой системы при запуске.Если присутствует, новый сервер подключится к этому сокету и запросит, чтобы старый сервер передал свой прослушивающий сокет в качестве вспомогательных данных, используя SCM_RIGHTS.Пример этого приведен в конце cmsg(3).

Другие советы

Жан-Поль Кальдероне написал подробная презентация в 2004 году о комплексном решении вашей проблемы с использованием Twisted, включая миграцию сокетов и другие проблемы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top