RTB工作机制

RTB竞价流程

严格来说,广告请求的流转路径可以有两种模式:

  1. SSP → DSP(直连模式)
    • SSP(供应方平台)直接向多个 DSP 发送广告请求,让 DSP 参与竞价。
    • 这种模式减少了中间环节,提高了效率,但可能缺乏灵活性。
  2. SSP → Ad Exchange → DSP(典型的 RTB 竞价流程)
    • SSP 先把广告请求发送给 Ad Exchange(广告交易市场)。
    • Ad Exchange 再将广告请求广播给多个 DSP,由 DSP 进行出价。
    • Ad Exchange 充当一个中介,统一管理竞价逻辑,决定最终中标者

目前,大多数 RTB 竞价采用 SSP → Ad Exchange → DSP 这种 中介交易市场 模式。

流程细化

  • SSP(Supply-Side Platform,供应方平台):代表媒体(Publisher),管理广告位资源,并将广告请求发给 Ad Exchange
  • Ad Exchange(广告交易平台):汇总多个 SSP 的广告请求,统一发送给 多个 DSP 进行竞价。
  • DSP(Demand-Side Platform,需求方平台):代表广告主(Advertiser),对广告请求进行评估,并提交出价(Bid)。
  • Ad Exchange 选出最高出价的广告,并返回给 SSP,最终在 Publisher 端展示广告

为什么引入 Ad Exchange?

  1. 统一管理多个 SSP 的广告资源,提升广告填充率(Fill Rate)。
  2. 公平竞价,让多个 DSP 竞争,提高广告收益。
  3. 数据汇总与隐私保护,防止 DSP 直接获取 Publisher 详细信息。

总结

Ad Exchange 负责向多个 DSP 发送广告请求,并从 DSP 收集出价,最终决定哪个广告展示。
SSP 负责连接媒体方,并将广告请求发给 Ad Exchange,有时也会直接对接 DSP。
✅ 目前主流 RTB 竞价采用 SSP → Ad Exchange → DSP 模式。

RTB(实时竞价)广告投放流程

完整的 RTB 广告竞价流程

  1. 用户访问媒体方(Publisher)
    • 用户打开一个 网站、APP、视频流媒体,页面或 APP 触发广告加载逻辑。
  2. 媒体方(Publisher)向 SSP 发送广告请求
    • Publisher 通过 HTTP API / JavaScript / SDKSSP(供应方平台) 发送广告请求。
    • 请求内容包括:
      • 广告位信息(尺寸、位置)
      • 用户信息(IP、Cookie ID、设备 ID、地理位置等)
      • 网站/APP 信息(域名、分类等)
      • 曝光环境(是否全屏、设备类型等)
  3. SSP 处理请求,并决定如何竞价
    • 流量筛选:去除无效流量(如机器人流量、作弊流量)。
    • 用户匹配:可能使用 DMP(数据管理平台)补充用户画像信息。
    • 发送广告请求到 Ad Exchange 或 直接给多个 DSP(视 SSP 设计而定)。
  4. Ad Exchange(广告交易平台)负责竞价
    • Ad Exchange 广播广告请求给多个 DSP(需求方平台)。
    • 各 DSP 进行竞价,算法会基于 用户画像、广告主预算、CTR/CVR 预估等 计算出价。
  5. DSP 竞价并返回出价结果
    • DSP 计算出最优出价(Bid Price),并返回广告创意(HTML/JS/视频)。
  6. Ad Exchange 选择最高出价者
    • Ad Exchange 选择出价最高的 DSP 作为获胜方,并将广告素材返回 SSP。
  7. SSP 决定最终展示
    • SSP 可能对 DSP 的广告进行 过滤或调整(如品牌安全、内容审核)。
    • 最终广告素材返回给 Publisher
  8. Publisher 展示广告给用户
    • 用户最终看到广告(Banner、视频、原生广告等)。

SSP 到底有没有转发广告请求给 Ad Exchange?

一般情况下:

  • SSP 并不会直接竞价,而是将请求发送到 Ad Exchange
  • Ad Exchange 负责广播请求,DSP 进行竞价
  • SSP 主要负责流量管理、数据增强、筛选无效流量

特殊情况:

  • 部分 SSP 也可以充当 Ad Exchange,直接连接 DSP 进行竞价(如 Google Ad Manager)。
  • 某些 SSP 可能会直接连接部分 DSP,绕过 Ad Exchange(通常是大型 SSP)。

总结

步骤 组件 作用
1 用户 访问媒体方(Publisher)
2 Publisher 发送广告请求给 SSP
3 SSP(供应方平台) 处理流量,决定是否进入竞价
4 Ad Exchange(广告交易平台) 发送广告请求到多个 DSP
5 DSP(需求方平台) 计算出价并返回广告素材
6 Ad Exchange 选择最高出价的 DSP
7 SSP 最终决定是否展示广告
8 Publisher 展示广告给用户

如果是 Java 开发,通常会涉及

  • SSP/Ad Exchange 服务端开发(Spring Boot + Kafka + Redis + MySQL)。
  • 竞价算法优化(CTR 预估、CVR 预估、动态定价)。
  • 高并发处理(QPS 高,需用 Kafka、Redis 做缓存)。
  • 日志分析 & 数据处理(Druid、ClickHouse 分析竞价数据)。

SSP 不会主动向 Ad Exchange 发送请求,必须依赖用户访问媒体方(Publisher)来触发。

详细解析

  1. 用户访问媒体方(Publisher)
    • 例如,用户打开某个新闻网站或 App,触发广告加载。
    • 该页面上可能有多个广告位(Banner、插屏、视频等)。
  2. 媒体方(Publisher)请求 SSP
    • 媒体方的广告 SDK 或 JavaScript 代码会向 SSP(供应方平台) 发送广告请求。
    • 请求内容包括 广告位信息、用户信息、环境信息等
  3. SSP 处理后向 Ad Exchange 发送请求
    • SSP 并不会自己主动给 Ad Exchange 发送请求,而是 在收到 Publisher 请求后,才决定是否把流量提交给 Ad Exchange 进行竞价。
    • 如果是私有交易(PMP),SSP 可能直接给特定 DSP 发请求,而不是走 Ad Exchange
  4. Ad Exchange 转发请求给多个 DSP 进行竞价
    • Ad Exchange 再向多个 DSP(需求方平台) 发送广告请求,DSP 计算出价后返回,最终由 Ad Exchange 选择最高出价者

总结

  • SSP 不会无缘无故地主动给 Ad Exchange 发请求
  • 只有当用户访问 Publisher,触发广告请求时,SSP 才会决定是否将流量发送给 Ad Exchange 或 DSP
  • Ad Exchange 负责把 SSP 提供的广告请求广播给多个 DSP 进行竞价

RTB 和 Header Bidding

Header Bidding 和 RTB 的关系可以理解为:Header Bidding 负责并行多个平台的竞价,而 RTB 是在每个并行平台内部进行的竞价流程。

1. Header Bidding:跨多个广告平台并行竞价

  • 发生阶段:在广告请求进入广告服务器(Ad Server)之前,由 Publisher(媒体方)触发。
  • 工作方式
    1. Publisher 通过浏览器端(如 Prebid.js)或服务器端(如 Prebid Server)向多个 SSP/DSP 并行发送竞价请求
    2. 每个 SSP/DSP 内部启动 RTB 竞价(即 SSP 向多个 DSP 请求出价)。
    3. 各 SSP/DSP 返回最高出价给 Header Bidding 逻辑,并提交给 Ad Server(如 Google Ad Manager)。

2. RTB:每个并行 SSP/DSP 内部的竞价流程

  • 发生阶段:在 Header Bidding 触发请求后,每个 SSP 内部通过 RTB 竞价选出最优广告。
  • 工作方式
    1. SSP 收到 Header Bidding 发送的广告请求,并通过 Ad Exchange 向多个 DSP 发起 RTB 竞价请求。
    2. 各 DSP 分析用户画像、投放策略、预算,决定是否出价,并返回最高的竞价结果
    3. SSP 在收到多个 DSP 的报价后,选择出价最高的 DSP 竞价广告,并返回 Header Bidding 逻辑。

3. Header Bidding vs. RTB 的关系

可以用下面的图示来理解:

┌──────────────┐
│  Publisher   │  → 向多个 SSP/DSP 并行发送 Header Bidding 请求
└──────────────┘
         ↓  
┌──────────────────────────────────────────┐
│   Header Bidding(多个 SSP 并行竞价)     │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐      │
│ │  SSP A  │ │  SSP B  │ │  SSP C  │  ... │
│ └─────────┘ └─────────┘ └─────────┘      │
└──────────────────────────────────────────┘
         ↓  
