YStudio Y++

gRPC类 / gRPC流类

Y++ / YStudio 开发文档 · 一点滴

类对象支持库(旁路插件)。路径:支持库 → 扩展类库。

类 插件 用途
gRPC类 supportlib.grpc 一元调用:同步/异步、重试、截止时间、取消、可选 gzip
gRPC流类 supportlib.grpc.stream 流式:服务端流 / 客户端流 / 双向流

免费,随整包 IDE。工程里用到哪个类,就只链接对应模块。消息载荷用 Protobuf类 编解码(或 proto_gen_ypl 生成字段名辅助)。

类型名必须写完整「gRPC类」「gRPC流类」。声明时自动创建。

硬约束

  1. 方法路径形如 /包名.服务名/方法名(与 .proto 的 package / service / rpc 对应)。
  2. 传输为 HTTPS + HTTP/2(通常需要 Windows 10 及以上)。
  3. 请求/响应是 protobuf 线格式字节集,不是 JSON 文本。
  4. 本库是 客户端;不能在本机起 gRPC 服务端。
  5. 回调在工作线程触发:置完成回调 / 置消息回调 不要直接改窗体控件,请投递到定时器或界面线程。
  6. 回调签名不必改;自定义上下文挂在对象上(可选,一个文本槽): - 不需要参数:置完成回调(&完成),回调仍写 函数 完成()。 - 简单标签:置完成回调(&完成, "订单A"),回调里 取回调参数()。 - 多字段 / 不同类型 / 数组(推荐):把 JSON类 编码后的文本放进回调参数,回调里再解码(见下方「回调参数用 JSON」)。 - 流式同理:置/取消息回调参数、置/取完成回调参数。
  7. 客户端流在 Windows 上会先缓冲写出的消息,在 结束客户端流 / 写完成 时一次发出(避免 HTTP/2 未知长度请求体被提前结束)。超大无限上传请自行分段多次打开。

适用场景(实战)

场景 建议
登录、查单、配置拉取、设备注册 gRPC类 一元
管理端调公司内部微服务 / gRPC 网关 gRPC类 + 置元数据 鉴权
任务进度、日志尾随、状态订阅 gRPC流类 打开服务端流
埋点/采样批量上报、分片上传 gRPC流类 打开客户端流
对话、远程指令来回 gRPC流类 打开双向流
界面不能卡 异步(真) + 定时器轮询 已完成,或 置完成回调
对方偶发不可用 置重试;慢接口用 置截止时间 / 取消

与 HTTP类 对比:已有 .proto、要强类型与流式时用 gRPC;公开 REST / 浏览器直连仍用 HTTP。


工程接入

  1. 插件目录(随整包 IDE,免费,不必单独上传官网): - plugins/supportlib.grpc/ → gRPC类 - plugins/supportlib.grpc.stream/ → gRPC流类 - 消息编解码另需 plugins/supportlib.protobuf/(Protobuf类) - 回调里传多字段/数组时另需 JSON类
  2. 在源码中声明对象即可自动引用,例如:
gRPC类 c
gRPC流类 s
Protobuf类 请求
  1. 打开工程后请 重新生成 再运行,确保链接到当前插件库(换过 IDE/插件版本后尤其重要)。
  2. 类型名必须写完整中文:「gRPC类」「gRPC流类」「Protobuf类」,不要写成 GrpcClient / Protobuf。
  3. 传输依赖系统 HTTPS + HTTP/2;通常需要 Windows 10 及以上。开发自签证书可 置校验证书(假),正式环境请校验并使用真实地址。

本库是 客户端。本机没有 gRPC 服务时,可用示例工程自带的 Python 模拟器联调(见下文「示例工程」)。


示例工程(对照练习)

随产品示例提供本机 HTTPS+HTTP/2 联调工程(目录名 grpc_smoke,含 _start_mock.bat 与说明 README.md)。打开后按步骤操作;按钮与 API 对照如下。

