如何使具有服务器流连接的Android grpc客户端保持活动状态?

如何使具有服务器流连接的Android grpc客户端保持活动状态?,android,kotlin,grpc,grpc-java,Android,Kotlin,Grpc,Grpc Java,我有一个grpc js服务器和一个Kotlin for Android客户端,用于进行服务器流式调用。这是GRPCService类 GRP类服务{ private val mChannel=ManagedChannelBuilder .对于地址GRPC\主机\地址,GRPC\主机\端口 .使用纯文本 .keepAliveTime10,TimeUnit.SECONDS .Keepalive无需调用 建筑 val asyncStub:ResponderServiceGrpc.ResponderSer

我有一个grpc js服务器和一个Kotlin for Android客户端,用于进行服务器流式调用。这是GRPCService类

GRP类服务{ private val mChannel=ManagedChannelBuilder .对于地址GRPC\主机\地址,GRPC\主机\端口 .使用纯文本 .keepAliveTime10,TimeUnit.SECONDS .Keepalive无需调用 建筑 val asyncStub:ResponderServiceGrpc.ResponderServiceStub= ResponderServiceGrpc.newStubmChannel } 并且该方法是从前台服务调用的

重写一次创建{ super.onCreate ... startForegroundMyNotificationBuilder.SERVICE\u NOTIFICATION\u ID,notificationBuilder.getServiceNotification } 覆盖趣味onStartCommandintent:Intent?,标志:Int,startId:Int:Int{ val userId=SharedReferencesManager.GetIntSharedReferencesManager.USER\u ID val taskRequest=Responder.taskRequest.newBuilder .setUserIduserId 建筑 grpcService.asyncStub.GettaskTaskRequest,对象: 河流观察者{ 覆盖未完成的乐趣{ Log.dgrpc任务,已完成 } 可丢弃的{ Log.dgrpc错误原因,t?.cause.toString t?.cause?.printStackTrace Log.dgrpc错误,原因之后 t!!.printStackTrace } 是否覆盖fun onNextvalue:Responder.TaskResponse{ 如果值!=null{ 当value.command{ ... } } } } 返回super.onStartCommandintent、flags、startId } 连接打开并保持打开状态约一分钟,没有通信,然后出现以下错误而失败

D/grpc error cause: null
D/grpc error: AFTER CAUSE
io.grpc.StatusRuntimeException: INTERNAL: Internal error
io.grpc.Status.asRuntimeException(Status.java:533)
io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onClose(ClientCalls.java:460)
io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:426)
io.grpc.internal.ClientCallImpl.access$500(ClientCallImpl.java:66)
io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.close(ClientCallImpl.java:689)
io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.access$900(ClientCallImpl.java:577)
io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:751)
io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:740)
io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
grpc js服务器是使用以下选项创建的

var server = new grpc.Server({
    "grpc.http2.min_ping_interval_without_data_ms" : 10000,
    "grpc.keepalive_permit_without_calls" : true,
    "grpc.http2.min_time_between_pings_ms" : 10000,
    "grpc.keepalive_time_ms" : 10000,
    "grpc.http2.max_pings_without_data" : 0,
    'grpc.http2.min_ping_interval_without_data_ms':  5000
});
我也从来没有收到过太多的ping错误

我注意到,如果存在定期通信,例如服务器每隔30秒左右通过此连接ping客户端少量数据,那么我不会收到错误,只要ping持续测试2天,连接就会保持打开状态


如何在不定期ping客户端的情况下保持连接打开?

您是否尝试过ManagedChannel Builder.keepAliveTime设置?我假设它会在服务器流调用的中间工作。

< P>你尝试过MauldChhannBuudio.KePayLaveTimes设置吗?我假设它将在服务器流调用的中间工作。

< P>托管通道有一个称为KePaPiVIEWOUTFLASH的属性,其默认值为false。如果未设置为true,则如果当前未发生活动调用,则不会发生keepAlive。您需要这样设置:

private val mChannel = ManagedChannelBuilder
    .forAddress(GRPC_HOST_ADDRESS, GRPC_HOST_PORT)
    .usePlaintext()
    .keepAliveTime(30, TimeUnit.SECONDS)
    .keepAliveWithoutCalls(true)
    .build()
您可能需要在服务器上执行一些其他设置,以便在不传递任何数据的情况下保持连接的打开状态。服务器上可能会出现一个错误,提示ping太多。发生这种情况是因为GRPC需要一些其他设置。我不确定如何使用JS服务器实现这一点,但应该不会太难。这些设置包括:

GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS
Minimum allowed time between a server receiving successive ping frames without sending any data/header/window_update frame.
还有这个:

GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS
Minimum time between sending successive ping frames without receiving any data/header/window_update frame, Int valued, milliseconds.
GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS
Is it permissible to send keepalive pings without any outstanding streams.
还有这个:

GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS
Minimum time between sending successive ping frames without receiving any data/header/window_update frame, Int valued, milliseconds.
GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS
Is it permissible to send keepalive pings without any outstanding streams.

我建议您通读一篇文章,以了解gRPC应如何保持连接打开。这是所有服务器和客户端实现都应该遵循的核心标准,但我注意到情况并非总是如此。您可以看看我刚才问的一个类似问题。

托管频道有一个名为keepAliveWithoutCalls的属性,该属性的默认值为false,如图所示。如果未设置为true,则如果当前未发生活动调用,则不会发生keepAlive。您需要这样设置:

private val mChannel = ManagedChannelBuilder
    .forAddress(GRPC_HOST_ADDRESS, GRPC_HOST_PORT)
    .usePlaintext()
    .keepAliveTime(30, TimeUnit.SECONDS)
    .keepAliveWithoutCalls(true)
    .build()
您可能需要在服务器上执行一些其他设置,以便在不传递任何数据的情况下保持连接的打开状态。服务器上可能会出现一个错误,提示ping太多。发生这种情况是因为GRPC需要一些其他设置。我不确定如何使用JS服务器实现这一点,但应该不会太难。这些设置包括:

GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS
Minimum allowed time between a server receiving successive ping frames without sending any data/header/window_update frame.
还有这个:

GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS
Minimum time between sending successive ping frames without receiving any data/header/window_update frame, Int valued, milliseconds.
GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS
Is it permissible to send keepalive pings without any outstanding streams.
还有这个:

GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS
Minimum time between sending successive ping frames without receiving any data/header/window_update frame, Int valued, milliseconds.
GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS
Is it permissible to send keepalive pings without any outstanding streams.

我建议您通读一篇文章,以了解gRPC应如何保持连接打开。这是所有服务器和客户端实现都应该遵循的核心标准,但我注意到情况并非总是如此。您可以看看我刚才问的一个类似问题。

谢谢您的回答,但不幸的是,在大约一分钟的不活动后,它仍然失败,并出现相同的错误。我对问题进行了编辑,以反映我的更改,并添加了更多的上下文。感谢您的回答,但不幸的是,在大约一分钟的不活动后,它仍然失败,并出现相同的错误。我已经编辑了这个问题,以反映我的变化,并添加了更多的上下文。谢谢你的帮助
结构化回答。我相应地编辑了我的问题,但错误仍然存在。我查看了您提供的所有链接,并在适用的情况下将其合并到我的代码中。我从来没有收到过太多的ping错误。它一直是上面的那个。我最初使用grpc js客户端测试了我的服务器,我在那里收到了相同的错误。只是为了确保,您没有在js服务器和Android客户端之间使用某些代理软件,如Nginx或任何L7负载平衡器?它们可能有自己的超时和连接清理配置。我有。我正在使用Nginx将GRPC端口上的通信转发到GRPC服务器。我没有想到这一点。让我也调查一下。谢谢你的提示。由于Nginx是一个L7代理,底层的L4-TCP连接在Nginx终止。这意味着您需要配置Nginx以保持连接打开,以符合gRPC规范。因为gRPC使用Http2。您可能需要检查Nginx端的一组配置,以确保其配置正确。老实说,我从来没有使用过http2代理。我的意思是Nginx不转发端口。它实际上检查http/http2协议上的底层通信量,并决定转发哪个主机。感谢结构良好的回答。我相应地编辑了我的问题,但错误仍然存在。我查看了您提供的所有链接,并在适用的情况下将其合并到我的代码中。我从来没有收到过太多的ping错误。它一直是上面的那个。我最初使用grpc js客户端测试了我的服务器,我在那里收到了相同的错误。只是为了确保,您没有在js服务器和Android客户端之间使用某些代理软件,如Nginx或任何L7负载平衡器?它们可能有自己的超时和连接清理配置。我有。我正在使用Nginx将GRPC端口上的通信转发到GRPC服务器。我没有想到这一点。让我也调查一下。谢谢你的提示。由于Nginx是一个L7代理,底层的L4-TCP连接在Nginx终止。这意味着您需要配置Nginx以保持连接打开,以符合gRPC规范。因为gRPC使用Http2。您可能需要检查Nginx端的一组配置,以确保其配置正确。老实说,我从来没有使用过http2代理。我的意思是Nginx不转发端口。它实际上检查http/http2协议上的底层通信量,并决定转发哪个主机。