#клиент_сервер #обновления
Я разрабатываю клиент и сервер на C++. Мне нужно реализовать возможность обновления сервера без вреда пользователям. Проблема в том, что я не должен отключать пользователей с выходом новой версии сервера, из-за его перезапуска. Пока я додумался только до такого решения, чтобы запускать новую версию сервера с новым портом, а старые не закрывать, пока ими кто-то пользуется. Пользователь сначала соединяется с маленьким сервером, который отправляет ему порт основного сервера. (Или для его версии клиента, или просит обновиться, а потом присылает порт последней версии). Добавлю что взаимодействия между пользвателями нет. Пользователь обращается к серверу за специальными расчётами.
Ответы
Ответ 1
Странное изобретение велосипеда на ровном месте. Как будто, у вас соединение по сети - вечное. В век мобильных устройств и прочего, гораздо проще заложится на корректную переустановку соединенея, чем изобретать какой-то ужас. Чем отличается ситуации - "соединение с клиентом пропало", "сервер упал и его подняли (думаете, этого не будет?)", "сервер перезапустили"? С точки зрения клиентов - ничем. Так что и механизм должен быть один - корректное переподключение.Ответ 2
Дополнение к варианту 2 ответа от @Mike Клиенты общаются с сервером не напрямую, а через некий простой фронтэнд сервер, который работает фактически в режиме прокси В *nix (вероятно и в Mac тоже) возможна реализация эффективного proxy, который передает другому процессу на том же хосте полученное соединение (открытый дескриптор) по UNIX DOMAIN или datagram сокету, а не транслирует в обе стороны все данные. Для этого (File Descriptor Passing) используется системный вызов sendmsg. Подробности можно посмотреть здесь или по запросу в гугле unix socket magic sendmsg. Как это можно использовать в Вашем случае imho достаточно очевидно.Ответ 3
Думаю можно попробовать примерно такой алгоритм. У сервера есть несколько основных портов, на которых он может работать. При запуске он пытается занять первый в списке порт, если ему это не удалось, т.к. порт занят другим сервером, он занимает следующий свободный порт. При этом он знает, что запущена старая копия. Он открывает соединение со старой копией, как это обычно делает клиент, и сообщает что он новый сервер. Старый сервер убеждается, что запрос пришел именно от его новой копии (какой нибудь криптографией или просто увидев, что он с 127.0.0.1). После чего он рассылает всем текущим клиентам команду соединятся с новой копией на новом порту. Когда все клиенты перейдут (отключатся от него) или по определенному таймауту он завершается. Новая копия, после завершения старой, может занять опять свой обычный порт и попросить клиентов занять опять обычный порт. Или не просить, они сами со временем перейдут. Вариант 2: Клиенты общаются с сервером не напрямую, а через некий простой фронтэнд сервер, который работает фактически в режиме прокси. Это фронтэнд через unix сокеты или сетевые сокеты передает запросы на основной бакэнд сервер и возвращает его ответы клиентам. Он же может служить балансером нагрузки и распределять запросы на разные бакэнд сервера. Соответственно обрыв коннектов у клиентов может быть только при перезапуске фронтэнда, но т.к. никакой бизнес-логики на нем не будет, то после первичной отладки выпускать его новые версии скорее всего не понадобится. Вариант 3: Все как вы и сказали в вопросе, только "маленький сервер" для сообщения текущего номера порта основного сервера изобретать не нужно. Он уже давно изобретен, называется DNS. В свою доменную зону добавляете SRV запись примерно следующего содержания: _myserv._tcp 10 IN SRV 0 5 1234 myserver.example.com. ; ^ ^ ; | Порт на котором сейчас служба - TTL записи. 10 секунд, т.е. DNS сервера не будут ее держать в кеше более 10 секунд Вам конечно надо будет научить свое клиентское приложение использовать эти записи, помимо A записей, указывающих IP. Запись можно обновлять автоматически при запуске нового сервера через механизм ddns.Ответ 4
Нужно решать вопрос не о сохранении "живым" соединения с пользователем, а о восстановлении в памяти пользовательской сессии при перезапуске процесса сервера. Вы можете держать эти данные в памяти, общей для двух процессов. Но второй процесс - это совершенно тупоголовый бинарник, который только держит дескриптор. Перезапущенный сервер должен находить этот бинарник и "возвращать себе" память.
Комментариев нет:
Отправить комментарий