步骤 操作
1 安装 Python 3,命令行可执行 python
2 双击 _start_mock.bat,看到 gRPC mock https://127.0.0.1:50051/ 后保持窗口开启
3 用 IDE 打开工程 → 重新生成 → 运行
4 按按钮分场景;日志末尾应出现 失败=0
按钮 演示内容 主要 API
Protobuf 本地置/取/编码/解码(可不启模拟器) Protobuf类
一元 同步 调用 + 置元数据 调用 置元数据 取状态码
异步 异步(真) + 定时器轮询 已完成 取响应
回调JSON 置完成回调 + JSON 用户参数 置完成回调 取回调参数 + JSON类
进阶 不可用(14)、重试、截止、异步取消 置重试 置截止时间 取消
流式 Watch 服务端流 3 条、Upload 客户端流 n=2 打开服务端流 读消息 打开客户端流 结束客户端流
双向流 Chat 写 ping / 读 echo / 写完成 打开双向流 写消息 写完成

模拟器方法路径:/demo.Greeter/SayHello、Unavailable、Flaky、Slow、Watch、Upload、Chat。请求/响应为 Protobuf 线格式;示例用字段号 1 表示字符串。


快速开始 · 一元同步

Protobuf类 请求
请求.置文本(1, "world")

gRPC类 c
c.置地址("https://127.0.0.1:50051")
c.置超时(10000)
c.置截止时间(8000)
c.置重试(2, 200)
c.置校验证书(假)   ' 仅开发/自签证书
字节集 响应 = c.调用("/demo.Greeter/SayHello", 请求.编码())
如果 (c.取状态码() <> 0) {
    输出(c.取错误())
    返回 ()
}
Protobuf类 答复
答复.解码(响应)
输出(答复.取文本(1))

快速开始 · 一元异步

gRPC类 c

' 回调签名始终无参;需要上下文时用取回调参数()
函数 调用完成()
    输出(c.取回调参数())   ' → 订单查询(若曾置入)
    如果 (c.取状态码() <> 0) {
        输出(c.取错误())
        返回 ()
    }
    字节集 r = c.取响应()

Protobuf类 请求
请求.置文本(1, "async")
c.置地址("https://127.0.0.1:50051")
c.置校验证书(假)
c.异步(真)

' 写法一:登记回调时顺带传参
c.置完成回调(&调用完成, "订单查询")

' 写法二:先赋值再登记(第二参可省略)
' c.置回调参数("订单查询")
' c.置完成回调(&调用完成)

c.调用("/demo.Greeter/SayHello", 请求.编码())
' 不需要自定义参数:c.置完成回调(&调用完成) 即可

回调参数用 JSON(多类型 / 数组)

对象上只有一个文本槽;要传整数、逻辑、数组等,请用 JSON 文本(依赖 JSON类):

gRPC类 c
JSON类 j

函数 调用完成()
    JSON类 回
    如果 (回.解析(c.取回调参数()) == 假) {
        输出(回.取错误())
        返回 ()
    }
    整数 订单号 = 回.取整数("id")
    文本 备注 = 回.取文本("note")
    逻辑 加急 = 回.取逻辑("rush")
    整数 n = 回.取成员数("tags")   ' 数组长度
    文本 首标签 = 回.取文本("tags[0]")
    输出(到文本(订单号) + " " + 备注 + " " + 首标签)

j.置整数("id", 1001)
j.置文本("note", "加急单")
j.置逻辑("rush", 真)
j.置文本("tags[0]", "vip")
j.置文本("tags[1]", "mail")
c.异步(真)
c.置完成回调(&调用完成, j.到文本())   ' 等价:c.置回调参数(j.到文本())
c.调用("/demo.Greeter/SayHello", 请求.编码())

只要标签、不要结构时,直接传普通文本即可,不必包 JSON。路径如 tags[0] 见 JSON类。

快速开始 · 服务端流

gRPC流类 s
s.置地址("https://127.0.0.1:50051")
s.置校验证书(假)
Protobuf类 请求
请求.置文本(1, "watch")
如果 (s.打开服务端流("/demo.Greeter/Watch", 请求.编码()) == 假) {
    输出(s.取错误())
    返回 ()
}
当 (真) {
    字节集 m = s.读消息()
    如果 (字节集长度(m) == 0) {
        跳出 ()
    }
    Protobuf类 片
    片.解码(m)
    输出(片.取文本(1))
}
s.关闭()