每个 SSP 内部进行 RTB 竞价:
         ↓  
┌───────────┐    ┌───────────┐    ┌───────────┐
│  DSP A1   │    │  DSP B1   │    │  DSP C1   │
│  DSP A2   │    │  DSP B2   │    │  DSP C2   │
│  DSP A3   │    │  DSP B3   │    │  DSP C3   │
└───────────┘    └───────────┘    └───────────┘
         ↓  
每个 SSP 选择一个最高出价后返回给 Header Bidding,再由广告服务器决定最终展示

4. 关键区别

对比项 Header Bidding RTB(每个 SSP 内部的流程)
触发方 Publisher(媒体方) SSP(供应方平台)
作用范围 多个 SSP 并行竞价 单个 SSP 内部的 RTB 竞价
竞价流程 Publisher 直接向多个 SSP/DSP 并行发送竞价请求 SSP 内部向多个 DSP 发起 RTB 竞价
竞价方式 所有 SSP 公开竞争 每个 SSP 选择最高 DSP 出价
优点 并行竞价,最大化收益 DSP 竞价更精准

5. 总结

Header Bidding 负责让多个 SSP 竞争,RTB 负责每个 SSP 内部的 DSP 竞价。
Header Bidding 让所有 SSP 并行竞价,而 RTB 是 SSP 内部的流程。
最终广告展示取决于 Header Bidding 最高出价 和 广告服务器内部的 RTB 竞价结果的比较。

publisher 向 SSP 发送请求

在大型互联网平台的广告营销业务中,Publisher(媒体)SSP(Supply-Side Platform,供应方平台) 发送广告请求的方式主要有以下几种:

1. 直接请求(S2S Server-to-Server 请求)

流程:
Publisher 的服务器直接向 SSP 发送 HTTP 请求(通常是 POST 请求),请求返回合适的广告素材。

请求方式:

  • HTTP API(RESTful API 或 gRPC)
  • WebSocket(少见)

