Как обрабатывать ежечасное закрытие соединения с Bigtable?

# #go #grpc #google-cloud-bigtable

#Вперед #grpc #google-облако-bigtable

Вопрос:

У меня есть сервисы golang с постоянным клиентом Bigtable. Службы выполняют сотни операций чтения / записи на Bigtable в секунду.

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

 Retryable error: rpc error: code = Unavailable desc =
 the connection is draining, retrying in 74.49241ms
  

За ошибкой следует увеличенное время обработки, которое я не могу допустить при возникновении этих ошибок.

Мне удалось выяснить, что клиент Bigtable использует пул соединений gRPC.

Похоже, что у сервера Bigtable gRPC максимальное время подключения составляет 1 час, что может объяснить указанную выше ошибку и увеличение времени обработки при повторном подключении.

Предполагается, что конфигурация maxAgeGrace дает дополнительное время для завершения текущих операций и позволяет избежать одновременного завершения всех подключений к пулу.

Я увеличил размер пула соединений с 4 до 12 по умолчанию без какой-либо реальной выгоды

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

Ответ №1:

Облачные клиенты bigtable используют пул соединений gRPC для подключения к bigtable. Java-клиент использует пул каналов для каждого соединения HBase, каждый пул каналов имеет несколько соединений gRPC. Соединения gRPC отключаются каждый час (или после 15 минут бездействия), и базовая инфраструктура gRPC выполняет повторное подключение. Первый запрос при каждом новом соединении выполняет ряд задач настройки, таких как подтверждение связи TLS и прогревание кэшей на стороне сервера. Эти операции довольно дороги и могут вызвать всплески задержки.

Bigtable спроектирована как система с высокой пропускной способностью, и амортизированная стоимость этих повторных подключений при постоянном объеме запросов должна быть незначительной. Однако, если клиентское приложение имеет очень низкий QPS или длительные периоды простоя между запросами и не может переносить эти всплески задержки, оно может создавать новое соединение Hbase (java) или новый клиент CBT (golang) каждые 30-40 минут и не запускать вызовы op (существующие на клиенте hbase или считывающие небольшую строку) на новом соединении / клиенте для запуска базовых соединений gRPC (один вызов на соединение, поскольку hbase по умолчанию вдвое превышает количество процессоров, go по умолчанию имеет 4 соединения). После загрузки вы можете заменить новое соединение / клиент для основных операций в клиентском приложении. Вот пример кода go для этого обходного пути.

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

1. Связанный вами обходной код использует концепцию «вращающейся таблицы» и отмечает, что «Для новой ссылки на таблицу потребуется, чтобы через нее проходило несколько запросов для установления каждого соединения в пуле соединений». Означает ли это, что при настройке нового клиента Bigtable каждая таблица, открытая в клиентском приложении, должна быть перенасыщена? Или новый клиент Bigtable может просто использовать одну таблицу для загрузки базовых соединений gRPC?

Ответ №2:

Я подозреваю, что это может быть связано с ошибкой, появившейся в недавнем выпуске grpc-go и только что исправленной. По сути, вместо повторного подключения сразу после разрыва соединения мы неправильно ждем 1 секунду перед повторным подключением. Пожалуйста, повторите попытку с помощью grpc-go master head. Спасибо!