注意:读循环请用 当 (真),不要写 循环 (真, n)(后者会变成只计次 1 次)。

快速开始 · 客户端流

gRPC流类 s
s.置地址("https://127.0.0.1:50051")
s.置校验证书(假)
如果 (s.打开客户端流("/demo.Greeter/Upload") == 假) {
    输出(s.取错误())
    返回 ()
}
Protobuf类 a
a.置文本(1, "a")
Protobuf类 b
b.置文本(1, "b")
s.写消息(a.编码())
s.写消息(b.编码())
字节集 汇总 = s.结束客户端流()
Protobuf类 回
回.解码(汇总)
输出(回.取文本(1))
s.关闭()

快速开始 · 双向流

gRPC流类 s
s.置地址("https://127.0.0.1:50051")
s.置校验证书(假)
如果 (s.打开双向流("/demo.Greeter/Chat") == 假) {
    输出(s.取错误())
    返回 ()
}
Protobuf类 片
片.置文本(1, "ping")
s.写消息(片.编码())
字节集 回 = s.读消息()   ' HTTP/2 下可与写交错
s.写完成()
s.关闭()

.proto → 字段名辅助

python build\proto_gen_ypl.py path\to\hello.proto -o 工程目录

生成如 HelloRequest_pb.yc,内含 置_HelloRequest_name(Protobuf类 消息, …) / 取_…。扩展类形参按值传句柄,不要写 &。

字段号与 .proto 一致;示例工程为简单演示直接用数字字段号,正式业务建议用生成辅助或统一常量。


状态码与错误

  • 取状态码():0 = 成功;非 0 为 gRPC 状态(如 1 已取消、4 超过截止时间、14 服务不可用)。
  • 取错误():中文说明,形如 gRPC类:服务不可用(状态码 14):…(面向用户,不含底层系统错误码)。
  • 取状态消息():服务端 grpc-message(若有)。

常见状态(便于对照日志):

码 含义(概要) 典型触发
0 成功 正常返回
1 已取消 取消()
4 超过截止时间 置截止时间 到期、或超时
14 服务不可用 对方返回 unavailable;可用 置重试

每次调用后务必看 取状态码();不要只看返回的字节集是否为空。


易错与排查

现象 原因与处理
服务端流只收到 1 条 读循环写成了 循环 (真, n)(会变成计次 1)。请用 当 (真) { … 跳出 }
回调里改按钮/文本框异常 完成/消息回调在工作线程。只改模块变量,界面更新放到定时器或界面线程
异步 调用 立刻得到空字节集 正常。应用 已完成 / 置完成回调 后再 取响应
想传整数/数组给回调却无效 回调签名固定无用户形参;上下文只有一个文本槽。多类型请放 JSON 文本,见上文
客户端流对端收不到中间包 Windows 上写出先缓冲,在 结束客户端流 / 写完成 时一次发出
自签证书连不上 开发可 置校验证书(假);确认地址为 https://… 且模拟器在跑
大量 FAIL / 截止异常 换过插件后未 重新生成;或 50051 上仍是旧模拟器进程
Flaky 重试不稳定 模拟器进程内计数;反复点「进阶」前可重启 _start_mock.bat
与 HTTP类 混用 JSON 当 gRPC 正文 gRPC 载荷是 protobuf 字节集,不是 JSON 文本

实战写法摘要

鉴权元数据(每次调用前):

c.清空元数据()
c.置元数据("authorization", "Bearer " + token)
字节集 r = c.调用("/pkg.Svc/Method", 请求.编码())

界面不卡:异步 + 定时器(示例「异步」按钮):

c.异步(真)
c.调用(路径, 请求.编码())
定时器.启动(50, &轮询)   ' 轮询里判断 已完成() 再取响应

界面不卡:异步 + 完成回调(示例「回调JSON」按钮):

c.异步(真)
c.置完成回调(&完成, j.到文本())
c.调用(路径, 请求.编码())
' 函数 完成() 内:取状态码 / 取响应 / 取回调参数;勿直接改控件

