Обработка ошибок Context Cancelled

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

Если я не ошибаюсь, в «простых» терминах отмена контекста означает, что данный запрос (через grpc с использованием gokit) истек. Правильный? Если да, то каким должен быть лучший способ решить эту проблему?

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

  2. Это что-то Go внутреннее, что может намекать на что-то, связанное с Go?

  3. Каков наилучший подход для начала обработки этой ошибки? Прямо сейчас все, что я вижу, «Контекст отменен» и понятия не имею, почему так.


person Em Ae    schedule 15.06.2020    source источник
comment
контекст отменен означает, что данный запрос истек, верно? Неа. Тайм-ауты создают context.DeadlineExceeded. Canceled означает, что была вызвана одна из функций CancelFunc, ни больше, ни меньше.   -  person Peter    schedule 15.06.2020


Ответы (1)


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

Входящие запросы к серверу должны создавать контекст, а исходящие вызовы к серверам должны принимать контекст.

Ошибка отмены контекста не обязательно означает ошибку тайм-аута.

Сценарий 1:

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

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

Сценарий 2:

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

Контекст можно закрыть, вызвав функцию cancel(), как показано ниже:

ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()

Отмена этого контекста освобождает связанные с ним ресурсы. Таким образом, если вызываемый объект явно закрыл контекст, как показано выше, это может привести к ошибке отмены контекста в вызывающем объекте.

Эти ошибки отмены контекста можно обработать, проверив ошибку context.Canceled из вызова grpc.Dial() (если вы используете grpc).

person Ashwin Shirva    schedule 15.06.2020