syntax = "proto3"; package bilibili.broadcast.v1; import "bilibili/rpc/status.proto"; import "google/protobuf/any.proto"; import "google/protobuf/empty.proto"; // broadcast操作,对应每个target_path service Broadcast { // 用户鉴权 rpc Auth(AuthReq) returns (AuthResp); // 心跳保活:成功心跳为4分45秒,重试心跳为30s,三次收不到进行重连(不超过5分45) rpc Heartbeat(HeartbeatReq) returns (HeartbeatResp); // 订阅target_path rpc Subscribe(TargetPath) returns (google.protobuf.Empty); // 取消订阅target_path rpc Unsubscribe(TargetPath) returns (google.protobuf.Empty); // 消息回执 rpc MessageAck(MessageAckReq) returns (google.protobuf.Empty); } // broadcast连接隧道 service BroadcastTunnel { // 创建双向stream连接隧道 rpc CreateTunnel(stream BroadcastFrame) returns (stream BroadcastFrame); } // 鉴权请求,通过authorization验证绑定用户mid message AuthReq { // 冷启动id,算法uuid,重新起启会变 string guid = 1; // 连接id,算法uuid,重连会变 string conn_id = 2; // 最后收到的消息id,用于过虑重连后获取未读的消息 int64 last_msg_id = 3; } // 鉴权返回 message AuthResp {} // 心跳请求 message HeartbeatReq{} // 心跳返回 message HeartbeatResp{} // target_path message TargetPath { // 需要订阅的target_paths repeated string target_paths = 1; } // 消息回执 message MessageAckReq { // 消息id int64 ack_id = 1; // ack来源,由业务指定用于埋点跟踪 string ack_origin = 2; // 消息对应的target_path,方便业务区分和监控统计 string target_path = 3; } // message_id: // client: 本次连接唯一的消息id,可用于回执 // server: 唯一消息id,可用于上报或者回执 // sequence: // client: 客户端应该每次请求时frame seq++,会返回对应的对称req/resp // server: 服务端下行消息,只会返回默认值:0 message FrameOption { // 消息id int64 message_id = 1; // frame序号 int64 sequence = 2; // 是否进行消息回执(发出MessageAckReq) // downstream 上只有服务端设置为true,客户端响应 // upstream 上只有客户端设置为true,服务端响应 // 响应帧禁止设置is_ack,协议上禁止循环 // 通常只有业务帧才可能设置is_ack, 因为协议栈(例如心跳、鉴权)另有响应约定 bool is_ack = 3; // 业务状态码 bilibili.rpc.Status status = 4; // 业务ack来源, 仅downstream时候由服务端填写. string ack_origin = 5; } // target_path: // "/" Service-Name "/" {method name} 参考 gRPC Request Path message BroadcastFrame { // 请求消息信息 FrameOption options = 1; // 业务target_path string target_path = 2; // 业务pb内容 google.protobuf.Any body = 3; }