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

#kubernetes #kubernetes-pod

Вопрос:

У меня есть (внутреннее) развертывание K8s (Python, TensorFlow, Guinicorn) с примерно 60 репликами и подключенной службой K8s для распространения входящих HTTP-запросов. Каждый из этих 60 модулей может фактически обрабатывать только один HTTP-запрос за раз (по причинам TensorFlow). Обработка запроса занимает от 1 до 4 секунд. Если второй запрос отправляется в модуль, пока он все еще обрабатывает его, второй запрос просто ставится в очередь в списке невыполненных работ Gunicorn.

Теперь я хотел бы максимально снизить вероятность возникновения этой очереди, т. Е. Направлять новые запросы в один из незанятых модулей, пока такой незанятый существует.

Циклическое выполнение не помогло бы, потому что не на каждый запрос требуется одинаковое количество времени для ответа (см. Выше).

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

Итак, как я мог бы достичь этой цели?

Ответ №1:

Не можете ли вы реализовать посредника между пабом/суб или сообщением?

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

Вы можете использовать Redis для создания очередей и в очереди, вы можете использовать pub/sub, также возможно использование библиотеки. я использовал один из них раньше в Node JS, однако можно было бы реализовать то же самое и с помощью python.

в 60 репликах в идеале будет работать рабочий или, можно сказать, писец.

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

Мы также сделали еще один шаг вперед, автоматически увеличив количество работников в зависимости от количества сообщений в очереди.

Эту библиотеку я использую с узлом js : https://github.com/OptimalBits/bull

Комментарии:

1. Спасибо. Да, я также рассматривал возможность перехода на подход «очередь и рабочие». Но концептуально эта служба Python делает то же самое, что и некоторые другие (все они являются параллельными запросами для получения определенных функций для сущности). Поэтому я хотел избежать введения отдельного способа потока данных для этого конкретного экземпляра только потому, что он немного медленнее, чем другие.

Ответ №2:

...kubectl get service shows "TYPE ClusterIP" and "EXTERNAL-IP <none>

В этом случае ваша служба k8s будет маршрутизировать запросы случайным образом… очевидно, что это не очень хорошо для вашего приложения. Если вы хотите использовать kube-прокси, вы можете переключиться в режим ipvs с помощью sed. Вот хорошая статья об этом. В противном случае вы можете рассмотреть возможность использования какого-либо контроллера входа, подобного упомянутому ранее; ingress-nginx с режимом «ewma».

Комментарии:

1. Ах, извините. Возможно, я выбрал не тот тег. Я просто убрал его. kubectl get service показывает «ClusterIP ТИПА» и «ВНЕШНИЙ-IP <нет>».

2. нет проблем, обновил ответ.