Мы используем GRPC для общения с одним из наших микросервисов.Большую часть времени StatusRuntimeException
, выбрасываемое микросервисом, правильно передается обратно и перехватывается клиентом в блоке try/catch
.
Однако в очень небольшом проценте этих запросов GRPC (при высокой нагрузке) кажется, что блок catch
не учитывается, и вместо этого возникает исключение.Как ни странно, когда всплывает исключение, сообщаемое в трассировке стека (io.grpc.StatusRuntimeException
), это того же типа , что указан в блоке перехвата (io.grpc.StatusRuntimeException
).То есть он по какой-то причине не перехватывается блоком catch
?
Это исключение в трассировке стека ( обратите внимание на ссылку на строку 191 ):
[2018-12-03 18:16:48,653] WARN[{2018-12-03 18:16:48} SF: /edam/intern] com.xxx.PersistentStore.invoke(PersistentStore.java:485)
- Unexpected invocation exception in persistent store method getBusinessUserProfilesWithPhotoFlag
>>> io.grpc.StatusRuntimeException: <<< NOT_FOUND: user profile photo metadata not found
at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:227)
at io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:208)
at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:141)
at com.xxx.UPPServiceGrpc$UppServiceBlockingStub.getMetadata(UppServiceGrpc.java:312)
at com.xxx.UppMicroserviceClient.getMetadata(UppMicroserviceClient.java:68)
at >>> com.xxx.UppMicroserviceImpl.getMetadata(UppMicroserviceImpl.java:191) <<
at com.xxx.UppMicroserviceImpl.lambda$getUserIdsWithPhotos$5(UppMicroserviceImpl.java:356)
И это наш блок try / catch ( обратите внимание, что строка 191 находится в блоке try, и она перехватывает исключение того же типа, о котором сообщалось в трассировке стека ):
import io.grpc.StatusRuntimeException;
public Optional<UserProfilePhotoMetadata> getMetadata(int userId) {
...
try {
191: GetMetadataResponse response = uppClient.getMetadata(request);
...
return toUserProfilePhotoMetadata(response.getPhotoMetadata());
195: } catch (StatusRuntimeException e) {
String errorCode = e.getStatus().getCode().name();
if (ENConfig.isUserProfilePhotoMetricsEnabled()) {
addFailureMetrics("getMetadata", errorCode);
}
return Optional.empty();
...
Опять же, этот код прекрасно работает в подавляющем большинстве вызовов, однако небольшое количество запросов, по-видимому, генерирует маршализованный GRPC StatusRuntimeException
объект, который имеет тот же спецификатор пакета как тип, указанный в блоке catch
, но, очевидно, не идентичен на двоичном уровне.
Теперь мы используем несколько разные версии GRPC для клиента / микросервиса, номы проверили SerialVersionIDs
класса StatusRuntimeException
на обоих, и они имеют одинаковое значение.Мы даже пытались сопоставить версии GRPC, но проблема не исчезла.
Кто-нибудь еще видел это или имеет какое-либо представление о причине?Некоторые проблемы с загрузчиком классов были предложены, но не проверены.