OpenClaw广告系统整体架构深度解析
OpenClaw是一套完整的程序化广告系统,覆盖广告请求、竞价、定向、展示、计费、报表全链路。本文从架构层面拆解每个模块,帮助你真正理解一个广告系统是如何运转的。
一、整体架构分层
OpenClaw采用分层微服务架构,大致分为接入层、业务层、数据层三层:
# OpenClaw 系统架构示意
#
# ┌────────────────────────────────────────────────────┐
# │ 接入层 (Access Layer) │
# │ Mobile SDK / Web SDK / API Gateway / CDN │
# └───────────────────┬────────────────────────────────┘
# │ 广告请求 (Ad Request)
# ┌───────────────────▼────────────────────────────────┐
# │ 业务层 (Business Layer) │
# │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
# │ │ 竞价引擎 │ │ 定向引擎 │ │ 频控/Pacing引擎 │ │
# │ └──────────┘ └──────────┘ └──────────────────┘ │
# │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
# │ │ 反作弊 │ │ 素材管理 │ │ 计费/结算服务 │ │
# │ └──────────┘ └──────────┘ └──────────────────┘ │
# └───────────────────┬────────────────────────────────┘
# │
# ┌───────────────────▼────────────────────────────────┐
# │ 数据层 (Data Layer) │
# │ MySQL(元数据) Redis(缓存/频控) Kafka(事件流) │
# │ ClickHouse(OLAP报表) OSS(素材存储) │
# └────────────────────────────────────────────────────┘
二、一次广告请求的完整生命周期
从用户打开App到看到广告,一次请求经历了哪些步骤?整个过程必须在 100ms 内完成,否则广告位会超时降级到兜底广告。
# 完整请求链路时序
#
# T=0ms App SDK 触发广告请求
# 请求体: {app_id, unit_id, device_id, ip, ua, geo, user_id}
#
# T=5ms API Gateway 鉴权+限流
# - 校验 app_id 合法性
# - 检查 QPS 是否超限
# - 附加设备画像数据
#
# T=10ms 定向引擎 过滤候选广告
# - 地域定向: geo in ['华南', '华东']
# - 设备定向: os=='Android' AND os_version>=10
# - 人群定向: user_tag intersect ['购物达人', '游戏玩家']
# 过滤后: 10000条广告 -> 50条候选
#
# T=20ms 频控引擎 去重
# - 查询 Redis: user:{user_id}:ad:{ad_id} 24h内已展示次数
# - 超频的广告从候选列表移除
#
# T=30ms 竞价引擎 排序
# - 计算每个候选广告的 eCPM
# - eCPM = bid_price * pCTR * quality_score
# - 取 Top3 参与最终竞价
#
# T=50ms 反作弊 黑名单检测
# - IP黑名单 / 设备黑名单 / 异常UA
#
# T=60ms 返回广告创意
# - 素材URL, 点击URL, 曝光监测URL
#
# T=100ms SDK 渲染广告
三、竞价引擎核心算法
def rank_ads(candidates, context):
"""
广告排序引擎
candidates: 候选广告列表
context: 请求上下文 (用户画像, 广告位信息)
"""
scored = []
for ad in candidates:
# CTR预测 (简化版逻辑回归)
pctr = predict_ctr(ad, context)
# 质量得分 (素材质量 + 落地页质量 + 历史表现)
quality = (ad.material_score * 0.3 +
ad.landing_score * 0.3 +
ad.historical_ctr * 0.4)
# eCPM排序分
ecpm = ad.bid_price * pctr * quality * 1000
scored.append((ecpm, ad))
# 按eCPM降序排列,取第一名展示
scored.sort(key=lambda x: x[0], reverse=True)
if not scored:
return None, 0
winner_ecpm, winner_ad = scored[0]
# GSP二价计费: 实际扣费 = 第二名eCPM / winner的pCTR / quality
if len(scored) >= 2:
second_ecpm = scored[1][0]
actual_price = second_ecpm / (predict_ctr(winner_ad, context) * 1.0) + 0.01
else:
actual_price = winner_ad.floor_price # 无竞争时按底价计费
return winner_ad, actual_price
四、高可用架构:关键组件的容灾设计
| 组件 | 高可用方案 | 故障处理 | 影响范围 |
|---|---|---|---|
| API Gateway | 多实例+Nginx负载均衡 | 节点摘除,流量转移 | 全系统入口 |
| 竞价引擎 | 无状态服务,水平扩展 | K8s自动重启 | 计算层 |
| Redis(频控) | 主从+哨兵/集群模式 | 降级跳过频控 | 频控功能 |
| MySQL(元数据) | 主从复制+自动切换 | 切从库只读模式 | 广告配置读取 |
| Kafka(日志) | 多分区多副本 | 消费者自动rebalance | 计费/报表 |
五、性能调优:OpenClaw生产环境核心配置
# openclaw.yaml - 生产环境推荐配置
server:
worker_threads: 32 # CPU核数 * 2
connection_timeout_ms: 80 # 广告请求超时,留20ms给渲染
max_connections: 10000
bidding_engine:
candidate_limit: 100 # 最多100个候选广告参与竞价
timeout_ms: 30 # 竞价计算超时
ctr_model: 'lightgbm' # CTR预测模型
cache:
ad_ttl_seconds: 300 # 广告缓存5分钟
user_profile_ttl: 3600 # 用户画像缓存1小时
hot_ad_preload: true # 热门广告预热到本地缓存
fraud_detection:
mode: 'async' # 异步检测,不阻塞主链路
ip_limit_per_hour: 20
device_limit_per_hour: 10
总结:OpenClaw的架构核心思想是高吞吐低延迟——竞价链路全程无阻塞IO,热数据全部在Redis,冷数据异步加载。理解这个架构,你就能在运维和二次开发时做出更好的决策。
