Skip to Content
🎉 gRPCity 3.0 is released. Read more →

Client

gRPCity 的 clients 工厂会从 loader 里发现 service,对它们建立连接,给你一个像普通 async 函数一样调用的类型化代理。

初始化

const clients = await loader.initClients({ services, channelOptions, credentials })

参数:

  • services(必填)—— { [服务名]: 地址 }
    • 服务名:含包名的完整 service 名称。
    • 地址:服务端地址,支持 host:port 字符串或 { host, port } 对象两种形态。
  • channelOptions(可选)—— 透传给底层 gRPC 的 channel 级配置。
  • credentials(可选)—— 客户端凭证,例如 TLS。

示例:

const credentials = loader.makeClientCredentials(rootCerts, privateKey, certChain, verifyOptions) const clients = await loader.initClients({ services: { 'dev.path.to.serviceA': 'domain.local:9099', 'path.to.serviceB': { host: '192.168.32.111', port: 10099 } }, channelOptions, credentials })

中间件

clients.use() 会在每次 RPC 前后运行。详见 Client Middleware 指南。

// 逐个添加 clients.use(f1) clients.use(f2) clients.use(f3) // 多个位置参数添加 clients.use(f1, f2, f3) // 用数组添加 clients.use([f1, f2, f3])

中间件只对 async 形式生效。callback 形式会绕过中间件。

获取实例

get(name) 按完整服务名返回一个已缓存的客户端代理。

const serviceAClient = clients.get('dev.path.to.serviceA') const serviceBClient = clients.get('path.to.serviceB')

get() 按名字缓存,重复调用返回同一个实例。如果需要一个全新的、不走缓存的客户端,请使用 getReal()

发起 RPC 调用

支持两种风格:asynccallback。常规情况下使用 async

async

const result = await serviceAClient.rpcMethod(request, metadata, options)

参数:

  • rpcMethod:proto 中 service 定义的方法。共有四种形态:unary、client streaming、server streaming、bidi streaming。
  • request:请求负载,结构由 proto 的 message 类型决定。
  • metadata(可选):作为键值对传递的请求 metadata,常用于鉴权、追踪等。
  • options(可选):per-call 选项对象。可用字段包括 timeout(单次调用超时,默认 10 秒)和 signal(用于取消调用的 AbortSignal,详见 AbortSignal)。

unary 示例:

const meta = loader.makeMetadata({ 'x-business-id': ['grpcity', 'testing'], 'x-timestamp-client': 'begin=' + new Date().toISOString() }) const options = { timeout: 5000 // 当前时间的 5 秒后超时 } const { status, peer, metadata, response } = await serviceAClient.rpcMethod( { name: 'myapp' }, meta, options )

每次调用都会返回四个字段:

  • status:服务端返回的 gRPC status。
  • peer:远端地址。
  • metadata:服务端返回的 trailing metadata。
  • response:响应负载本身。

典型结果:

{ status: { code: 0, details: 'OK', metadata: Metadata { internalRepr: Map(0) {}, options: {} } }, peer: '::9098', metadata: Metadata { internalRepr: Map(2) { 'content-type' => [Array], 'date' => [Array] }, options: {} }, response: { message: 'hello greeter by Greeter in server1', count: 1 } }

callback

callback 形式挂在 .call. 下:

const a = serviceAClient.call.rpcMethod1({ name: 'myapp' }, (err, result) => { if (err) throw err return result }) const b = serviceBClient.call.rpcMethod2({ name: 'youapp' }, (err, result) => { if (err) throw err return result })

重新初始化

服务端地址在运行时发生变化时,先清空已有 clients,再用新映射重新初始化。

const clients = await loader.initClients({ services: { 'dev.path.to.serviceA': 'domain.local:9099', 'path.to.serviceB': { host: '192.168.32.111', port: 10099 } } }) clients.clear() clients.init({ services: { 'dev.path.to.serviceA': 'domain.local:9088', 'path.to.serviceB': { host: '192.168.32.112', port: 10099 } } })

clear() 必须在 init() 之前。否则后续 init 会拿到缓存工厂,地址切换静默失效。

Last updated on