2016-09-22 2 views
9

Я использую gRPC с Python как клиент/сервер внутри pubs kubernetes ... Я хотел бы иметь возможность запускать несколько модулей одного типа (серверы gRPC) и позволить клиенту подключаться к их (случайным образом).балансировка нагрузки на стороне клиента gRPC

Я отправил 10 контейнеров сервера и установил «сервис» для их таргетинга. Затем, в клиенте, я подключился к DNS-имени службы - это означает, что кубернеты должны выполнять балансировку нагрузки и направлять меня на случайный серверный модуль. На самом деле клиент вызывает функции gRPC (который работает хорошо), но когда я смотрю на журналы, я вижу, что все вызовы идут на один и тот же серверный модуль.

Предполагаю, что клиент выполняет какое-то кэширование DNS, которое приводит ко всем вызовам, отправляемым на тот же сервер. Это так? В любом случае отключить его и установить один и тот же клиент-заглушка, чтобы сделать «новый» вызов и получить новый ip по DNS с каждым вызовом?

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

EDIT

, вероятно, не проблема кэширования ... Может быть просто способ КПГР работает. HTTP/2 и постоянное многоразовое соединение. Любой способ «отключиться» после каждого вызова?

ответ

10

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

Путь сторона клиента LB работает в ядре КПГР C (основе для всех, кроме Java и Go ароматизаторов или КПГРЫ) выглядит следующим образом (авторитетный документ можно найти here):

стороны клиента LB остается простым и «немым» нарочно. Способ, который мы выбрали для реализации сложных политик LB, - через внешний сервер LB (как описано в вышеупомянутом документе). Вы не имеете отношения к этому сценарию. Вместо этого вы просто создаете канал, в котором будет использоваться LB-политика .

Ввод политики LB представляет собой список разрешенных адресов. При использовании DNS, если foo.com разрешается до [10.0.0.1, 10.0.0.2, 10.0.0.3, 10.0.0.4], политика попытается установить соединение со всеми из них. Первый, который успешно соединится, станет выбранным , пока он не отключится от. Таким образом, имя «pick-first». Более длинное имя могло бы быть «выбрать сначала и придерживаться его как можно дольше», но это сделало для очень длинного имени файла :). Если/когда выбранный будет отключен, политика pick-first перейдет к возврату следующего успешно подключенного адреса (внутренне называемого «подключенным подканалом»), если таковой имеется. Еще раз, он будет продолжать выбирать этот подключенный подканал до тех пор, пока он остается подключенным.Если все они потерпят неудачу, вызов завершится неудачно.

Проблема заключается в том, что разрешение DNS, исходящее из строя, запускается только 1) при создании канала и 2) при отключении выбранного подключенного подканала.

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

Данные изменения, внесенные в Q1 2017 (см. https://github.com/grpc/grpc/issues/7818), позволят клиентам выбрать другую политику LB, а именно Round Robin. Кроме того, мы можем взглянуть на введение «рандомизированного» бита в эту конфигурацию клиента, которая перетасовывает адреса до того, как сделает Round-Robin над ними, эффективно достигая того, что вы намереваетесь.

+0

Благодарим вас за подробный ответ. На самом деле, я уже сделал то, что вы предлагали, и создавал новый канал для каждого запроса (неэффективно, я знаю). Из вашего ответа я понимаю, что только первый ip в dns будет получать запросы до тех пор, пока он не остановится (нет доступных подключений/убит/разбился), и только тогда клиенты получат второй ip и т. Д. ... это правильно? – Idan

+0

Да. Как уже упоминалось, до тех пор, пока изменения не позволят выбрать раунд robin вместо выбора сначала как политика LB. –

+0

Есть ли типичное решение для масштабирования нескольких серверов gRPC? или балансировку нагрузки на стороне клиента? –

1

Если вы создали ванильный сервис Kubernetes, служба должна иметь свой собственный виртуальный IP-адрес с балансировкой нагрузки (проверьте, соответствует ли kubectl get svc your-serviceCLUSTER-IP для вашего обслуживания). Если это так, кэширование DNS не должно быть проблемой, поскольку этот единственный виртуальный IP должен разделять трафик между фактическими бэкэндами.

Попробуйте kubectl get endpoints your-service, чтобы убедиться, что ваш сервис действительно знает обо всех ваших внутренних серверах.

Если у вас есть headless service, поиск DNS будет возвращать запись A с 10 IP-адресами (по одному для каждой из ваших подписок). Если ваш клиент всегда выбирает первый IP-адрес в записи A, это также объясняет поведение, которое вы видите.

+0

Для сервера есть CLUSTER_IP, и я вижу, что у меня есть все конечные точки, когда я получаю «конечные точки». все еще идет на тот же сервер. Я думаю, что это может быть способ работы gRPC и повторное использование соединения с HTTP/2 ... – Idan