请求入参:

  • 媒体信息(Publisher 信息,如 site_idapp_id
  • 广告位信息ad_unit_id,广告尺寸 width/height,支持的广告类型 banner/video/native
  • 用户信息(用户 ID user_id,IP ip,Cookie/Device ID)
  • 设备信息(设备类型 device_type,操作系统 os,浏览器 browser,屏幕分辨率 screen_size
  • 地理位置(GPS lat/lon 或 IP 解析地址)
  • 用户行为数据(历史点击、浏览记录)
  • GDPR/CCPA 合规信息(用户隐私偏好)
  • 竞价方式(是否支持 Header Bidding,期望的最低 CPM)

2. 浏览器/APP 端请求(Client-Side 请求)

流程:
用户访问 Publisher 网站或 APP,浏览器/APP 直接向 SSP 发送广告请求。

请求方式:

  • HTTP GET/POST 请求(一般用于 Web 端)
  • JavaScript 代码加载广告(JS SDK)
  • APP 通过 SDK 发送请求(Android/iOS)

请求入参:

  • 广告位信息ad_slot_id,广告尺寸,格式)
  • 用户信息(Cookie、Device ID、IP)
  • 设备信息(User-Agent,操作系统,分辨率)
  • 广告上下文(页面 URL,APP 版本,屏幕方向)
  • GDPR/CCPA 隐私参数

3. Header Bidding(前端竞价)

流程:
Publisher 通过 JavaScript 代码(如 Prebid.js)或 APP SDK 并行向多个 SSP 发送竞价请求,并选出最高价广告填充。

请求方式:

  • HTTP POST / GET 请求(通常使用 JSON 格式)
  • WebRTC / WebSocket(部分实时竞价使用)

请求入参:

  • 广告位信息(广告 ID、尺寸、格式)
  • 用户 ID 同步信息(SSP 需要与 DMP 进行 ID Mapping)
  • 用户行为数据(历史点击、转化等)
  • GDPR/CCPA 隐私参数

总结

请求方式 发送者 请求方式 适用场景
S2S 直连 服务器 HTTP POST 大型 Publisher,流量大,减少延迟
Client-Side 浏览器/APP JS、SDK 适用于小型 Publisher,易于部署
Header Bidding 浏览器/APP JS(Prebid.js)、SDK 允许多个 SSP 竞价,提高收益

Publisher(媒体方)和 SSP(供应方平台)的通信方式

Publisher(网站、APP、视频平台等)和 SSP 之间的通信通常通过 HTTP(S) API、SDK 或 JavaScript 代码 实现,主要方式如下:

1. 直接通过 HTTP(S) API 进行广告请求

适用于: 网站、APP、小程序等 无 SDK 集成 的场景
工作方式: Publisher 在页面或 APP 端发起 HTTP(S) 请求,向 SSP 请求广告

示例流程:

  1. 用户访问 Publisher 网站或 APP,触发广告加载逻辑。
  2. Publisher 向 SSP 发送广告请求,通常是 HTTP GET/POST 请求(OpenRTB 格式)。
  3. SSP 接收到请求后,进行流量过滤和用户匹配(DMP 数据、反作弊等)。
  4. SSP 将请求转发给 Ad Exchange 或 DSP 进行 RTB 竞价
  5. 最终选择最高出价的广告并返回广告素材 URL 或代码
  6. Publisher 在前端渲染广告内容(HTML/JS/视频)。

示例 HTTP 广告请求(OpenRTB JSON 格式):

{
  "id": "123456789",
  "site": {
    "id": "example.com",
    "domain": "example.com"
  },
  "device": {
    "ip": "192.168.1.1",
    "ua": "Mozilla/5.0"
  },
  "user": {
    "id": "abc123"
  },
  "imp": [
    {
      "id": "1",
      "banner": {
        "w": 300,
        "h": 250
      }
    }
  ]
}

说明:

  • id:请求 ID
  • site.domain:媒体域名
  • device:用户设备信息(IP、User-Agent)
  • user.id:用户唯一标识(可能是 Cookie ID 或 IDFA/GAID)
  • imp:广告位信息(如 banner 广告的尺寸 300x250)

SSP 返回广告 JSON(OpenRTB Response 格式):

{
  "id": "123456789",
  "seatbid": [
    {
      "bid": [
        {
          "id": "bid123",
          "impid": "1",
          "price": 1.2,
          "adm": ""
        }
      ]
    }
  ]
}

说明:

  • seatbid.bid.price:广告出价(1.2 美元)
  • adm:广告 HTML 代码(可以是图片、视频或 JS 代码)

2. 通过 SSP 提供的 JavaScript 代码加载广告

适用于: 网站、PC 端 Web(如新闻网站、博客)
工作方式: Publisher 在网页中插入 SSP 提供的 JS 代码,由前端异步请求 SSP 获取广告

示例:Publisher 在 HTML 中插入 JS 代码

<script async src="https://ssp.example.com/ad.js?site_id=12345">script>

JS 代码运行后,会向 SSP 发起广告请求(类似 HTTP API 请求,但是在前端进行)。
SSP 返回广告后,JS 代码负责渲染广告位(展示 Banner、视频或原生广告)。

优点

  • 适用于 网页,无需后端修改
  • 可以动态加载广告,提高灵活性
  • 支持 异步加载,不影响网页主内容

缺点

  • 浏览器隐私限制(如 Safari ITP 限制跨站 Cookie)
  • 可能被 AdBlock 屏蔽

3. 通过 SDK 进行广告请求(适用于 APP)

适用于: 移动 APP(iOS、Android)
工作方式: Publisher 在 APP 中集成 SSP 提供的 SDK,SDK 负责发起广告请求

APP 代码示例(Android Java)

AdView adView = new AdView(this);
adView.setAdUnitId("ca-app-pub-3940256099942544/6300978111");
adView.setAdSize(AdSize.BANNER);

AdRequest adRequest = new AdRequest.Builder().build();
adView.loadAd(adRequest);

SDK 负责完成广告请求、竞价、填充广告,Publisher 只需要调用 loadAd()

优点

  • 降低开发复杂度(SDK 直接封装 HTTP 请求)
  • 支持离线缓存,提高广告展示率
  • 支持更多广告形式(视频、原生广告等)

缺点

  • 需要 APP 开发人员集成 SDK
  • 可能增加 APP 体积
  • 需要 定期更新 SDK 以支持新功能

4. 通过 VAST / VPAID 进行视频广告请求

适用于: 视频网站、短视频 APP、直播平台
工作方式: Publisher 通过 VAST(Video Ad Serving Template)或 VPAID(Video Player Ad Interface Definition)标准,从 SSP 获取视频广告 URL,并在播放器中播放

示例:Publisher 请求视频广告 VAST XML

<VAST version="3.0">
    <Ad id="123456">
        <InLine>
            <AdSystem>SSPAdSystem>
            <Creatives>
                <Creative>
                    <Linear>
                        <MediaFiles>
                            <MediaFile type="video/mp4">
                                https://cdn.example.com/video_ad.mp4
                            MediaFile>
                        MediaFiles>
                    Linear>
                Creative>
            Creatives>
        InLine>
    Ad>
VAST>

播放器解析 VAST XML 并播放视频广告

优点

  • 适用于视频网站、直播平台
  • 标准化格式,兼容多个广告平台

缺点

  • 需要 播放器支持 VAST/VPAID
  • 浏览器和 APP 限制(如 iOS 自动播放限制)

总结

通信方式 适用场景 优点 缺点
HTTP API(OpenRTB) 网站、APP、小程序 直接对接 SSP,适用于 RTB 竞价 需要后端开发,延迟较高
JavaScript(前端异步加载) 网站 适合网页,易集成 受浏览器隐私限制,可能被 AdBlock 拦截
SDK(移动端) iOS、Android APP 易于集成,封装完整 需要更新 SDK,占用 APP 体积
VAST/VPAID(视频广告) 视频网站、直播 标准化,兼容性强 需要播放器支持

Java 开发,通常需要实现 HTTP API 方式,处理 OpenRTB 请求和响应。

SSP

SSP(供应方平台)通常采用微服务架构,但它并不是单个微服务,而是一套分布式微服务系统。

SSP 的核心功能:

  • 广告请求接收服务:从媒体(Publisher)或 APP SDK 接收广告请求。
  • 用户数据管理(DMP 集成):管理用户数据、行为数据,并用于广告定向。
  • 流量过滤与反作弊:防止无效流量(IVT)、机器人点击等欺诈行为。
  • 广告竞价管理:将广告请求发送到 Ad Exchange 或直接向多个 DSP 进行 RTB 竞价。
  • 填充率优化:基于历史数据和机器学习优化广告填充率。

微服务拆分方式:
Traffic Manager Service(流量管理服务):接收广告请求,进行基本过滤。
Bid Request Service(竞价请求服务):将请求转发给 Ad Exchange 或 DSP。
Anti-Fraud Service(反作弊服务):分析广告流量是否正常。
Analytics Service(数据分析服务):记录广告投放数据,优化收益。

为什么 SSP 适合微服务架构?

SSP 需要处理 高并发流量请求,并与 多个 Ad Exchange、DSP 交互,需要 低延迟、可扩展、稳定性强,所以通常会拆分为多个微服务。

SSP 微服务架构示例

SSP 主要负责 接收媒体方(Publisher)请求,优化流量,发送给 Ad Exchange 或直接对接 DSP 竞价
可以拆分成如下 微服务组件

微服务 功能 技术栈(Java 相关)
流量接入服务 处理 Publisher 的广告请求(HTTP/gRPC) Spring Boot + Netty
流量过滤与优化 过滤无效流量(IVT)、反作弊 Java + Redis + Elasticsearch
广告竞价分发服务 把广告请求转发给 Ad Exchange / DSP Kafka + Netty
PMP 直销服务 处理 Private Marketplace(私有市场)交易 Spring Boot + MySQL
预算 & 库存管理服务 计算广告位库存、控制广告填充率 ClickHouse + Redis
日志 & 监控服务 记录竞价日志,提供 BI 分析 ELK(Elasticsearch + Logstash + Kibana)
数据分析服务 分析 eCPM、填充率,优化流量分发 Flink / Spark + Druid

SSP 作为微服务架构的优势

  1. 高并发 & 低延迟
    • 需要处理 每秒数百万级别的广告请求(QPS 非常高)。
    • 采用 Netty、Redis、Kafka 等高性能技术优化处理速度。
    • 竞价流程必须 在 100ms 内完成,否则可能失去竞价机会。
  2. 扩展性强
    • 流量高峰时,微服务架构可以 动态扩容,避免系统崩溃。
    • 例如可以使用 Kubernetes 自动扩展 SSP 的广告请求处理服务
  3. 解耦 & 模块化
    • 广告竞价、流量过滤、反作弊、数据分析 独立拆分,不会影响核心请求处理服务。
    • 支持不同的 Ad Exchange / DSP,对接不同的广告交易市场,适配灵活。
  4. 智能优化广告填充
    • 机器学习(ML) 模型可以优化广告填充率,提高 eCPM。
    • Flink / Spark 实时分析竞价数据,帮助优化广告流量分发。

Java 开发 SSP 需要掌握的技术

高性能架构

  • Netty / Spring Boot(处理高并发广告请求)
  • Redis(缓存广告位 & 竞价数据,加速查询)
  • Kafka(处理广告竞价流量,异步提高吞吐量)

流量优化

  • 机器学习(Flink / Spark):优化 eCPM、过滤垃圾流量
  • 反作弊(Elasticsearch + Redis):识别无效流量(IVT),防止广告欺诈

分布式架构

  • Kubernetes / Docker(容器化部署,支持动态扩展)
  • MySQL + ClickHouse(存储竞价日志,优化报表查询)

总结

SSP 不是单个微服务,而是由多个微服务组成的分布式系统。
它的核心职责是优化广告流量,并向 Ad Exchange / DSP 发送竞价请求。
SSP 采用高并发、低延迟的微服务架构,如 Netty + Kafka + Redis + ClickHouse。

需要关注点?

  • 如何优化 SSP 的广告竞价逻辑?
  • 如何实现高并发低延迟的 SSP 系统?
  • 如何优化 SSP 的反作弊 & 流量过滤?

Ad Exchange

Ad Exchange 不是单个微服务,而是一个分布式微服务系统。
Ad Exchange(广告交易平台)负责 接收 SSP 发送的广告请求,并将其转发给多个 DSP 进行竞价,最终选出最高出价的广告展示给用户。
由于 高并发、低延迟、实时竞价 的需求,Ad Exchange 通常采用微服务架构,拆分成多个独立的子系统,以保证高效稳定运行。

Ad Exchange 的核心功能:

  • 广告请求路由(Request Routing):从 SSP 接收广告请求,并广播给多个 DSP。
  • 实时竞价(RTB Auction):计算 DSP 提供的出价,决定最终广告填充。
  • 价格控制与策略管理:支持 二价拍卖(Second-Price Auction)一价拍卖(First-Price Auction)
  • 响应优化:管理广告响应时间,确保在毫秒级别完成竞价。

微服务拆分方式:
Bid Manager Service(竞价管理服务):负责向 DSP 发送竞价请求,并计算出价。
Auction Engine Service(竞价引擎服务):处理 RTB 竞价逻辑,选出最高出价者。
Ad Delivery Service(广告投放服务):处理广告素材返回,确保广告正确展示。
Reporting & Analytics Service(报表与分析服务):记录竞价数据,优化 DSP 竞价策略。

结论:Ad Exchange 也是一个由多个微服务组成的系统,核心是竞价引擎,但其他功能也需要不同微服务支持。

Ad Exchange 典型微服务架构

Ad Exchange 可以拆分为如下 微服务组件

微服务 功能 技术栈(Java 相关)
竞价请求处理服务 解析 SSP 请求,并转发给 DSP Spring Boot + Netty
实时竞价引擎 计算 DSP 竞价结果,选择最高出价 Java + Redis + ClickHouse
广告填充服务 处理未竞价成功的流量(Fallback 广告) Spring Boot + Redis
反作弊 & 质量控制 过滤垃圾流量(IVT)、无效点击 Elasticsearch + Kafka
日志 & 监控服务 记录竞价日志,提供 BI 分析 ELK(Elasticsearch + Logstash + Kibana)
数据分析服务 计算 eCPM、优化 DSP 竞价策略 Flink / Spark + Druid
流量管理 & 频次控制 处理广告展示频次、用户曝光控制 Redis + MySQL

Ad Exchange 为什么适合微服务架构?

  1. 超高并发 & 低延迟
    • 每秒数百万次竞价请求(QPS 非常高),需要低延迟(一般 50ms 内)。
    • 采用 Netty、Redis、Kafka 提高吞吐量,保证高效竞价。
  2. 扩展性强
    • Kubernetes 自动扩容,适应广告流量波动(节假日、热门事件时流量暴增)。
    • 可动态调整 竞价引擎、流量管理、日志分析 等微服务的实例数量。
  3. 解耦 & 易维护
    • 竞价引擎、流量过滤、广告填充 等功能独立部署,互不影响。
    • 支持不同的 SSP、DSP 对接,不影响核心竞价逻辑
  4. 实时优化广告收益
    • 机器学习(ML) 实时分析竞价数据,优化 DSP 竞价策略,提高 eCPM(有效千次展示收益)
    • Flink / Spark 进行流式分析,提升广告填充率,优化 DSP 出价策略。

Java 开发 Ad Exchange 需要掌握的技术

高性能架构

  • Netty / Spring Boot(高并发处理 SSP 请求)
  • Redis / Kafka(竞价缓存 & 实时消息流处理)
  • ClickHouse / MySQL(存储竞价日志,优化查询)

实时竞价 & 机器学习

  • Flink / Spark(流式计算 eCPM / DSP 竞价分析)
  • 机器学习模型优化 DSP 竞价策略(提高 CVR)

分布式 & 容器化

  • Kubernetes / Docker(动态扩展 Ad Exchange 竞价服务)
  • Elasticsearch + Kibana(日志分析 & 反作弊监控)

总结

Ad Exchange 不是单个微服务,而是由多个微服务组成的分布式系统。
它的核心职责是连接 SSP 和 DSP,执行实时竞价,并选择最高出价的广告展示。
采用高并发、低延迟架构,如 Netty + Kafka + Redis + ClickHouse。

需要关注点?

  • 如何优化 Ad Exchange 的实时竞价性能?
  • 如何设计 Ad Exchange 的反作弊系统?
  • 如何优化 DSP 竞价策略,提高广告收益?

DSP

DSP(需求方平台)通常是一个微服务架构的系统,但它并不一定是单个微服务,而是由多个微服务组成的分布式系统。

为什么 DSP 适合微服务架构?

DSP 主要负责广告竞价、投放策略、数据分析等任务,高并发、低延迟,适合拆分为多个微服务。
常见的 DSP 微服务架构 可能包括以下几个核心模块:

微服务 功能 技术栈(Java 相关)
广告请求处理服务 负责接收 Ad Exchange 的广告竞价请求 Spring Boot + Netty
竞价引擎(Bid Engine) 计算出价,决定是否参与竞价 Java + Redis + ClickHouse
用户画像服务(DMP) 结合 DMP(数据管理平台)优化广告投放 Spark/Flink + MongoDB
策略决策服务(Rule Engine) 处理黑名单、品牌安全、预算控制 Drools / 自定义规则引擎
广告素材管理服务 处理广告创意(图片、视频、HTML) MinIO + Redis 缓存
日志与监控服务 记录竞价日志,分析 CTR/CVR ELK(Elasticsearch + Logstash + Kibana)
报表与BI分析 统计广告投放效果 ClickHouse + BI 平台

DSP 作为微服务架构的优势

  1. 高并发
    • DSP 需要在 毫秒级内 计算广告出价,必须 横向扩展 来处理 高 QPS(每秒请求量)
  2. 低延迟
    • RTB(实时竞价)要求 DSP 在 100ms 内 完成竞价,微服务架构可以通过 Redis 缓存、异步处理 来优化性能。
  3. 易扩展
    • DSP 需要不断调整广告投放策略,比如 A/B 测试、机器学习优化 CTR/CVR,微服务架构更容易迭代。
  4. 数据隔离 & 解耦
    • 竞价逻辑用户画像报表分析 可以独立拆分,不会相互影响。

Java 开发 DSP 需要掌握的技术

如果你想开发 DSP 竞价系统的核心微服务,可以关注以下技术:
高性能处理

  • Netty / Spring Boot(高并发请求处理)
  • Redis(缓存竞价数据,优化速度)
  • Kafka(实时数据流处理,如点击/曝光事件上报)

竞价算法优化

  • 机器学习(CTR/CVR 预估)
  • 规则引擎(Drools 竞价策略)
  • 预算控制(动态出价)

数据分析

  • ClickHouse / Druid(广告数据分析)
  • Flink / Spark(用户画像建模)

分布式架构

  • Kubernetes / Docker(部署 DSP 服务)
  • MySQL + MongoDB(存储竞价日志、广告创意)

总结

  • DSP 不是单个微服务,而是一套微服务架构的系统
  • 它需要多个高性能微服务协同工作,如竞价引擎、用户画像、广告素材管理等。
  • RTB 竞价要求极低延迟(100ms 内响应),所以 DSP 通常采用高并发架构,如 Netty + Redis + Kafka + ClickHouse

DMP

在广告营销业务中,SSP、DSP 和 Ad Exchange 这三个核心组件都会用到 DMP(Data Management Platform,数据管理平台),但它们使用 DMP 的方式和目的有所不同。

DMP 在 SSP、DSP、Ad Exchange 中的作用

  1. SSP(供应方平台)使用 DMP
    • 目的:帮助媒体方(Publisher)最大化广告收益,提高广告投放的精准度。
    • 使用方式
      • 分析网站或 APP 用户数据(如行为数据、兴趣、地域信息)。
      • 通过 DMP 的数据来增强用户画像,从而为广告交易提供更优质的用户信息,提高广告库存的价值。
      • 在 RTB 竞价过程中,将 DMP 提供的用户数据打包给 Ad Exchange,让 DSP 竞价时可以参考。
  2. DSP(需求方平台)使用 DMP
    • 目的:帮助广告主找到更精准的目标受众,提高广告的转化率(CVR)。
    • 使用方式
      • 通过 DMP 获取第三方数据(如人口统计、兴趣、历史行为等)来增强广告主已有的第一方数据(自有用户数据)。
      • 进行用户分群(segmentation),使广告投放更加精准。
      • 在 RTB 竞价时,利用 DMP 数据来计算某个用户的 LTV(Lifetime Value)转化可能性,从而决定是否竞价以及出价多少。
  3. Ad Exchange(广告交易平台)使用 DMP
    • 目的:提升广告交易的效率,增强数据匹配能力。
    • 使用方式
      • 通过 DMP 对广告请求进行预处理,提升广告匹配度,使 SSP 和 DSP 之间的数据更好地对接。
      • 提供额外的受众数据,使 DSP 能够更精准地匹配广告。
      • 作为数据桥梁,促进数据共享,提高竞价的精准度和广告展示的相关性。

DMP 的数据来源

DMP 主要通过以下几种方式获取数据:

  • 第一方数据(1st Party Data):广告主或媒体方自己收集的数据,如网站访问数据、用户 CRM 数据、APP 交互数据等。
  • 第二方数据(2nd Party Data):来自合作伙伴的数据,例如 Publisher 与广告主之间共享的数据。
  • 第三方数据(3rd Party Data):来自数据供应商,如 Experian、BlueKai、Lotame 等,提供更广泛的用户行为和兴趣数据。

现实环境中如何使用 DMP

在实际应用中:

  • SSP 可能会使用自己的 DMP,但通常也会对接第三方 DMP 来增强用户数据。
  • DSP 一般会直接与多个 DMP 进行对接,以获得更丰富的数据,提高广告投放的精准度。
  • Ad Exchange 可能会整合多个 DMP 数据,以便在竞价过程中提供更好的用户数据匹配服务。

总的来说,DMP 是广告营销生态中的重要组成部分,SSP、DSP、Ad Exchange 都会使用 DMP,但具体的使用方式和数据需求各不相同。

三者共用或者各自拥有

Ad Exchange、SSP、DSP 这三者可以 共用一个 DMP,但在实际操作中,也可以根据需求和架构设计选择不同的方案。

1. 三者共用一个 DMP

数据管理平台(DMP) 主要用于收集、整理和分析用户数据,帮助提高广告投放的精准度和效果。在广告生态中,SSP、DSP 和 Ad Exchange 都需要通过数据来优化广告竞价、流量管理和广告展示,因此它们完全可以共用一个 DMP。

优势
  • 数据一致性: 如果三者共用一个 DMP,所有广告请求和竞价的基础数据(如用户画像、行为数据等)都可以共享,这样就避免了数据不一致的问题。
  • 统一数据源: 共用一个 DMP 可以确保每个环节获取的用户数据是最新的,这对精确广告投放至关重要。
  • 优化广告效果: 通过共享 DMP,Ad Exchange、SSP 和 DSP 可以基于相同的用户行为数据做出一致的广告决策,提高广告的投放效果(例如 CTR 和 CVR)。
  • 减少冗余: 如果三者各自维护自己的 DMP,会产生冗余的工作和资源浪费。共用 DMP 可以减少维护成本。
实现方式
  • 跨平台集成: 可以通过 API 或其他数据交换机制,让 SSP、DSP 和 Ad Exchange 从 DMP 获取实时数据,并确保所有数据的同步和一致性。
  • 数据治理: 需要设计良好的数据治理和权限控制机制,确保每个服务都能根据自己的需求访问数据,同时避免敏感数据泄露。

2. 三者各自拥有自己的 DMP

在某些情况下,SSP、DSP 和 Ad Exchange 会选择 各自拥有独立的 DMP,这通常与 独立运营不同的业务需求 有关。

优势
  • 定制化数据: 每个系统(SSP、DSP、Ad Exchange)可能会有不同的需求,独立的 DMP 可以根据其业务特点定制化数据的收集、分析和展示。
  • 更高的控制性: 每个系统可以完全控制自己的数据,不会受到其他系统的限制和干扰。
  • 专注于目标: 各自拥有 DMP 可以让每个系统专注于自己的核心业务,例如 DSP 可能更关注广告效果优化,SSP 则更关注广告流量的质量和匹配。
劣势
  • 数据孤岛: 如果每个系统都有独立的 DMP,那么就可能出现 数据孤岛,即不同系统的数据无法共享。这会导致广告优化效果降低,因为各个系统之间无法利用其他系统的有效数据。
  • 额外的维护成本: 维护多个 DMP 会导致资源和成本的增加。数据的同步、清洗、分析等工作需要分别处理,增加了复杂度。
实现方式
  • 数据同步与对接: 尽管各自拥有 DMP,但可以通过集成机制将不同系统的数据进行同步。例如,Ad Exchange 可以从 DSP 和 SSP 获取数据,进行优化后再回传给它们。
  • 集中管理: 在实际使用中,可以采用一些数据集成工具,将多个 DMP 的数据汇总至 数据湖数据仓库 中,以供统一分析和处理。

总结

  1. 共用一个 DMP:
    • 适合场景: 当 Ad Exchange、SSP 和 DSP 之间需要密切协作,并且对数据一致性和共享有较高要求时。
    • 优势: 数据一致性好、降低冗余、提高广告效果。
    • 劣势: 数据治理和权限管理较为复杂,需要跨平台集成。
  2. 各自拥有 DMP:
    • 适合场景: 当每个系统有独立的运营和数据需求时。
    • 优势: 更高的灵活性和控制性。
    • 劣势: 数据孤岛,增加维护成本。

在现实环境中,SSP、DSP 和 Ad Exchange 通常会选择共用一个 DMP,而不是每个系统独立拥有自己的 DMP。这种方式更为常见,并且具有以下几个实际优势:

  1. 数据一致性和协作:
    • 广告交易中的每个环节(SSP、DSP 和 Ad Exchange)都依赖用户数据(如用户兴趣、行为数据、地理位置等)来进行广告定向和竞价。如果每个系统独立维护自己的 DMP,会出现 数据不一致 的问题,导致广告效果差异大,甚至可能出现同一用户在不同平台上看到不一致的广告。共用一个 DMP 可以确保各方数据的一致性,提高广告投放的精确度和效果。
  2. 降低冗余和提高效率:
    • 每个系统独立维护一个 DMP,会涉及到 重复的数据收集、处理、存储和分析,这会浪费资源和增加成本。共用一个 DMP 可以减少重复建设,统一维护,提高数据使用效率。
  3. 统一的广告优化:
    • 通过共享一个 DMP,广告投放的各方(DSP 和 SSP)可以基于统一的数据做出优化决策。DSP 可以根据 DMP 提供的实时数据调整竞价策略,SSP 可以根据这些数据优化流量分配,从而提高 CTR(点击率)CVR(转化率)
  4. 简化数据治理:
    • 在一个统一的 DMP 下,广告平台可以集中管理用户数据、权限和隐私保护,降低合规性风险和操作复杂度。如果每个系统都维护自己的 DMP,可能会增加数据治理的难度,尤其是在处理敏感数据(如用户隐私信息)时。

为何一些系统可能选择各自拥有自己的 DMP?

尽管共用一个 DMP 是更常见的选择,但某些特定的广告平台或业务场景中,也可能会选择 各自独立的 DMP。例如:

  1. 独立性强的系统:
    如果 SSP、DSP 和 Ad Exchange 之间的合作较少,或者它们分别由不同的公司运营,且不希望共享数据,可能会选择各自拥有独立的 DMP。
  2. 定制化需求:
    有些平台可能会根据特定的广告业务需求或目标市场定制自己的 DMP,以便更好地进行数据收集、分析和优化。

总结

现实中,绝大多数广告平台(SSP、DSP、Ad Exchange)选择共用一个 DMP。
这不仅能提高数据一致性和广告效果,还能减少冗余的工作和资源浪费,优化数据的使用效率。尤其是在 广告竞价(RTB)精准投放 的需求下,统一的 DMP 能更好地支撑多方数据共享和广告优化。

注意点

  • 共用 DMP 的数据共享机制如何提高广告投放精度?
  • 数据隐私和合规性在共用 DMP 时如何保障?

DMP 代码结构

DMP(数据管理平台)的代码结构一般围绕数据采集、存储、处理、分析、API 服务等核心功能展开。其架构通常分为多个模块,每个模块都可以是一个独立的微服务,并结合大数据生态进行高效的数据管理和分析。

DMP/
│── data-ingestion/          # 数据采集层
│   ├── log-collector/       # 日志采集(Kafka、Flume、Logstash)
│   ├── event-tracker/       # 用户行为跟踪(埋点SDK,如JS/Python/Java)
│   ├── batch-ingestion/     # 批量数据导入(ETL、Hive、Flink)
│── data-storage/            # 数据存储层
│   ├── hdfs/                # HDFS 存储用户数据
│   ├── clickhouse/          # ClickHouse 进行实时数据分析
│   ├── mongodb/             # MongoDB 存储非结构化数据
│   ├── redis/               # Redis 作为缓存加速查询
│── data-processing/         # 数据处理层
│   ├── spark-processing/    # Spark 进行离线数据处理
│   ├── flink-streaming/     # Flink 进行实时数据计算
│   ├── feature-engineering/ # 特征工程,构建广告投放画像
│── data-analysis/           # 数据分析层
│   ├── user-profiling/      # 用户画像分析
│   ├── audience-segmentation/ # 受众分群
│   ├── predictive-modeling/ # 预测建模(机器学习)
│── api-services/            # API 服务层
│   ├── rest-api/            # 提供对外接口(Spring Boot、FastAPI)
│   ├── grpc-service/        # gRPC 实现高性能数据传输
│── ui-dashboard/            # 前端可视化
│   ├── react/               # 基于 React 或 Vue.js 构建的管理面板
│── deployment/              # 部署运维
│   ├── docker/              # Docker 部署
│   ├── kubernetes/          # K8s 集群管理
│   ├── monitoring/          # Prometheus + Grafana 监控

2. DMP 关键模块

1)数据采集层(Data Ingestion)