订阅进度(服务端流): 打开 → 当 (真) 读到空跳出 → 关闭。

批量上报(客户端流): 打开 → 多次 写消息 → 结束客户端流 取汇总 → 关闭。

对话(双向流): 打开 → 写/读可交错 → 写完成 → 关闭。


gRPC类/方法

置地址

  • 签名:无 置地址(文本 地址)
  • 说明:设置服务根地址。可写 https://主机:端口,或省略协议(默认按 https 处理)。后续 调用 都打到该主机。
  • 参数一│文本 地址: 如 "https://127.0.0.1:50051"。
  • 示例:置地址("https://api.example.com:443")

置超时

  • 签名:无 置超时(整数 毫秒)
  • 说明:解析/连接/发送/接收共用超时。与 置截止时间 同时设置时取更严(更短)的一方。
  • 参数一│整数 毫秒: >0 生效;未设时默认约 30000。
  • 示例:置超时(10000)

置截止时间

  • 签名:无 置截止时间(整数 毫秒)
  • 说明:从调用开始起的总时限。超时后状态码多为 4(超过截止时间)。0 = 不额外限制(仍受 置超时 约束)。HTTP/2 下除会话超时外还有看门狗,避免慢响应拖死界面。
  • 参数一│整数 毫秒: 如 400 表示约 0.4 秒内必须结束。
  • 示例:置截止时间(5000)

置校验证书

  • 签名:无 置校验证书(逻辑 校验)
  • 说明:HTTPS 是否校验证书。假 = 忽略自签/主机名不匹配等(仅建议开发或内网)。默认校验。
  • 示例:置校验证书(假)

置压缩

  • 签名:无 置压缩(逻辑 启用)
  • 说明:真 = 请求消息体用 gzip(对方需支持 grpc-encoding: gzip)。默认关。
  • 示例:置压缩(真)

置重试

  • 签名:无 置重试(整数 次数, [整数 间隔毫秒=200])
  • 说明:首次失败后的额外重试次数。仅对可重试状态生效(如超时、资源耗尽、中止、服务不可用)。已取消 与成功不会重试。间隔会随次数递增。
  • 参数一│整数 次数: 0 = 不重试;3 = 最多共 4 次尝试。
  • 参数二│整数 间隔毫秒: 基础退避间隔,默认 200。
  • 示例:置重试(3, 80)

清空元数据 / 置元数据

  • 签名:无 清空元数据() · 无 置元数据(文本 键, 文本 值)
  • 说明:自定义请求元数据(HTTP/2 头),常用于鉴权。每次 调用 前可清空再设置。
  • 示例:置元数据("authorization", "Bearer xxx")

异步 / 取异步

  • 签名:无 异步(逻辑 启用) · 逻辑 取异步()
  • 说明:异步(真) 后,调用 在后台执行并立刻返回空字节集;用 已完成 / 置完成回调 / 定时器取结果。假 = 恢复同步(调用 阻塞到结束)。
  • 示例:异步(真)

已完成

  • 签名:逻辑 已完成()
  • 说明:异步模式下,后台调用是否已结束。同步模式或未在调用时为真。
  • 示例:如果 (c.已完成()) { … }

取消

  • 签名:逻辑 取消()
  • 说明:取消进行中的异步调用。成功发起取消后状态码多为 1(已取消)。无进行中任务时返回假。
  • 示例:c.取消()

置完成回调

  • 签名:无 置完成回调([子程序指针 回调=0], [文本 用户参数=""])
  • 说明:异步结束时触发。回调固定 函数 名()(忘了写用户参数形参也没关系)。可选第二参:非空文本写入回调参数;省略则不改已有值。传 0 清除回调并清空参数。工作线程,勿直接改控件。
  • 参数一│子程序指针: &调用完成 或 0。
  • 参数二│文本 用户参数: 可选,如 "订单查询"。
  • 示例:置完成回调(&调用完成) · 置完成回调(&调用完成, "订单查询")

