Гарантированно ли вызов onComplete/onCancel с помощью grpc?

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

Я использую ServerCall.Listener:

  • код для выполнения в начале вызова находится в конструкторе слушателя
  • код для выполнения в конце вызова запускается onComplete и onCancel
  • поток, создающий слушателя, должен быть тем, который вызовет onComplete / onCancel (мы используем локальные переменные потока)

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

Но есть проблема: иногда кажется, что даже если прослушиватель был создан, за ним не следует вызов onComplete или onCancel.

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

Должна ли произойти одна из этих ситуаций? Я использую grpc-netty версии 1.6.1.

Спасибо за помощь!


person yohan    schedule 20.02.2018    source источник


Ответы (1)


Гарантируется, что будет вызван ровно один из onComplete/onCancel.

Проблема в том, что "поток, создающий экземпляр слушателя, должен быть тем, который вызовет onComplete/onCancel". Как правило, это неверно по нескольким причинам:

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

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

Единственный раз, когда ваше предположение будет верным сегодня, - это использование блокирующей заглушки. Но это из-за детали реализации, на которую не следует полагаться.

person Eric Anderson    schedule 20.02.2018
comment
Большое спасибо, Эрик, это очень помогает! - person yohan; 21.02.2018
comment
@Eric Я не смог найти в репозитории никакой документации, касающейся модели многопоточности сервера java gRPC. Есть ли ресурс, который можно было бы прочитать об этом? - person Brice; 21.02.2018
comment
И StreamObserver, и ClientCall/ServerCall не являются потокобезопасными (за исключением методов, явно упоминающих об этом). Это в Javadoc. Прослушиватели независимо не являются потокобезопасными от вызовов (входящие и исходящие независимо не являются потокобезопасными, поэтому их можно вызывать одновременно). StreamObserver делает все возможное, чтобы указать это в документации. - person Eric Anderson; 22.02.2018