主要负责从各种渠道收集数据,例如:

  • 用户行为数据(网页点击、APP 交互、搜索记录)
  • 广告曝光和点击数据(RTB 竞价日志)
  • 第三方数据(数据提供商)

技术栈:

  • 实时数据采集:Kafka、Flink、Logstash
  • 埋点 SDK:JavaScript、Python SDK 进行用户行为跟踪
  • 批量数据采集:ETL(Apache NiFi、Airflow)

2)数据存储层(Data Storage)

用于存储和管理收集到的海量数据,不同类型的数据使用不同的存储:

  • HDFS:存储原始用户行为数据
  • ClickHouse:存储实时用户画像数据
  • MongoDB:存储半结构化的用户信息
  • Redis:缓存热门人群数据,加速查询
  • Elasticsearch:用于快速搜索广告投放数据

3)数据处理层(Data Processing)

DMP 需要进行数据清洗、特征工程、用户分群等处理:

  • Flink/Spark 处理用户行为数据
  • ETL 任务进行数据转换
  • Kafka 作为流式数据中间件
  • 机器学习特征工程(TensorFlow、Scikit-Learn)

示例:

from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("DMPUserProfile").getOrCreate()

# 读取用户行为数据
df = spark.read.json("hdfs://data/user_behavior.json")

