OpenRTB 协议实战:程序化广告的通信语言
在程序化广告生态中,DSP(需求方平台)、ADX(广告交易平台) 与 SSP(供应方平台) 之间的实时通信是整个竞价链路的核心。而这套通信机制的基础,正是 OpenRTB 协议。
本文将从协议结构、关键字段、实际案例三个维度,帮你快速掌握 OpenRTB 的核心要点。
一、为什么需要 OpenRTB?
传统广告投放依赖人工操作,效率低、粒度粗。而程序化广告追求 毫秒级响应、实时竞价、精准定向,必须有一套标准化的数据交换格式。
OpenRTB(Real-Time Bidding)由 IAB(Interactive Advertising Bureau) 主导制定,目前主流版本是 OpenRTB 2.5。
核心价值:
- 统一数据格式,降低对接成本
- 支持实时竞价,毫秒级响应
- 丰富的扩展字段,满足业务定制化需求
二、协议结构一览
一次完整的竞价流程涉及两个核心请求:
1. Bid Request(出价请求)— ADX → DSP
这是 ADX 向 DSP 发送的"竞价邀请",包含广告位信息、用户特征、投放限制等。
{
"id": "abc123-uuid",
"tmax": 120,
"device": {
"ua": "Mozilla/5.0...",
"ip": "203.0.113.42",
"geo": {
"country": "CHN",
"city": "Dalian"
}
},
"user": {
"id": "user_xyz789",
"data": [{
"segment": [{"id": "interest_tech"}]
}]
},
"imp": [{
"id": "1",
"bidfloor": 0.5,
"banner": {
"w": 300,
"h": 250,
"mimes": ["image/jpeg", "image/png"]
}
}],
"site": {
"id": "site_001",
"name": "News Portal",
"publisher": {"id": "pub_123"}
}
}
关键字段解读:
- <code>id</code>: 唯一请求标识,用于关联后续响应
- <code>tmax</code>: 超时时间(毫秒),DSP 必须在此时限内返回响应
- <code>device</code>: 设备信息(UA、IP、地理位置),用于用户定向
- <code>imp</code>: 广告展示请求列表,每个 <code>imp</code> 代表一个广告位
- <code>bidfloor</code>: 最低出价(CPM)
2. Bid Response(出价响应)— DSP → ADX
DSP 收到请求后,经过竞价决策,返回出价结果。
{
"id": "abc123-uuid",
"seatbid": [{
"bid": [{
"id": "bid_001",
"impid": "1",
"price": 1.25,
"adm": "<html><img src=https://ad.example.com/creative.jpg/></html>",
"crid": "creative_888",
"nurl": "https://dsp.example.com/win?price=${AUCTION_PRICE}"
}]
}],
"bidid": "bid_response_001"
}
关键字段解读:
- <code>seatbid</code>: 出价席位列表
- <code>price</code>: 出价金额(CPM)
- <code>adm</code>: 广告物料(HTML、图片、VAST 等)
- <code>crid</code>: 创意 ID,用于素材追踪
- <code>nurl</code>: 竞价获胜通知地址,<code>${AUCTION_PRICE}</code> 会被替换为实际成交价
三、实战:竞价超时处理
在 RTB 项目中,超时控制是性能优化的关键。
根据行业实践和 MEMORY.md 中记录的约束要求:
- Bid Request 处理 < 30ms
- Redis 读写 < 5ms
超时处理代码示例(C#):
public async Task<BidResponse> HandleBidRequestAsync(BidRequest request, CancellationToken ct)
{
// 创建超时任务
var timeoutTask = Task.Delay(25, ct); // 预留 5ms 余量
// 并行执行竞价逻辑
var biddingTask = ExecuteBiddingAsync(request, ct);
// 任一任务完成即返回
var completedTask = await Task.WhenAny(biddingTask, timeoutTask);
if (completedTask == timeoutTask)
{
// 超时,返回默认响应或空响应
_logger.LogWarning("Bid request {RequestId} timed out", request.Id);
return CreateDefaultResponse(request.Id);
}
return await biddingTask;
}
Redis 缓存优化策略:
public async Task<UserProfile> GetUserProfileAsync(string userId)
{
var cacheKey = $"user:{userId}";
// 先查 Redis(目标 < 5ms)
var cached = await _redisDatabase.StringGetAsync(cacheKey);
if (cached.HasValue)
{
return JsonSerializer.Deserialize<UserProfile>(cached);
}
// 缓存未命中,查 DB 后回填
var profile = await _repository.GetUserProfileAsync(userId);
// 异步回写缓存
_ = _redisDatabase.StringSetAsync(cacheKey,
JsonSerializer.Serialize(profile),
TimeSpan.FromMinutes(5));
return profile;
}
四、注意事项
- 协议版本兼容性:不同 ADX 可能使用不同版本的 OpenRTB,需做好版本适配层
- 安全传输:生产环境必须使用 HTTPS/TLS,防止请求被篡改
- 日志脱敏:用户 IP、设备 ID 等敏感信息在日志中需脱敏处理
- 幂等性:ID 生成和请求处理需保证幂等,避免重复计费
五、总结
OpenRTB 是程序化广告的"通用语言",掌握其协议结构和实战用法,是开发 DSP/ADX 系统的基础。建议结合实际项目(如 Google Authorized Buyers、OpenRTB 规范文档)深入学习。
参考来源:
- IAB OpenRTB 2.5 Specification
- Google Authorized Buyers API Documentation
关注我,获取更多 RTB 实战经验与 .NET 性能优化技巧。