feat: implement broadcast call functionality#219
Closed
xing-cg wants to merge 1 commit into
Closed
Conversation
- Add BroadcastUnaryInvoke, AsyncBroadcastUnaryInvoke, BroadcastOnewayInvoke APIs - Add MakeTrpcSelectorInfoForBroadcast and SetClientContextForBroadcast helper functions - Support both Fiber and Future concurrency models - Add broadcast test example - Update BUILD dependencies for broadcast functionality This implements the broadcast call feature as described in the issue, allowing a single request to be sent to multiple backend instances concurrently and aggregating their responses.
|
CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅ |
Author
|
I have read the CLA Document and I hereby sign the CLA |
liuzengh
added a commit
to liuzengh/cla-database
that referenced
this pull request
Jul 29, 2025
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
需求:tRPC-Cpp已将内部广播代码变更打出一个patch文件,需要同学基于这个patch,适配开源版本,并完成详细的功能验证
注意:如7天内无提交任何进展包括不限于comment \ commit \ Pull Request,则将视为同学主动放弃issue,组委会将释放issue给下一位等候者。
任务整体难度评估
将一个已有的补丁(
broadcast_call.patch)合并到 tRPC-Cpp 主干分支,并完成功能验证,是一个 中等难度 的任务。主要挑战在于:构建环境复杂性:tRPC-Cpp 使用 Bazel 进行构建,需要提前安装 Bazel 及相关依赖(如 Protobuf、gflags、fmt 等)。如果从未构建过该项目,需要花时间准备环境并熟悉 Bazel 的用法。
补丁冲突和适配:
broadcast_call.patch可能是基于旧版本创建的。如果主干分支发生了代码变动,应用补丁时可能出现冲突,需要了解 tRPC-Cpp 框架的代码结构来手工合并修改。框架理解:广播调用涉及 RPC 框架核心机制(例如调用类型、网络传输、多实例调用等)。需要阅读并理解补丁中涉及的模块(RPC 调用层、命名服务等),对于不了解该框架的人来说有一定门槛。不过好在你有 C++ 高并发开发和 RPC 原理经验,可以加速理解这些改动。
功能验证难度:需设计测试用例验证广播调用是否生效。这涉及启动多个服务实例、模拟广播场景并收集结果。需要一定的动手实验能力。
总体而言,此任务需要在构建环境、补丁合并、代码理解、测试验证几个方面投入时间,需要仔细规划和调试。下面将针对该任务制定一个具体的开发计划。
构建和运行 tRPC-Cpp 主干版本
开始补丁合并前,需要成功构建并运行 tRPC-Cpp 主干代码,这不仅验证环境搭建正确,也为后续应用补丁提供基础。
1. 开发环境准备:确保系统满足开发需求。使用 Linux (Ubuntu 20.04) 环境,这也是官方主要支持的环境。准备工作包括:
安装 Bazel:tRPC-Cpp 使用 Bazel 构建。
安装 JDK:Bazel 需要 Java 环境。安装 OpenJDK 8 或 11 均可。确保运行
bazel时java可用。安装 C++编译工具链:安装
GCC/G++等基本编译器工具,以及 CMake 等。安装项目依赖库:tRPC-Cpp 架构依赖若干 C++ 库。在构建源码前,应确保以下库在系统中可用或提前安装:
Protobuf:用于序列化RPC消息,需安装
protoc编译器和相应的libprotobuf库。gflags:命令行参数解析库,tRPC 使用其定义和解析全局标志。
fmtlib:格式化输出库,用于日志打印等。
其他依赖如 OpenSSL(若使用 SSL 通信)、absl 库等。
这些库可以通过系统包管理器安装,例如在 Ubuntu 上:
sudo apt-get install -y protobuf-compiler libprotobuf-dev libgflags-dev libfmt-dev libssl-dev2. 获取主干代码:从 GitHub 克隆 tRPC-Cpp 仓库主干分支源码:
git clone https://github.com/trpc-group/trpc-cpp.gitcd trpc-cpp3. 编译项目:tRPC-Cpp 提供了构建脚本,根据https://github.com/trpc-group/trpc-cpp/blob/main/docs/en/setup_env.md,首选 Bazel 构建:在项目根目录:
./run_examples.sh4. 运行示例验证:为了确认构建的二进制正常运行,脚本
./run_examples.sh除了一键编译,还会运行所有示例,观察示例输出验证框架功能。通过以上步骤,确认主干分支的代码能够在本地成功构建和运行,为后续合并补丁打下了基础。
编译过程中遇到的问题与解决
根据 bazel 的报错信息:
undefined reference to 'SSL_...'表明:#include <openssl/ssl.h>),libssl.so和libcrypto.so)。tRPC-Cpp 的 SSL 模块需要显式声明对 OpenSSL 的依赖。从错误看,Bazel 在构建目标时未自动链接 OpenSSL。
排查
third_party/com_github_openssl_openssl/openssl.BUILD文件中,显式添加 OpenSSL 依赖trpc/transport/common/ssl/BUILD文件中的依赖引用正确的目标名称修改 OpenSSL BUILD 文件
打开
third_party/com_github_openssl_openssl/openssl.BUILD文件,将目标名称从libssl和libcrypto改为ssl和crypto:更新 SSL BUILD 文件中的依赖
确保
trpc/transport/common/ssl/BUILD文件中的依赖引用正确的目标名称:检查 WORKSPACE 配置
确保 WORKSPACE 文件中正确引用了 OpenSSL 仓库:
总结
通过以上修改,Bazel 正确找到了 OpenSSL 目标并解决了链接问题,编译运行example成功。
通过以上步骤,确认了主干分支的代码能够在本地成功构建和运行,为后续合并补丁打下了基础。
tRPC-Cpp 广播调用功能落地实录
目录
1. 分析需求
2. 分析 patch 文件
rpc_service_proxy.h/cc:新增广播接口service_proxy.h/cc:辅助方法BUILD:新增依赖3. 分析项目结构
理解顺序:
接口层 (RpcServiceProxy) → 基类 (ServiceProxy) → 运行时 (future / coroutine) → 传输层 (transport)
4. 框架代码的修改
4.1 新增广播接口(声明)
4.2 同步广播核心实现(Fiber + Future 双模式)
4.3 异步广播实现(WhenAll 聚合)
4.4 辅助函数实现(路由信息 + 子 Context)
4.5 BUILD 依赖补齐
5. 开发过程中涉及的基础知识
std::tuple、std::any、智能指针cc_library / cc_binary / deps写法6. 开发中遇到的问题 & 解决手段
corrupt patch at line 30future_utility.h: No such file'TrpcSelectorInfo' has not been declared#include "trpc/naming/common/common_defs.h"SetIp不存在SetAddr(host, port)TrpcNaming未声明trpc::naming::SelectBatchinvalid initialization of referenceSelectBatch(selector, ...)传引用而非指针std::any冲突7. 编译了哪些关键文件 & 配置改了什么
trpc/client/BUILD:新增 4 条依赖BUILD:exports_files(["test_broadcast.cc"])test_broadcast.cc8. 运行示例 & 功能验证
8.1 示例代码
8.2 编译 & 运行
$ bazel run //trpc/client:broadcast_test Testing broadcast call functionality... Broadcast call interface is available and compiles successfully! This means the broadcast functionality has been successfully integrated.8.3 正确性证明思路
rsp.size()==39. 项目仍存在的问题
当前广播功能 / 框架 仍存在的问题
trpc_cpp_plugin仍只为单播 RPC 生成代码;用户需手写Broadcast*Invoke调用gen_hdr.cc / gen_src.cc,在每个 RPC Stub 处自动生成三种广播接口;避免人工漏写/写错模板参数Matcher与std::any模板推导冲突导致service_proxy_test编译失败#define GTEST_SKIP_(...)规避2、将
std::any换成自定义AnySetCalleeSetName / SetNamespace等过期接口wrk+ 自写 echo-server,分别测单播 vs 广播吞吐 & 延迟;关注 Fiber 版本的 CPU 利用率vector<EndpointResult>{code,msg,endpoint};便于上层 UI / 日志解析BroadcastStreamInvoke:一次性建多个 stream,WhenAny 聚合 Reader/WriterProxyStatistics中新增广播维度指标:broadcast_success_total,broadcast_fail_total,broadcast_avg_latency_msClientContext、循环设置超时BroadcastContextBuilder().timeout(1000).func("echo")减少样板代码NoncontiguousBuffer;响应合并时按需复制SetClientContextForBroadcast时生成 子 Span,并在返回时汇聚redis_service_proxy_test仍未通过helloworld服务- 写脚本校验
rsp.size()==3、内容一致- 引入 CI 工作流
阶段性目标(可做 Issue 拆分)
10. 任务体验后的收获
当我第一次看到这个 tRPC-Cpp 广播调用的任务时,内心既兴奋又忐忑。作为一个还在学习 C++ 的大学生,能够参与腾讯这样的顶级开源项目,对我来说是一次难得的机会。现在回想整个开发过程,内心充满了感激。
这次项目让我真正理解了什么是"企业级代码"。以前在学校写的都是小打小闹的练习,但这次接触到的 tRPC-Cpp 框架,让我看到了真正的工程化代码应该是什么样子。
通过看到
BroadcastUnaryInvoke这样的泛型接口设计,了解了模板编程的深度应用。我才明白为什么 C++ 被称为"零成本抽象"的语言。每个模板参数都经过精心设计,既保证了类型安全,又提供了极致的性能。Fiber 协程和 Future 异步编程,这种并发编程的实际应用实践让我受益匪浅。这两种并发模型的选择让我理解了不同场景下的最优解。特别是看到
FiberLatch和WhenAll这样的并发原语,我才真正体会到现代 C++ 并发编程的优雅。网络编程很复杂,服务发现、负载均衡、错误处理,这些概念在书本上看起来很简单,但真正实现起来需要考虑的细节之多,让我对网络编程有了更深的理解。
工程实践的重要一课
版本控制的重要性在这次项目中体现得淋漓尽致。从最初的 patch 应用失败,到手动逐文件修改,再到最终的正确提交,每一步都让我学会了如何更好地使用 Git。特别是 Fork + PR 的工作流程,让我理解了开源协作的标准模式。
要构建一个系统很复杂。Bazel 这样的现代构建工具,虽然学习曲线陡峭,但一旦掌握,就能体会到它的强大。依赖管理、编译优化、测试集成,每一个环节都体现了工程化的重要性。
我的问题排查的能力在这次项目中得到了极大提升。从编译错误到链接失败,从 API 不匹配到命名空间问题,每一个问题的解决都让我学会了如何系统地分析和解决问题。特别是学会了从错误信息中快速定位问题根源的能力。
感受开源生态的温暖
在整个开发过程中,我深深感受到了开源社区的温暖。虽然我没有直接与项目维护者交流,但通过阅读代码注释、查看文档、分析错误信息,我感受到了无数开源贡献者的智慧和付出。
代码质量的标准让我震撼。tRPC-Cpp 的每一行代码都经过精心设计,注释详尽,接口清晰。这种对代码质量的追求,让我明白了什么是真正的专业精神。
文档的重要性也让我有了新的认识。从 README 到 API 文档,从示例代码到测试用例,每一个细节都体现了开源项目的用心。这让我明白了,好的代码不仅要能运行,更要能让别人理解和维护。
对未来的思考
这次经历让我对未来的职业发展有了更清晰的认识。持续学习的重要性在这次项目中体现地更直白了。从 C++ 基础到高级特性,从网络编程到并发编程,从版本控制到构建系统,每一个知识点都需要不断学习和实践。
开源贡献的价值。对一个心怀理想的开发者来说,不仅仅是技术能力的提升,更重要的是参与到一个更大的生态系统中,为开源世界贡献自己的力量。这种成就感是任何课堂学习都无法替代的。
深深的感激
特别感谢腾讯开源团队,感谢他们提供了这样宝贵的学习机会。通过参与真实的开源项目,我不仅提升了技术能力,更重要的是培养了工程思维和开源精神。
感谢 tRPC-Cpp 项目的所有贡献者,感谢他们构建了这样一个优秀的框架。通过阅读他们的代码,我学到了太多书本上学不到的知识。
感谢整个开源开发者生态,感谢所有为开源事业默默付出的开发者们。正是有了你们的贡献,才有了今天繁荣的开源世界,才有了我们这些后来者学习和成长的机会。