gRPC API 协议详解与 Proto 客户端生成指南)
Dapr 可插拔组件Pluggable ComponentsgRPC API 协议详解与 Proto 客户端生成指南【免费下载链接】daprDapr is a portable runtime for building distributed applications across cloud and edge, combining event-driven architecture with workflow orchestration.项目地址: https://gitcode.com/GitHub_Trending/da/dapr导读本文以 Dapr 仓库中 dapr/proto/components/v1 目录下的 Pluggable Components可插拔组件gRPC 协议定义文件为对象系统讲解 Dapr 如何通过独立的 gRPC 服务让用户将自研组件运行在 daprd 二进制之外你将掌握common、state、pubsub、bindings、secretstore五类 proto 文件中的服务与方法设计理解流式消息确认ACK、事务、批量操作、查询等核心语义并学会使用make init-proto/make gen-proto从零生成 Go gRPC 与 Connect 客户端代码。一、Pluggable Components 是什么Dapr 的组件体系默认以进程内编译的方式运行——状态存储、发布订阅、绑定、密钥仓库等组件都直接链接进 daprd 二进制。而 Pluggable Components 是 Dapr 提供的一种组件扩展机制它允许开发者编写独立于 daprd 进程之外运行的自定义组件组件与 daprd 之间通过本目录定义的 gRPC 协议进行通信。该功能的协议定义集中在 dapr/proto/components/v1 目录包含 5 个 proto 文件文件组件类型说明common.proto全部组件公共消息与通用约定Metadata、Features、Ping 等state.proto状态存储StateStore 及其事务、批量、查询扩展服务pubsub.proto发布订阅PubSub 服务与流式消息拉取协议bindings.proto输入/输出绑定InputBinding 与 OutputBinding 服务secretstore.proto密钥仓库SecretStore 服务与批量获取所有文件都声明在package dapr.proto.components.v1包下Go 端生成代码的输出包为github.com/dapr/dapr/pkg/proto/components/v1见各文件中的option go_package声明。从源码结构可以推断这套协议的目标是让每种组件类型的 gRPC 服务与 daprd 内部既有的组件抽象一一对应从而把进程内接口平滑替换为跨进程 gRPC 接口。二、公共协议common.protocommon.proto 是所有组件服务共同依赖的基础文件它定义了三个核心消息MetadataRequest携带mapstring, string properties作为所有组件初始化请求的基座——组件的配置元数据连接串、密钥、超时等都通过这张 KV 表传入。FeaturesRequest/FeaturesResponseFeaturesResponse返回repeated string features用于向 daprd 通告组件实现了哪些可选特性例如状态存储是否支持 ETag、事务等其语义与 Dapr 组件能力声明如ComponentFeature对齐。PingRequest/PingResponse用于组件存活探活liveness。两个空请求/响应消息都在注释中明确标注 reserved for future-proof extensibility为未来扩展预留体现了协议设计上对向后兼容性的刻意留白。三、状态存储协议state.protostate.proto 定义了 Dapr 状态存储组件最完整的一组 gRPC 服务共包含 4 个服务。3.1 StateStore 主服务StateStore服务覆盖了状态存储的全部核心操作RPC请求 / 响应说明InitInitRequest→InitResponse用给定元数据初始化状态存储组件FeaturesFeaturesRequest→FeaturesResponse返回已实现的状态存储特性列表GetGetRequest→GetResponse读取指定 key 的数据SetSetRequest→SetResponse写入指定 key 的值DeleteDeleteRequest→DeleteResponse删除指定 keyBulkGetBulkGetRequest→BulkGetResponse一次获取多个 keyBulkSetBulkSetRequest→BulkSetResponse一次写入多个 keyBulkDeleteBulkDeleteRequest→BulkDeleteResponse一次删除多个 keyPingPingRequest→PingResponse存活探活关键消息字段Etag{ string value }表示状态条目版本。在GetRequest/SetRequest/DeleteRequest中用作If-Match 头语义实现乐观并发控制对应StateOptions.StateConcurrency的 FIRST_WRITE / LAST_WRITE 模式。StateOptions定义两组枚举——StateConcurrencyCONCURRENCY_UNSPECIFIED、CONCURRENCY_FIRST_WRITE、CONCURRENCY_LAST_WRITE与StateConsistencyCONSISTENCY_UNSPECIFIED、CONSISTENCY_EVENTUAL、CONSISTENCY_STRONG与 Dapr 用户侧状态操作 API 中的 concurrency / consistency 语义一一对应。GetResponse返回bytes data、Etag etag、mapstring,string metadata与content_type。BulkStateItem批量读取的单个条目除 data/etag/metadata/content_type 外还带error字段允许单条目级的部分失败。批量请求的BulkGetRequestOptions/BulkSetRequestOptions/BulkDeleteRequestOptions统一提供int64 parallelism参数控制批量操作的并发度。3.2 QueriableStateStore查询扩展服务QueriableStateStore服务提供Query(QueryRequest) → QueryResponseRPC设计目标是以互补服务的形式向 StateStore 服务嵌入查询能力It was designed to embed query features to the StateStore Service as a complementary service。其消息模型Querymapstring, google.protobuf.Any filter过滤器值采用 Any 类型以支持各存储引擎自定义查询语法例如 Dapr 查询 API 中的 filter 结构、repeated Sorting sort排序、Pagination pagination分页。SortingkeyOrder枚举ASC/DESC。Paginationint64 limit与string tokentoken 用于游标式分页。QueryResponserepeated QueryItem itemsstring token下一页游标 metadata。这与仓库中pkg/state查询能力的实现相呼应——凡是支持Query的状态存储组件均可通过该 RPC 暴露查询语义。3.3 TransactionalStateStore事务扩展服务TransactionalStateStore服务提供Transact(TransactionalStateRequest) → TransactionalStateResponseRPC同样以互补服务方式嵌入事务能力TransactionalStateOperation使用oneof request组合DeleteRequest或SetRequest一条事务里可混合删除与写入。TransactionalStateRequestrepeated TransactionalStateOperation operations 请求元数据。3.4 TransactionalStoreMultiMaxSize该服务提供MultiMaxSize(MultiMaxSizeRequest) → MultiMaxSizeResponseRPC用于向兼容事务的状态存储查询单次事务允许的最大操作数int64 max_size便于 daprd 对超长事务做拆批处理。四、发布订阅协议pubsub.protopubsub.proto 定义PubSub服务覆盖消息发布、批量发布与流式订阅RPC说明Init用元数据初始化 pubsub 组件Features返回已实现的 pubsub 特性Publish向指定 topic 发布单条消息BulkPublish批量发布BulkPublishRequest内含repeated BulkMessageEntry entries每条带entry_id响应BulkPublishResponse.failed_entries逐条返回失败项支持部分失败语义PullMessages双向流组件服务端向 daprd客户端推送消息客户端回流 ACK流关闭即表示出错客户端需重建连接Pause/Resume暂停/恢复消息投递实现优雅停机pause-and-drain。协议注释明确服务端可不实现返回UNIMPLEMENTED此时 daprd 回退为 close-first 停机两个方法均幂等Ping存活探活流式拉取的 ACK 协议细节协议注释原文要点双向流PullMessagesRequest ↔ PullMessagesResponse中第一条客户端请求必须携带Topic含topic名与订阅元数据后续请求不得再设置 topic该 topic 用于整个流的持续拉取。每条PullMessagesResponse携带{transient}消息 IDid字段客户端处理完成后通过PullMessagesRequest.ack_message_id回执 ACK处理失败时通过ack_errorAckMessageError仅含message字符串回报错误。AckMessageError的设计与 bindings 协议中的AckResponseError完全同构。此外PublishRequest携带pubsub_namepubsub 组件名、topic、data、metadata与content_type与 daprd 发布 API 的参数模型一致。五、绑定协议bindings.protobindings.proto 定义了输入绑定与输出绑定两个服务。5.1 InputBinding输入绑定RPC说明Init初始化输入绑定组件Read双向流组件向 daprd 持续推送事件daprd 回流 ACKPing存活探活ReadResponse组件 → daprd携带data、metadata、content_type以及用于后续 ACK 的{transient}message_iddaprd 通过ReadRequest.response_data处理结果载荷、message_id与可选的response_errorAckResponseError完成消息确认或失败回报。流关闭即视为出错客户端需要重建流。5.2 OutputBinding输出绑定RPC说明Init初始化输出绑定组件Invoke以可选载荷调用外部系统InvokeRequestdatametadataoperationInvokeResponsedatametadatacontent_typeListOperations列出组件支持的 operation 列表ListOperationsResponse.operationsPing存活探活从源码结构看operation字段直接对应 Dapr 绑定调用 API 中的 operation 参数如create、get等ListOperations则为元数据发现提供支撑。六、密钥仓库协议secretstore.protosecretstore.proto 定义SecretStore服务RPC说明Init初始化密钥仓库Features返回已实现的特性GetGetSecretRequestkeymetadata→GetSecretResponsemapstring,string dataBulkGetBulkGetSecretRequest→BulkGetSecretResponsemapstring, SecretResponse data其中SecretResponse是mapstring,string secretsPing存活探活协议注释特别说明某些密钥仓库如 Kubernetes Secret允许一个 key 下保存多个密文因此GetSecretResponse.data设计为 key → value 的映射而非单值BulkGetSecretResponse也相应采用密钥名 → 多值映射的两层结构与 Dapr 密钥 API 的返回结构保持一致。七、Proto 客户端生成全流程7.1 前置条件按 dapr/proto/components/v1/README.md 的要求安装protoc版本固定为v4.25.4对应 protobuf 编译器套件上层 dapr/README.md 亦给出 v25.4 的同一版本约定。安装三个代码生成插件protoc-gen-go、protoc-gen-go-grpc、protoc-gen-connect-go。7.2 安装插件make init-proto在仓库根目录执行make init-proto该命令实际执行的安装逻辑位于 Makefile等价于go install google.golang.org/protobuf/cmd/protoc-gen-go$(PROTOC_GEN_GO_VERSION) go install google.golang.org/grpc/cmd/protoc-gen-go-grpcv$(PROTOC_GEN_GO_GRPC_VERSION) go install connectrpc.com/connect/cmd/protoc-gen-connect-gov$(PROTOC_GEN_CONNECT_GO_VERSION)其中三个插件的版本号均由 Makefile 顶部的变量统一管理。7.3 生成客户端make gen-proto若protoc已就绪从仓库根目录执行make gen-protogen-proto目标Makefile依次执行check-proto-version版本校验、为dapr/proto下每个子目录逐一生成GRPC_PROTOS : $(shell ls dapr/proto)每个目录对应gen-proto-name目标最后执行modtidy整理 go.mod。单个目录的生成命令见 Makefileprotoc --go_out. --go_optmodulegithub.com/dapr/dapr \ --go-grpc_out. --go-grpc_optrequire_unimplemented_serversfalse,modulegithub.com/dapr/dapr \ --connect-go_out. --connect-go_optmodulegithub.com/dapr/dapr \ ./dapr/proto/components/v1/*.proto值得注意的两个生成选项--go-grpc_optrequire_unimplemented_serversfalse生成的 gRPC 服务接口不强制嵌入Unimplemented*Server占位结构便于组件实现方更轻量地接入。同时输出connect-go代码说明 Dapr 的 gRPC 服务同时支持 Connect RPC 生态客户端。7.4 版本校验check-proto-versionMakefile会逐一比对protoc、protoc-gen-go-grpc与protoc-gen-connect-go的版本版本不匹配时直接报错退出并提示使用规定版本避免生成代码与工具链漂移。7.5 产物位置生成结果落在pkg/proto下components 相关产物位于 pkg/proto/components/v1纯 protobuf 消息代码common.pb.go、state.pb.go、pubsub.pb.go、bindings.pb.go、secretstore.pb.gogRPC 服务桩state_grpc.pb.go、pubsub_grpc.pb.go、bindings_grpc.pb.go、secretstore_grpc.pb.goConnect 客户端componentsconnect/下的bindings.connect.go、pubsub.connect.go、secretstore.connect.go、state.connect.go这些.go文件为自动生成产物组件开发者可直接 import 对应包实现服务端或作为客户端与 daprd 通信。八、WindowsWSL2 / Ubuntu 24.04下的生成说明针对 Windows 用户dapr/README.md 给出了 WSL2 Ubuntu 24.04 环境的完整步骤安装unzip下载protoc-25.4-linux-x86_64.zip并解压将bin/*移入/usr/local/bin、include/*移入/usr/local/include清理临时目录切换到 Dapr 仓库目录例如 Windows 侧P:/Code/Dapr在 Ubuntu 终端中对应/mnt/p/Code/Dapr执行make init-proto安装三个插件并通过ln -s ~/go/bin/protoc-gen-go /usr/local/bin等命令将插件软链到 PATH执行make gen-proto生成客户端代码。九、Proto 变更后的依赖同步README.md 与 dapr/README.md 均提示当 proto 出现破坏性变更时需要同步更新 e2e 测试应用依赖。在tests目录下执行# 使用 dapr 的最近一次提交 ./update_testapps_dependencies.sh be08e5520173beb93e5d5f047dbde405e78db658该脚本位于 tests/update_testapps_dependencies.sh会将各测试应用的 go.mod 指向最新 dapr 版本并生成对应 go.sum在 Windows 上需借助 mingw 工具执行 bash 脚本最后将修改过的 go.mod 一并提交。十、从协议到实现组件接入路径综合以上协议设计与仓库结构可以梳理出 Pluggable Components 的接入路径实现端开发者根据目标组件类型选择StateStore、PubSub、InputBinding/OutputBinding或SecretStore服务实现其中 RPC 方法并通过MetadataRequest.properties接收组件配置。能力声明通过FeaturesRPC 向 daprd 声明组件特性对查询、事务、批量等能力通过实现对应的互补服务QueriableStateStore、TransactionalStateStore、TransactionalStoreMultiMaxSize或批量 RPC 暴露。生命周期Init完成初始化、Ping支撑健康检查、Pause/Resumepubsub支撑优雅停机。通信语义状态类操作用 ETag StateOptions 表达并发与一致性消息类操作用双向流 {transient}message_id 表达投递与 ACK批量操作统一用 parallelism 控制并发度。这套协议与 daprd 内置组件的接口语义高度同构对应仓库中pkg/components与pkg/runtime的组件抽象使得开发者可以用任何支持 gRPC 的语言编写组件在不重新编译 daprd 的前提下扩展 Dapr 的组件生态——这正是本目录协议设计的核心价值。提示文章所引用的 Makefile 目标、proto 文件与生成产物路径均可在当前仓库中直接查看验证实际使用前请确认本地 protoc 及插件版本与本仓库 Makefile 中PROTOC_VERSION、PROTOC_GEN_GO_VERSION、PROTOC_GEN_GO_GRPC_VERSION、PROTOC_GEN_CONNECT_GO_VERSION声明的版本一致。【免费下载链接】daprDapr is a portable runtime for building distributed applications across cloud and edge, combining event-driven architecture with workflow orchestration.项目地址: https://gitcode.com/GitHub_Trending/da/dapr创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考