# 进行特征提取
df = df.groupBy("user_id").agg({"clicks": "sum", "impressions": "sum"})

df.show()

4)数据分析层(Data Analysis)

DMP 需要提供用户画像分析、受众分群、预测建模

  • 用户画像建模(性别、年龄、兴趣、消费能力)
  • 受众分群(高净值人群、游戏玩家、母婴用户等)
  • 机器学习建模(预测用户点击率 CTR)

示例:用 Python 进行广告点击率(CTR)预测:

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split

# 假设有CTR数据集
X_train, X_test, y_train, y_test = train_test_split(features, labels, test_size=0.2)

model = RandomForestClassifier(n_estimators=100)
model.fit(X_train, y_train)

# 预测点击率
predictions = model.predict(X_test)

5)API 服务层(API Services)

DMP 需要对外提供 API,让 SSP、DSP、Ad Exchange 获取数据:

  • Spring BootFastAPI 提供 RESTful API
  • gRPC 进行高性能数据交互

示例:一个简单的用户画像 API:

from fastapi import FastAPI
import redis

app = FastAPI()
redis_client = redis.Redis(host="localhost", port=6379)

@app.get("/user_profile/{user_id}")
def get_user_profile(user_id: str):
    data = redis_client.get(f"user_profile:{user_id}")
    return {"user_id": user_id, "profile": data}

