OpenRTB 协议实战:程序化广告的通信语言

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;
}

四、注意事项

  1. 协议版本兼容性:不同 ADX 可能使用不同版本的 OpenRTB,需做好版本适配层
  2. 安全传输:生产环境必须使用 HTTPS/TLS,防止请求被篡改
  3. 日志脱敏:用户 IP、设备 ID 等敏感信息在日志中需脱敏处理
  4. 幂等性:ID 生成和请求处理需保证幂等,避免重复计费

五、总结

OpenRTB 是程序化广告的"通用语言",掌握其协议结构和实战用法,是开发 DSP/ADX 系统的基础。建议结合实际项目(如 Google Authorized Buyers、OpenRTB 规范文档)深入学习。


参考来源:

  • IAB OpenRTB 2.5 Specification
  • Google Authorized Buyers API Documentation

关注我,获取更多 RTB 实战经验与 .NET 性能优化技巧。