如何处理(捕获)io.grpc.StatusRuntimeException:UNAVAILABLE:无法解析主机

问题描述 投票:0回答:1

考虑以下非阻塞双向流 gRPC 调用:

this.channel = ManagedChannelBuilder.forAddress("NoSuchServer", 12345))
              .usePlaintext()
              .build();

this.kvStore = KVStoreServiceGrpc.newStub(channel);
this.executor = Executors.newSingleThreadExecutor();

this.executor.submit(() -> {
       // This try-and-catch is my failed attempt at handling StatusRuntimeException
       try {
         this.toServer = kvStore.connect(new StreamObserver<KVMessage>() {

              @Override
              public void onNext(KVMessage resp) {
                      lock.lock();
                      response = resp;
                      responseReceived.signalAll();
                      lock.unlock();
              }
            /* Implementation for `onError` and `onCompletedd` redacted */
        });
           Thread.sleep(5000);
        } catch (StatusRuntimeException e) {
               // Never caught!
                System.err.println("*** FAILED TO CONNECT TO SERVER!!! ***");
        }
        gate.countDown();
});

上面的代码将导致

StatusRuntimeException: UNAVAILABLE: Unable to resolve host NoSuchServer
,就像任何无法解析的主机一样:

$ java -jar m1-client.jar
Command> connect NoSuchServer 12345
Mar 04, 2024 3:14:24 P.M. io.grpc.internal.ManagedChannelImpl$NameResolverListener handleErrorInSyncContext
WARNING: [Channel<1>: (NoSuchServer:12345)] Failed to resolve name. status=Status{code=UNAVAILABLE, description=Unable to resolve host NoSuchServer, cause=java.lang.RuntimeException: java.net.UnknownHostException: NoSuchServer: Name or service not known
    at io.grpc.internal.DnsNameResolver.resolveAddresses(DnsNameResolver.java:223)
    at io.grpc.internal.DnsNameResolver.doResolve(DnsNameResolver.java:282)
    at io.grpc.internal.DnsNameResolver$Resolve.run(DnsNameResolver.java:318)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
    at java.base/java.lang.Thread.run(Thread.java:1589)
Caused by: java.net.UnknownHostException: NoSuchServer: Name or service not known
    at java.base/java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
    at java.base/java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:52)
    at java.base/java.net.InetAddress$PlatformResolver.lookupByName(InetAddress.java:1059)
    at java.base/java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1673)
    at java.base/java.net.InetAddress$NameServiceAddresses.get(InetAddress.java:1003)
    at java.base/java.net.InetAddress.getAllByName0(InetAddress.java:1663)
    at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1528)
    at io.grpc.internal.DnsNameResolver$JdkAddressResolver.resolveAddress(DnsNameResolver.java:632)
    at io.grpc.internal.DnsNameResolver.resolveAddresses(DnsNameResolver.java:219)
    ... 5 more
}
io.grpc.StatusRuntimeException: UNAVAILABLE: Unable to resolve host NoSuchServer
    at io.grpc.Status.asRuntimeException(Status.java:533)
    at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onClose(ClientCalls.java:481)
    at io.grpc.internal.DelayedClientCall$DelayedListener$3.run(DelayedClientCall.java:489)
    at io.grpc.internal.DelayedClientCall$DelayedListener.drainPendingCallbacks(DelayedClientCall.java:528)
    at io.grpc.internal.DelayedClientCall$1DrainListenerRunnable.runInContext(DelayedClientCall.java:317)
    at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
    at java.base/java.lang.Thread.run(Thread.java:1589)
Caused by: java.lang.RuntimeException: java.net.UnknownHostException: NoSuchServer: Name or service not known
    at io.grpc.internal.DnsNameResolver.resolveAddresses(DnsNameResolver.java:223)
    at io.grpc.internal.DnsNameResolver.doResolve(DnsNameResolver.java:282)
    at io.grpc.internal.DnsNameResolver$Resolve.run(DnsNameResolver.java:318)
    ... 3 more
Caused by: java.net.UnknownHostException: NoSuchServer: Name or service not known
    at java.base/java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
    at java.base/java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:52)
    at java.base/java.net.InetAddress$PlatformResolver.lookupByName(InetAddress.java:1059)
    at java.base/java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1673)
    at java.base/java.net.InetAddress$NameServiceAddresses.get(InetAddress.java:1003)
    at java.base/java.net.InetAddress.getAllByName0(InetAddress.java:1663)
    at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1528)
    at io.grpc.internal.DnsNameResolver$JdkAddressResolver.resolveAddress(DnsNameResolver.java:632)
    at io.grpc.internal.DnsNameResolver.resolveAddresses(DnsNameResolver.java:219)

(注意:第一个线程转储来自记录器,可以将其关闭;但这是一个单独的讨论)

看起来

StatusRuntimeException
是从内部库调用中抛出的(可能作为内部级别的异步任务)。 与阻塞 gRPC 调用不同,客户端应用程序可以通过上述方式使用 try-and-catch 捕获从较低级别抛出的异常,而我无法对非阻塞 gRPC 调用执行相同的操作。

如何在应用程序级别捕获

StatusRuntimeException

附注我到处搜索答案,并认为有一种简单的方法来处理从内部库调用引发的异常(一般来说),但这些“内部异常”似乎并没有向上传播到应用程序级别。

java grpc grpc-java
1个回答
0
投票

grpc-java 的内部不会抛出异常。相反,他们会报告

Status
。对于阻塞存根,该状态会转换为
StatusRuntimeException
并抛出。对于异步存根,它也会转换为异常,但会传递给
onError(Throwable)
作为参数

this.toServer = kvStore.connect(new StreamObserver<KVMessage>() {
     @Override
     public void onNext(KVMessage resp) {
         lock.lock();
         response = resp;
         responseReceived.signalAll();
         lock.unlock();
     }

     @Override
     public void onError(Throwable t) {
         Status status = Status.fromThrowable(t);
         // This is the equivalent of the catch block for blocking stubs.
         // Do custom error handling here.
         System.err.println("*** FAILED TO CONNECT TO SERVER!!! ***");
     }
     /* Implementation for `onCompleted` redacted */
});

有关更多信息,请参阅

错误处理示例
asyncCall()函数。

© www.soinside.com 2019 - 2024. All rights reserved.