6)UI 可视化层(UI Dashboard)

提供 Web 界面,让运营人员查看数据:

  • React/Vue.js 前端
  • Grafana 监控系统
  • ECharts/D3.js 进行数据可视化

示例:用 ECharts 显示用户画像数据:

var myChart = echarts.init(document.getElementById('main'));
myChart.setOption({
    title: { text: '用户兴趣分布' },
    series: [{ type: 'pie', data: [{ value: 40, name: '游戏' }, { value: 60, name: '电商' }] }]
});

3. DMP 的技术选型

组件 技术栈
数据采集 Kafka, Flume, Logstash, JavaScript SDK
数据存储 HDFS, ClickHouse, MongoDB, Redis, ElasticSearch
数据处理 Apache Spark, Flink, Airflow, Python
模型训练 Scikit-Learn, TensorFlow, PyTorch
API 服务 Spring Boot, FastAPI, gRPC
前端可视化 React, Vue.js, ECharts, Grafana
部署运维 Docker, Kubernetes, Prometheus

4. 结论

DMP 不是一个单一的微服务,而是一个包含多个微服务和大数据组件的大数据平台:

  1. 数据采集(日志埋点、事件追踪)
  2. 数据存储(HDFS、MongoDB、ClickHouse)
  3. 数据处理(Spark、Flink、Kafka)
  4. 数据分析(用户画像、机器学习)
  5. API 服务(Spring Boot、FastAPI)
  6. 可视化界面(React、Grafana)

DMP 结合了 大数据处理 + 机器学习 + 微服务,支持 SSP、DSP、Ad Exchange 进行精准营销。

1. 数据同步层(Data Sync)

在 DMP 里,数据同步非常重要,保证各个存储系统(MySQL、Kafka、Hive)之间的数据一致性:

  • MySQL Sync(Debezium)监听数据变更
  • Kafka Sync 处理实时流数据
  • Hive Sync 将批量数据同步到 Hive

示例:使用 Flink CDC 监听 MySQL 变更并同步到 Kafka:

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
FlinkKafkaProducer<String> kafkaProducer = new FlinkKafkaProducer<>(
    "kafka-topic",
    new SimpleStringSchema(),
    kafkaProps
);
env.addSource(new MySQLSource()).addSink(kafkaProducer);
env.execute();

2. 安全策略(Security)

数据安全在 DMP 里至关重要,需要:

  • RBAC 角色权限管理
  • 数据加密(AES、SSL)
  • 日志审计(ELK Stack)

