#ruby_on_rails #ruby #ssh
Приложение на Rails. После ввода пользователем реквизитов необходимо открыть SSH соединение (использую Net::Ssh), и очень бы не хотелось, чтобы при каждом запросе к приложению SSH соединение открывалось заново. Подскажите, как можно сохранять подключение через Net::Ssh и использовать его при каждом запросе к сайту.
Ответы
Ответ 1
Соединение штука несериализуемая и между процессами передаваемая с трудом даже в пределах одной машины, что уж говорить о множестве машин — ведь воркеры вовсе не обязаны все быть на одной машине. Совсем простое решение: всё равно осуществлять SSH-соединения в процессе веб-сервера. Надо с осторожностью отнестись к тому, как там устроены ввод-вывод и многопоточность, чтобы код обработки HTTP-запросов и SSH-соединений не мешал друг другу. А проблему установления нескольких соединений от разных серсеров можно решить "липкими сессиями" на балансировщике, с помощью которых пользователь будет закреплён за конкретным процессом. Есть реализация в nginx, опция sticky. При этом nginx сам должен знать о каждом воркере, чтобы иметь возможность "прилеплять" пользователей, это не со всякой конфигурацией вебсервера совместимо: в конфиге nginx воркеры должны быть перечислены явно. Но это довольно грустное решение в том плане, что взаимодействие по HTTP практически не требует поддержки какого-либо состояния, что удобно, т. к. даёт возможность держать много идентичных процессов и обслуживать любые запросы любым из них, не боясь аномалий. К тому же, в зависимости от того, насколько у вас разнятся нагрузки от отдельных пользователей, nginx может распределить нагрузку между воркерами не вполне равномерно. И обратите внимание на то, что у вас будет происходить, если от пользователя придут два запроса на SSH-соединение практически одновременно, когда у вас оно ещё не установлено. Примите меры, чтобы не установить два соединения. Менее грустным решением была бы отдельная служба, которая держит SSH-соединения и общается с вебсервером по какому-нибудь внутреннему протоколу. Хотя как только начнутся проблемы с удержанием большого количества SSH-соединений на одном сервере (это вопрос уже к вам, какого роста нагрузок вы ждёте), вам придётся делать похожую систему: с помощью подобия "липких сессий" (важно: принадлежащих пользователям, а не воркерам вебсерверов) распределять соединения по нескольким процессам/хостам с этой выделенной службой. Только вместо того, чтобы возиться с куками, отвечающий за соединение сервер можно зашить прямо в идентификатор соединения, используемый в общении между серверами. Сложно, да? Что поделать. Вы пытаетесь связать очень разнородные вещи.Ответ 2
Я бы попробовал так: Создать инициализатор, в нем создать глобальную переменную, например Hash, в которой и хранить ваши соединения. Ну или создать класс синглтон, тут уж от вкусов зависит. Но нужно не забыть решить вопрос о закрытии соединения!
Комментариев нет:
Отправить комментарий