Перегрузка соединений с аэродинамическими узлами - проблемы глобального соединения

63
4

Я пытаюсь использовать Aerospike DB на разветвленном сервере. Мой кластер состоит из 6 узлов. Я использую клиент python, но это не должно быть важно.

Сначала я создал клиента, связал его и чем я разветкил сервер. Это решение имеет проблемы, когда состояние кластера изменяется (узел умирает), соединение возвращает True для is_connected() но операции чтения и записи не могут выполняться успешно. В этом решении у меня было около 700 соединений для каждого узла, что было хорошо для кластера.

Моя вторая попытка заключалась в том, чтобы создать клиент, а не вилку сервера и подключиться к каждой вилке. Это решение правильно обрабатывает изменения кластера, но для каждого узла у меня есть около 7 тыс. Соединений, что приводит к неустойчивости узлов.

Любые идеи, как решить это лучше?

спросил(а) 2021-01-19T16:43:10+03:00 6 месяцев, 1 неделя назад
1
Решение
78

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

Я бы предположил, что вы CLOSE_WAIT с проблемой с CLOSE_WAIT. В случае долгосрочных приложений, написанных на Java, С#, C и т.д., Те, которые подключаются к кластеру, и продолжают работать и отправлять на него операции. Для большинства динамических языков в контексте сервера они предназначены для принятия ограниченного количества запросов, а затем прекращаются, а некоторые диспетчеры процессов постоянно открывают новые процессы. Это обычное явление для приложений Python за WSGI, PHP внутри Apache (mod_php) или за FastCGI (PHP-FPM), приложений Ruby за пассажиром и т.д. Каждый раз, когда процесс завершается, сокеты, которые он использовал, становятся недоступными в течение определенного периода времени (обычно в течение 4 минут). Поскольку процессы настроены на выполнение небольшого количества запросов, вы увидите, что соединения застряли в CLOSE_WAIT.

Решение состоит в том, чтобы каждый процесс принимал как можно больше запросов. Я бы отслеживал ваши процессы приложений, чтобы убедиться, что их размер остается стабильным, и до тех пор, пока утечка памяти не раздувается, найдите правильный номер максимального количества запросов. Подобный случай в PHP связан с устаревшими рекомендациями конфигурации сервера, которые предлагают несколько сотен запросов в процессе. С PHP, который намного более стабилен с точки зрения использования памяти, это недопустимое предположение и ухудшает производительность, а также имеет побочный эффект, который вы описали. Поскольку как клиенты Python, так и PHP могут обрабатывать тысячи запросов (~ 4.5Ktps за один процесс в последнем тесте) запросов в секунду, максимальный предел запроса 500 означает, что процесс убивается за долю секунды на пике.

ответил(а) 2021-01-19T16:43:10+03:00 6 месяцев, 1 неделя назад
46

Мы изучили этот вопрос более тщательно, и мы выяснили, что для каждого процесса нет необходимости иметь собственное клиентское соединение.

При использовании forking важно использовать общую память (shm). Рабочий пример показан ниже: https://gist.github.com/tivvit/c3652fdb6208752188fc

Shm имеет важное значение, поскольку в этом режиме родительский процесс (тот, который создает соединение) порождает поток обслуживания, который сохраняет состояние кластера в действии соединения.


Если shm omited, никто не сохраняет состояние кластера. Когда состояние кластера изменяется (процессы в узлах), процессы используют соединение со старой установкой кластера, что приводит к появлению ТАЙМЕРА ПОДКЛЮЧЕНИЯ и другим проблемам.

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

Может быть, это следует упомянуть в документации?

ответил(а) 2021-01-19T16:43:10+03:00 6 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема