2

框架:经验丰富的工程师/开发人员第一次处理 GRPC 和 HTTP2,并且很长时间以来第一次处理流式编程。

@grpc/grpc-js使用软件包时,为了成功检测 GRPC 服务器中的“故障”(服务器意外断开连接、服务器意外断开连接、服务器超时并消失等),我需要注意哪些事件?

也就是说——我们有一个使用 protobuffers 的 GRPC 服务,我们可以调用/设置一个类似这样的流

const protoLoader = require('@grpc/proto-loader')

const packageDefinition = protoLoader.loadSync(
  __dirname + '/path/to/v1.proto',
  {keepCase: true,
    longs: String,
    enums: String,
    defaults: true,
    oneofs: true
  })

const packageDefinition = grpc.loadPackageDefinition(packageDefinition).com.foo.bar.v1
const client = new packageDefinition.IngestService(
  'server.url.here.com:443',
  grpc.credentials.createSsl()
)

const stream = client.recordSpan(metadata)        

此时stream是一个ClientDuplexStreamImplobject,它以 Node 的 native Duplex作为其父类/对象。

Duplex对象同时实现了writablereadable流接口,这意味着它可能会发出close, drain, error, finish, pipe,unpipe事件(可写),或close, data, end, error, pause, readable,resume事件(可读)。该对象似乎也有一个metadatastatus事件ClientDuplexStreamImpl

我想要做的是设置一个有弹性的流。在我的幼稚想法中,这就像“如果流因任何原因断开连接,我将销毁对象并尝试使用退避算法再次连接”一样简单。

我幼稚的头脑面临的挑战是不清楚close和之间的区别end是什么,或者error频道是否只是让我知道发生错误,或者是否发生了错误并且一切都消失了。

此外,因为这些是流事件,所以也不清楚是否每种服务器断开连接都会反映在流中,以及我是否需要查看不同的对象(这些对象是哪些对象?)来检测连接的实际状态到服务器。

还值得一提的是,这是针对我无法控制其实现的服务器。

所以——重申我的问题:作为 GRPC 服务的客户端/消费者,我需要做什么来确保我检测到服务器已经“消失”并且我应该尝试重新连接?

4

1 回答 1

3

简短的回答是 gRPC 调用通常statusstatus.code等于结尾grpc.status.UNAVAILABLE,因此您应该能够通过使用该代码侦听状态/错误并在发生这种情况时重新建立流来完成您想要的。

首先,我想解释一下 gRPC 请求的整个生命周期。启动请求后,您通常会首先获得一个metadata包含响应标头的事件。然后您将执行一些write操作并接收一些data事件。然后流将结束,并触发一些半冗余事件。该end事件表示没有更多数据要读取,但没有其他信息。该close事件也可能在这里触发,但我从不使用它。该status事件提供了一个状态对象,说明流如何结束。.code等于grpc.status.OK表示流成功完成。在任何其他情况下,error也会发出一个事件,并且error对象将另外具有状态具有的所有相同字段。您应该始终监听该error事件,因为如果您不这样做并且发出了一个事件,Node 会自动将其冒泡并将其作为全局异常抛出。

如果流因任何原因结束,包括服务器断开连接,它将以status事件结束。网络错误(包括服务器断开连接)通常由UNAVAILABLE状态代码指示。当根本无法建立连接时,也会使用该代码。

在大多数情况下,gRPC 无论如何都是对连接的抽象。单个 gRPC 客户端可以由多个 TCP 连接支持,如果连接断开,gRPC 将自动尝试重新建立连接。

于 2020-03-26T20:45:25.593 回答