BRPC中的备份请求机制详解
brpc 项目地址: https://gitcode.com/gh_mirrors/br/brpc
什么是备份请求
备份请求(Backup Request)是一种提高系统可用性和降低延迟的技术手段。其核心思想是:当客户端向服务端发起请求时,如果在预设时间内没有收到响应,则自动向另一个服务实例发送相同的请求,最终取最先返回的结果。
这种机制特别适合对延迟敏感且需要高可用的场景,比如推荐系统、广告系统等在线服务。
BRPC中的备份请求实现方式
在BRPC框架中,提供了两种主要的备份请求实现方式:
1. 使用Channel的备份请求功能
当后端服务可以挂载在同一个命名服务内时,这是最推荐的方式。具体实现步骤如下:
- 创建Channel时设置
backup_request_ms
参数 - BRPC会自动管理请求流程:
- 先向一个服务实例发送请求
- 如果超过
backup_request_ms
时间未响应 - 向另一个服务实例发送相同请求
- 取最先返回的结果
这种方式的优势在于:
- 大部分情况下只会发送一个请求
- 只在超时情况下才会发送备份请求
- 对后端服务的压力通常只有一倍
2. 使用SelectiveChannel
当后端服务不能挂载在同一个命名服务内时(例如跨集群部署),可以使用SelectiveChannel:
- 创建一个SelectiveChannel
- 添加多个sub channel(每个对应不同的服务集群)
- 设置
backup_request_ms
参数 - BRPC会自动管理跨集群的备份请求
这种方式特别适合多集群互备的场景,可以在不同集群间实现请求的自动切换。
如何设置合理的backup_request_ms
backup_request_ms
参数的设置非常关键,设置过小会导致过多不必要的备份请求,设置过大则失去了备份请求的意义。建议通过以下方法确定合理值:
- 观察服务的延迟分布(CDF图)
- 选择一个能覆盖大部分请求的阈值
- 例如设置2ms可能覆盖95%的请求
- 设置10ms可能覆盖99.99%的请求
在BRPC中可以通过内置的latency_cdf图来观察延迟分布,也可以自定义延迟统计:
#include <bvar/bvar.h>
#include <butil/time.h>
// 创建延迟统计器
bvar::LatencyRecorder api_latency("api");
// 在请求处理代码中
butil::Timer tm;
tm.start();
process_request(); // 处理请求
tm.stop();
api_latency << tm.u_elapsed(); // 记录微秒级延迟
不推荐的实现方式
有些开发者可能会尝试通过发起两个异步RPC然后Join的方式实现类似效果,但这种做法存在明显问题:
- 总是会发送两个请求
- 对后端服务造成双倍压力
- 资源利用率低下
除非有特殊需求,否则应该优先使用BRPC内置的备份请求机制。
实际应用示例
假设我们有一个推荐服务,要求99%的请求延迟在10ms以内。我们可以这样配置:
brpc::ChannelOptions options;
options.backup_request_ms = 5; // 5毫秒后触发备份请求
brpc::Channel channel;
if (channel.Init("service_name", &options) != 0) {
// 处理初始化失败
}
通过监控发现,5ms的阈值可以覆盖约98%的请求,同时备份请求比例控制在2%左右,既保证了低延迟,又不会给后端带来过大压力。
总结
BRPC的备份请求机制是提高服务可用性和降低延迟的有效手段。合理配置后,可以在不明显增加后端压力的情况下,显著改善服务质量。关键点在于:
- 根据场景选择合适的实现方式
- 基于实际延迟数据设置合理的超时阈值
- 持续监控和调整参数
通过这种方式,开发者可以轻松构建高可用、低延迟的分布式服务。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考