置回调参数 / 取回调参数

  • 签名:无 置回调参数(文本 用户参数) · 文本 取回调参数()
  • 说明:赋值用 置回调参数("" 清空);取值在回调里 取回调参数()。与 置完成回调 第二参等效。
    槽位是单个文本:多参数、不同类型、数组请放入 JSON 文本(见上文「回调参数用 JSON」),不要期望回调形参里直接出现整数/数组。

调用

  • 签名:字节集 调用(文本 方法路径, 字节集 请求)
  • 说明:发起一元 RPC。同步:返回响应消息字节集(失败可能为空,务必看 取状态码)。异步:立刻返回空,完成后用 取响应。
  • 参数一│文本 方法路径: 如 "/demo.Greeter/SayHello"。
  • 参数二│字节集 请求: 一般为 Protobuf类.编码() 结果;可空。
  • 示例:字节集 r = c.调用("/demo.Greeter/SayHello", 请求.编码())

取响应

  • 签名:字节集 取响应()
  • 说明:取出最近一次异步调用的响应消息(成功时)。建议在 已完成 为真且状态码为 0 后调用。
  • 示例:字节集 r = c.取响应()

取状态码 / 取状态消息 / 取错误

  • 签名:整数 取状态码() · 文本 取状态消息() · 文本 取错误()
  • 说明:最近一次调用的结果。0 成功;取错误 为面向用户的中文说明。

gRPC流类/方法

配置(与一元类似)

置地址 置超时 置截止时间 置校验证书 置压缩 清空元数据 置元数据 —— 语义同 gRPC类(流式无 置重试)。

置消息回调

  • 签名:无 置消息回调([子程序指针 回调=0], [文本 用户参数=""])
  • 说明:每条消息回调;结束时再调且结束=真。签名固定 函数 名(字节集 消息, 逻辑 结束)。可选第二参写入消息回调参数。读线程,勿直接改 UI。
  • 示例:置消息回调(&收到一片) · 置消息回调(&收到一片, "订阅A")

置完成回调

  • 签名:无 置完成回调([子程序指针 回调=0], [文本 用户参数=""])
  • 说明:流结束时回调。签名固定 函数 名()。可选第二参。工作线程。
  • 示例:置完成回调(&流结束, "订阅A")

置/取消息回调参数 · 置/取完成回调参数

  • 说明:与一元相同——各一个文本槽;复杂数据用 JSON 文本;"" 清空。

取消

  • 签名:逻辑 取消()
  • 说明:取消当前流(关闭进行中的请求)。状态码多为已取消。

打开服务端流

  • 签名:逻辑 打开服务端流(文本 方法路径, 字节集 请求)
  • 说明:发送一条请求,然后连续接收多条响应。成功返回真,再用 读消息 或消息回调取片。
  • 示例:打开服务端流("/demo.Greeter/Watch", 请求.编码())

读消息 / 还有消息

  • 签名:字节集 读消息() · 逻辑 还有消息()
  • 说明:读消息 阻塞等待下一条;流结束或超时返回空字节集。还有消息 表示队列里是否已有可读消息(不阻塞)。
  • 示例:见上方「服务端流」快速开始。

打开客户端流 / 写消息 / 结束客户端流

  • 签名:逻辑 打开客户端流(文本 方法路径) · 逻辑 写消息(字节集 消息) · 字节集 结束客户端流()
  • 说明:打开后多次 写消息,最后 结束客户端流 发出全部缓冲并读取一条汇总响应。适合批量上报。
  • 示例:见上方「客户端流」快速开始。

打开双向流 / 写完成

  • 签名:逻辑 打开双向流(文本 方法路径) · 逻辑 写完成()
  • 说明:打开后可读可写交错(HTTP/2)。写端结束时调 写完成。仍可用 读消息 / 写消息。
  • 示例:见上方「双向流」快速开始。

关闭

  • 签名:无 关闭()
  • 说明:关闭当前流与网络句柄,可再次 打开*流。切换流类型前建议先关闭。

取状态码 / 取状态消息 / 取错误

  • 说明:同 gRPC类,表示最近一次流操作的状态。

相关

Protobuf类 · JSON类 · 字节集 · HTTP类