Проблема с настройкой gRPC.Получение прерывистой ошибки RPC недоступно - PullRequest
0 голосов
/ 25 октября 2018

У меня есть сервер и клиент grpc, которые работают, как и ожидалось, большую часть времени, но иногда я получаю сообщение об ошибке «Транспорт закрывается»:

rpc error: code = Unavailable desc = transport is closing

Мне интересно, если это проблема с моимнастроить.Клиент довольно простой

connection, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
pb.NewAppClient(connection)
defer connection.Close()

, и вызовы выполняются с тайм-аутом, например

ctx, cancel := context.WithTimeout(ctx, 300*time.Millisecond)
defer cancel()

client.MyGRPCMethod(ctx, params)

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

Никаких особых настроек с сервером не происходит

grpc.NewServer()

Существуют ли какие-либо распространенные ошибки при настройке клиента / сервера grpc, которые я могу совершать?

Ответы [ 3 ]

0 голосов
/ 31 октября 2018

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

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

"транспорт закрывается "имеет много разных причин для этого;пожалуйста, смотрите соответствующий вопрос в нашем FAQ и дайте нам знать, если у вас остались вопросы: https://github.com/grpc/grpc-go#the-rpc-failed-with-error-code--unavailable-desc--transport-is-closing

0 голосов
/ 15 февраля 2019

После долгих поисков я наконец-то пришел к приемлемому и логичному решению этой проблемы.

Основная причина такова: Основное TCP-соединение внезапно закрыто , но ни клиент, ни сервер gRPC не «уведомлены» об этом событии.

Проблема на нескольких уровнях:

  • Управление ядром TCP-сокетов
  • Любые промежуточные балансировщики нагрузки / обратные прокси-серверы (от облачных провайдеров или иным образом) и как они управляют сокетами TCP
  • Сам уровень вашего приложения и его сетевые требования - может ли он повторно использовать то же соединение для будущих запросов, не

Мое решение оказалось довольно простым:

server = grpc.NewServer(
    grpc.KeepaliveParams(keepalive.ServerParameters{
        MaxConnectionIdle: 5 * time.Minute,           // <--- This fixes it!
    }),
)

Это гарантирует, что сервер gRPC изящно сам закроет нижележащий сокет TCP, прежде чем произойдет какое-либо внезапное уничтожение с сервера ядра или промежуточных серверов.(У AWS и Google Cloud Load Balancers оба тайм-аута превышают 5 минут).

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

Мои $ 0,02: Не 't слепо доверять способности любой организации (даже Google) разрабатывать и поддерживать API.Это классический случай ошибочных значений по умолчанию.

0 голосов
/ 25 октября 2018

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

Мое решение, которое работает, состояло в том, чтобы создать мой connection с grpc.Dial один раз для моей функции main, а затем создать pb.NewAppClient(connection) для каждого запроса.Поскольку connection уже был создан, задержка не была проблемой.После того, как запрос был сделан, я закрыл клиент.

...