示例:Spring Security 进行 API 认证:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/api/**").authenticated()
            .and().oauth2Login();
    }
}

3. 监控与日志

  • Prometheus + Grafana 监控 DMP 运行状态
  • ELK(Elasticsearch + Logstash + Kibana) 进行日志分析
  • Jaeger 进行分布式链路追踪

示例:Prometheus 监控 Java API:

@RestController
public class MetricsController {
    private final Counter requestCounter = Counter.build()
            .name("api_requests_total")
            .help("Total API Requests")
            .register();
    
    @GetMapping("/metrics")
    public String getMetrics() {
        requestCounter.inc();
        return "OK";
    }
}

总结

  • DMP 代码结构需要包含:数据采集、存储、处理、分析、同步、API、UI、监控、安全
  • 数据同步很重要,保证 MySQL、Kafka、Hive 之间数据一致性
  • 安全策略不可忽略,RBAC 权限管理 + 数据加密
  • 日志与监控必须到位,ELK + Prometheus 保障可观测性

SSP 代码结构

SSP(供应方平台)主要用于管理媒体方的广告资源,并将广告请求转发给 Ad Exchange 或 DSP 进行实时竞价(RTB)。它的代码结构通常涉及 广告请求处理、流量过滤、竞价管理、广告填充、日志与监控等模块

SSP/
│── ad-request-handler/       # 广告请求处理模块
│   ├── http-server/          # 处理媒体方的广告请求(Spring Boot、Netty)
│   ├── grpc-server/          # 处理 gRPC 请求,提高性能
│   ├── validation/           # 请求参数校验(IP、设备信息)
│── traffic-filter/           # 流量过滤模块(防作弊、无效流量)
│   ├── bot-detection/        # 识别爬虫和自动化流量
│   ├── fraud-detection/      # 过滤点击欺诈流量
│   ├── geo-filtering/        # 地域过滤(基于 IP 库)
│── ad-auction/               # 竞价管理模块
│   ├── bid-request/          # 生成 RTB 竞价请求,转发给 Ad Exchange/DSP
│   ├── bid-response/         # 解析 DSP 返回的竞价结果
│   ├── auction-engine/       # 竞价逻辑(第二高价竞价、优先广告策略)
│── ad-selection/             # 广告填充模块
│   ├── direct-ads/           # 直接投放广告(非竞价广告)
│   ├── fallback-ads/         # 兜底广告(竞价失败时填充)
│── data-sync/                # 数据同步模块
│   ├── dmp-integration/      # 与 DMP 对接,获取用户画像数据
│   ├── kafka-events/         # 通过 Kafka 进行数据同步
│── reporting/                # 数据上报模块
│   ├── win-notification/     # 向 DSP 发送竞价成功通知
│   ├── impression-tracking/  # 记录广告展示(曝光)日志
│   ├── click-tracking/       # 记录广告点击日志
│── api-services/             # API 服务层
│   ├── rest-api/             # 提供对外 API(Spring Boot、FastAPI)
│   ├── grpc-service/         # 高性能 API(gRPC)
│── ui-dashboard/             # 管理控制台
│   ├── react/                # React 或 Vue.js 前端界面
│   ├── reporting-ui/         # 广告报表可视化
│── security/                 # 安全模块
│   ├── auth/                 # 用户认证(JWT、OAuth2)
│   ├── rate-limiting/        # API 限流(Sentinel、Guava RateLimiter)
│── deployment/               # 部署运维
│   ├── docker/               # Docker 容器化部署
│   ├── kubernetes/           # Kubernetes 自动扩展
│   ├── monitoring/           # 监控系统(Prometheus + Grafana)

核心模块解析

1. 广告请求处理(Ad Request Handler)

媒体方(Publisher)会向 SSP 发送广告请求,SSP 需要解析请求,并进行流量过滤:

{
  "user_id": "12345",
  "device": "mobile",
  "location": "New York, USA",
  "ad_slot": "banner_top",
  "page_url": "https://example.com/article"
}

示例:Spring Boot 处理广告请求:

@RestController
@RequestMapping("/ad")
public class AdRequestController {
    @PostMapping("/request")
    public ResponseEntity<AdResponse> handleAdRequest(@RequestBody AdRequest request) {
        if (!TrafficFilter.isValidRequest(request)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        AdResponse response = AdAuction.processRequest(request);
        return ResponseEntity.ok(response);
    }
}

2. 竞价管理(Ad Auction)

SSP 需要将广告请求转发给 Ad Exchange 或多个 DSP 进行实时竞价(RTB),然后选择 最高竞价的广告进行展示

{
  "bid_request_id": "abc123",
  "imp": [
    {
      "id": "1",
      "banner": {
        "w": 300,
        "h": 250
      }
    }
  ],
  "site": {
    "domain": "example.com"
  },
  "user": {
    "id": "user_123"
  }
}

示例:发送 HTTP 请求到 Ad Exchange 进行竞价:

public BidResponse sendBidRequest(BidRequest bidRequest) {
    RestTemplate restTemplate = new RestTemplate();
    return restTemplate.postForObject("https://adexchange.com/bid", bidRequest, BidResponse.class);
}

3. 流量过滤(Traffic Filtering)

SSP 需要防止广告欺诈(如虚假流量、自动点击),可以通过 IP 黑名单、设备指纹、爬虫检测 来进行过滤:

public static boolean isValidRequest(AdRequest request) {
    return !FraudDetection.isBlacklistedIP(request.getIp()) &&
           !BotDetection.isAutomatedTraffic(request.getUserAgent());
}

4. 广告填充(Ad Selection)

如果没有 DSP 竞价成功,SSP 需要使用直接投放广告或兜底广告

public AdResponse getFallbackAd(AdRequest request) {
    return new AdResponse("fallback_ad.jpg", "https://sponsor.com");
}

5. 数据同步(Data Sync)

SSP 需要与 DMP 交互,获取用户画像,提高广告匹配度:

public UserProfile getUserProfile(String userId) {
    return restTemplate.getForObject("https://dmp.com/user/" + userId, UserProfile.class);
}

6. 广告效果监测(Reporting)

广告展示后,SSP 需要回传曝光(impression)和点击(click)数据

public void trackImpression(String adId, String userId) {
    kafkaTemplate.send("impressions", new ImpressionLog(adId, userId, System.currentTimeMillis()));
}

7. 监控与日志

SSP 需要 Prometheus + Grafana 进行监控:

@RestController
public class MetricsController {
    private final Counter requestCounter = Counter.build()
            .name("ad_requests_total")
            .help("Total Ad Requests")
            .register();
    
    @GetMapping("/metrics")
    public String getMetrics() {
        requestCounter.inc();
        return "OK";
    }
}

总结

SSP 需要实现的核心功能

  1. 广告请求处理(解析 Publisher 传来的请求)
  2. 流量过滤(防止无效流量、广告欺诈)
  3. 竞价管理(将请求转发给 DSP 进行 RTB 竞价)
  4. 广告填充(选择最高价广告,或兜底广告)
  5. 数据同步(与 DMP 对接,提高广告精准度)
  6. 广告监测(上报曝光、点击数据)
  7. 监控与日志(Prometheus 监控、ELK 日志分析)

这个架构可以支撑 高并发、低延迟 的 SSP 系统

Ad Exchange 代码结构

Ad Exchange(广告交易平台)是连接 SSP(供应方平台)和 DSP(需求方平台) 的核心组件,负责接收 SSP 传来的广告竞价请求,并将其转发给多个 DSP 进行 RTB(实时竞价),然后选择最高竞价广告进行返回。

AdExchange/
│── request-handler/          # 广告竞价请求处理模块
│   ├── http-server/          # 处理 HTTP 广告竞价请求
│   ├── grpc-server/          # 处理 gRPC 广告竞价请求
│── bid-manager/              # 竞价管理模块
│   ├── dsp-connector/        # 向多个 DSP 发送竞价请求
│   ├── auction-engine/       # 竞价引擎(Vickrey Auction、First Price Auction)
│── impression-tracking/      # 监测广告曝光与点击
│   ├── win-notification/     # 竞价胜出通知(通知 DSP)
│   ├── event-logger/         # 记录曝光、点击日志
│── dmp-integration/          # DMP 数据对接
│   ├── user-profiling/       # 获取用户画像数据
│   ├── targeting-rules/      # 进行人群定向匹配
│── analytics/                # 竞价数据分析
│   ├── real-time-metrics/    # 监控竞价速率、胜出率
│   ├── fraud-detection/      # 竞价欺诈检测
│── api-services/             # API 层
│   ├── rest-api/             # 提供 REST API
│   ├── grpc-service/         # 提供 gRPC API
│── ui-dashboard/             # 管理控制台
│   ├── react/                # 前端 UI
│   ├── bid-analytics/        # 竞价分析界面
│── deployment/               # 部署与监控
│   ├── docker/               # Docker 容器化
│   ├── kubernetes/           # Kubernetes 自动扩展
│   ├── monitoring/           # Prometheus + Grafana 监控

核心模块解析

1. 竞价请求处理(Request Handler)

Ad Exchange 需要接收 SSP 传来的竞价请求,并解析请求数据:

{
  "id": "req_12345",
  "imp": [
    {
      "id": "1",
      "banner": {
        "w": 300,
        "h": 250
      }
    }
  ],
  "site": {
    "domain": "example.com"
  },
  "user": {
    "id": "user_6789"
  }
}

Spring Boot 处理 HTTP 请求:

@RestController
@RequestMapping("/adexchange")
public class BidRequestController {
    @PostMapping("/bid")
    public ResponseEntity<BidResponse> handleBidRequest(@RequestBody BidRequest request) {
        AuctionResult result = AuctionEngine.runAuction(request);
        return ResponseEntity.ok(result.getWinningBid());
    }
}

2. 竞价管理(Bid Manager)

Ad Exchange 需要向多个 DSP 发送竞价请求,并收集竞价数据:

public class DspConnector {
    private final RestTemplate restTemplate = new RestTemplate();
    
    public BidResponse sendBidRequest(BidRequest bidRequest, String dspUrl) {
        return restTemplate.postForObject(dspUrl, bidRequest, BidResponse.class);
    }
}

示例:DSP 竞价返回的响应数据:

{
  "id": "bid_7890",
  "price": 1.5,
  "ad": {
    "url": "https://ads.com/ad123.jpg"
  }
}

3. 竞价引擎(Auction Engine)

Ad Exchange 需要对多个 DSP 返回的竞价结果进行比对,选出 最高出价广告

public class AuctionEngine {
    public static BidResponse runAuction(BidRequest request, List<BidResponse> dspBids) {
        return dspBids.stream()
                      .max(Comparator.comparing(BidResponse::getPrice))
                      .orElse(null);
    }
}

常见的竞价算法:

  • 第一价格拍卖(First Price Auction):最高出价者支付其出价金额
  • 第二价格拍卖(Vickrey Auction):最高出价者支付次高出价金额

4. 广告曝光与点击监测(Impression Tracking)

Ad Exchange 需要记录广告展示和点击事件,并通知 DSP:

public void trackImpression(String adId, String userId) {
    kafkaTemplate.send("impressions", new ImpressionLog(adId, userId, System.currentTimeMillis()));
}

竞价胜出后,通知 DSP:

public void notifyWinningBid(BidResponse bid) {
    restTemplate.postForObject("https://dsp.com/win", bid, Void.class);
}

5. DMP 数据对接(DMP Integration)

Ad Exchange 需要与 DMP(数据管理平台) 对接,获取用户画像数据:

public UserProfile getUserProfile(String userId) {
    return restTemplate.getForObject("https://dmp.com/user/" + userId, UserProfile.class);
}

通过 DMP 定向投放广告

public boolean isUserTargeted(UserProfile userProfile, AdRequest request) {
    return userProfile.getInterests().contains(request.getTargetCategory());
}

6. 竞价数据分析(Analytics)

Ad Exchange 需要分析竞价数据,包括 竞价速率、胜出率、欺诈检测

@RestController
public class MetricsController {
    private final Counter bidCounter = Counter.build()
            .name("bids_total")
            .help("Total Bids Processed")
            .register();
    
    @GetMapping("/metrics")
    public String getMetrics() {
        bidCounter.inc();
        return "OK";
    }
}

7. 监控与运维(Monitoring & Deployment)

Ad Exchange 需要使用 Prometheus + Grafana 进行监控

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: adexchange-monitor
spec:
  endpoints:
  - port: metrics
    interval: 30s
  selector:
    matchLabels:
      app: adexchange

总结

Ad Exchange 需要实现的核心功能

  1. 竞价请求处理(接收 SSP 传来的竞价请求)
  2. 向 DSP 发送竞价请求(收集多个 DSP 的竞价数据)
  3. 竞价引擎(选择最高出价的广告)
  4. 曝光和点击监测(上报曝光、点击数据,通知 DSP)
  5. DMP 数据对接(获取用户画像,提高广告匹配度)
  6. 竞价数据分析(监控竞价速率、欺诈检测)
  7. 高性能架构(使用 Kafka、gRPC、Redis 进行优化)

这个架构可以支撑 高并发、低延迟 的 Ad Exchange 系统

DSP 代码结构

DSP(Demand-Side Platform)主要负责 接收 Ad Exchange 的竞价请求,执行 广告选择与定价策略,并返回 竞价响应。DSP 需要结合 DMP(数据管理平台) 进行用户定向投放,同时管理 广告主账户、预算控制、广告创意等

DSP/
│── request-handler/          # 竞价请求处理
│   ├── http-server/          # 处理 HTTP 请求
│   ├── grpc-server/          # 处理 gRPC 请求
│── bidding-engine/           # 竞价引擎
│   ├── ad-selection/         # 选择最合适的广告
│   ├── price-strategy/       # 竞价策略(第一价格拍卖、第二价格拍卖)
│── dmp-integration/          # DMP 数据对接
│   ├── user-profiling/       # 用户画像分析
│   ├── targeting-engine/     # 目标受众匹配
│── ad-management/            # 广告管理模块
│   ├── ad-creative/          # 广告创意管理
│   ├── campaign-management/  # 广告投放管理(预算、日限额)
│── reporting/                # 数据分析与报表
│   ├── win-rate-analysis/    # 竞价胜率分析
│   ├── budget-monitoring/    # 预算消耗监控
│── api-services/             # API 服务
│   ├── rest-api/             # 提供 REST API
│   ├── grpc-service/         # 提供 gRPC API
│── deployment/               # 部署与监控
│   ├── docker/               # Docker 容器化
│   ├── kubernetes/           # Kubernetes 自动扩展
│   ├── monitoring/           # Prometheus + Grafana 监控

关键模块解析

1️⃣ 竞价请求处理(Request Handler)

DSP 需要接收 Ad Exchange 发送的竞价请求,并解析请求数据:

{
  "id": "req_12345",
  "imp": [
    {
      "id": "1",
      "banner": {
        "w": 300,
        "h": 250
      }
    }
  ],
  "site": {
    "domain": "example.com"
  },
  "user": {
    "id": "user_6789"
  }
}

Spring Boot 处理 HTTP 竞价请求:

@RestController
@RequestMapping("/dsp")
public class BidRequestController {
    @PostMapping("/bid")
    public ResponseEntity<BidResponse> handleBidRequest(@RequestBody BidRequest request) {
        BidResponse bidResponse = BiddingEngine.processBid(request);
        return ResponseEntity.ok(bidResponse);
    }
}

2️⃣ 竞价引擎(Bidding Engine)

DSP 需要根据 广告匹配度、用户定向、广告预算 计算最佳竞价:

public class BiddingEngine {
    public static BidResponse processBid(BidRequest request) {
        // Step 1: 选择适合的广告
        Ad ad = AdSelection.selectBestAd(request);

        // Step 2: 计算竞价价格
        double bidPrice = PricingStrategy.calculateBid(ad, request);

        return new BidResponse(ad.getId(), bidPrice, ad.getAdUrl());
    }
}

广告选择逻辑:

public class AdSelection {
    public static Ad selectBestAd(BidRequest request) {
        List<Ad> eligibleAds = AdRepository.getAdsByTargeting(request.getUser());
        return eligibleAds.stream()
                .max(Comparator.comparing(Ad::getClickThroughRate))  // 选择点击率最高的广告
                .orElse(null);
    }
}

竞价策略(第一价格拍卖 or 第二价格拍卖):

public class PricingStrategy {
    public static double calculateBid(Ad ad, BidRequest request) {
        double baseBid = ad.getBasePrice();
        return baseBid * (1 + Math.random() * 0.2); // 增加浮动因子
    }
}

3️⃣ DMP 数据对接(DMP Integration)

DSP 需要与 DMP 交互,获取 用户画像,优化广告投放:

public class DmpClient {
    private static final String DMP_URL = "https://dmp.com/user/";

    public static UserProfile getUserProfile(String userId) {
        return restTemplate.getForObject(DMP_URL + userId, UserProfile.class);
    }
}

然后,DSP 需要根据 DMP 数据进行 精准投放

public class TargetingEngine {
    public static boolean isUserTargeted(UserProfile userProfile, Ad ad) {
        return userProfile.getInterests().contains(ad.getCategory());
    }
}

4️⃣ 广告管理(Ad Management)

DSP 需要管理 广告创意、广告主账户、预算控制

public class AdCampaign {
    private String advertiserId;
    private String campaignId;
    private double dailyBudget;
    private double spentToday;

    public boolean canBid(double bidAmount) {
        return (spentToday + bidAmount) <= dailyBudget;
    }
}

如果预算已达上限,DSP 不会继续竞价

public class BudgetManager {
    public static boolean checkBudget(AdCampaign campaign, double bidAmount) {
        return campaign.canBid(bidAmount);
    }
}

5️⃣ 竞价分析 & 监控(Reporting & Monitoring)

DSP 需要监控 竞价胜率、广告转化率、预算消耗

@RestController
@RequestMapping("/metrics")
public class MetricsController {
    private final Counter bidCounter = Counter.build()
            .name("dsp_bids_total")
            .help("Total DSP Bids")
            .register();

    @GetMapping("/bids/count")
    public String getBidCount() {
        bidCounter.inc();
        return "Bids counted.";
    }
}

6️⃣ 监控与运维(Monitoring & Deployment)

DSP 需要使用 Prometheus + Grafana 进行监控

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: dsp-monitor
spec:
  endpoints:
  - port: metrics
    interval: 30s
  selector:
    matchLabels:
      app: dsp

代码结构总结

DSP 需要实现的核心功能

  1. 竞价请求处理(接收 Ad Exchange 的竞价请求)
  2. 广告匹配(根据用户数据选择最优广告)
  3. 竞价计算(第一价格拍卖 or 第二价格拍卖)
  4. DMP 数据对接(精准投放,优化广告效果)
  5. 广告管理(控制广告预算 & 竞价策略)
  6. 竞价分析 & 监控(监控竞价胜率、转化率、预算消耗)
  7. 高并发架构(使用 Kafka、Redis、gRPC 进行优化)

这个架构可以支撑 高并发、精准投放 的 DSP 平台

第一价格拍卖

广告营销业务DSP(需求方平台) 中,竞价计算 是 DSP 决定广告出价 的核心环节。第一价格拍卖(First-Price Auction) 是其中的一种竞价方式。

什么是第一价格拍卖(First-Price Auction)?

第一价格拍卖 是指 广告主(DSP)提交的最高出价即为实际支付价格,即 最终赢家支付自己的出价金额

竞价流程

  1. Ad Exchange 向多个 DSP 发送竞价请求
  2. 各 DSP 计算并提交竞价
  3. 出价最高者赢得广告位
  4. 胜出 DSP 按照自己的出价金额支付费用

举例说明

假设 3 个 DSP 参与竞价,它们的出价如下:

DSP 出价(Bid)
DSP A $3.50
DSP B $4.00
DSP C $3.80

在第一价格拍卖规则下:

  • DSP B 出价最高($4.00),因此赢得广告位
  • DSP B 支付 $4.00(等于自己的出价)

第一价格拍卖的优缺点

优势 劣势
透明 —— 竞价者支付的价格与出价完全一致 出价过高风险 —— 由于不知道其他 DSP 出价,可能导致广告主支付过高费用
快速决策 —— 不需要复杂的二次计算 价格波动大 —— 由于 DSP 可能会过度竞价减少出价,导致市场价格不稳定
防止拍卖操控 —— 无法通过策略性出价操控价格 广告主成本较高 —— 竞价者为了赢得广告位,往往会出更高价格

第一价格拍卖的 DSP 代码示例

DSP 的竞价引擎 中,第一价格拍卖的逻辑很简单,就是返回出价最高的 DSP,并让其支付自身出价

public class FirstPriceAuction {
    public static BidResponse determineWinner(List<BidRequest> bids) {
        // 按出价金额降序排列
        bids.sort((b1, b2) -> Double.compare(b2.getBidPrice(), b1.getBidPrice()));

        // 最高出价者赢得广告位
        BidRequest winningBid = bids.get(0);

        return new BidResponse(winningBid.getDspId(), winningBid.getBidPrice(), winningBid.getAdUrl());
    }
}

Ad Exchange 端,当收到 DSP 竞价后,执行第一价格拍卖

public class AdExchange {
    public static void main(String[] args) {
        List<BidRequest> bidRequests = List.of(
            new BidRequest("DSP_A", 3.50, "https://ad-a.com"),
            new BidRequest("DSP_B", 4.00, "https://ad-b.com"),
            new BidRequest("DSP_C", 3.80, "https://ad-c.com")
        );

        // 执行第一价格拍卖
        BidResponse winner = FirstPriceAuction.determineWinner(bidRequests);
        System.out.println("赢家: " + winner.getDspId() + " | 付款金额: $" + winner.getBidPrice());
    }
}

执行后输出

赢家: DSP_B | 付款金额: $4.00

第一价格 vs. 第二价格拍卖

竞价方式 支付金额 市场影响
第一价格拍卖 最高竞价者支付自己的出价 出价会偏保守,广告主可能出更低的价格
第二价格拍卖 最高竞价者支付第二高出价 + 一定增量(如$0.01) DSP 会大胆出价,因为不会真正支付自己出价的最高金额

实际广告投放市场中,第二价格拍卖更常用,因为它可以 减少 DSP 过度出价的风险,但近年来一些平台(如 Header Bidding)开始更多采用 第一价格拍卖 来提升广告收入。

总结

  • 第一价格拍卖:最高出价者支付自己的出价
  • 优势:透明、快速决策、防止操控
  • 劣势:广告主可能过度支付,价格波动大
  • 实际应用:虽然传统上 RTB 采用第二价格拍卖,但 Header Bidding 等机制更倾向于第一价格拍卖,以最大化收益

在 DSP 竞价策略中,第一价格拍卖简单直观,但广告主通常需要结合数据分析(如 DMP)调整出价,以避免支付过高的成本!

你可能感兴趣的:(java)