返回知识工坊

Learning Path

SpringCloud 微服务广告系统设计与实现

学习基于SpringCloud的微服务架构广告系统,涵盖设计思想、模块实现、测试和高级主题,帮助掌握企业级广告系统开发。

进阶6 张卡120 分钟发布于 2026年7月13日

路径目标

SpringCloud 微服务广告系统设计与实现

本学习路径基于慕课网实战课程,引导读者从零开始理解广告系统设计、微服务搭建、投放与检索模块实现,以及测试和优化策略,适合中高级开发者提升实战能力。

6 张知识卡6 个诊断问题6 个边界答案6 个记忆锚点6 个衍生拓展
01
外部资料

说清广告系统设计思想与微服务架构选型

广告系统是企业营收核心,设计需考虑高并发、可扩展性。本卡覆盖广告系统整体设计思想,包括对外服务入口、投放与检索模块划分。微服务架构使用SpringCloud实现服务注册、网关和业务系统搭建,确保系统解耦和独立部署。常见误区是过度设计,需平衡功能与性能。

诊断题

  1. 在广告系统设计中,如何划分广告主投放模块和媒体方检索模块的职责?
  2. 使用SpringCloud搭建微服务时,服务注册中心(如Eureka)和网关(如Zuul)各自解决什么问题,有哪些常见陷阱?

答案骨架

我能说清广告系统设计思想:

  1. 广告系统分为广告主投放和媒体方检索两大模块,前者负责广告创建和管理,后者负责广告匹配和展示
  2. 微服务架构通过服务注册中心实现服务发现,网关统一入口和路由
  3. 适用边界是系统规模大、团队多时采用微服务,小系统可能单体更高效
  4. 易混点是混淆服务注册与服务发现,注册是服务实例上报,发现是客户端查找
  5. 衍生关联到配置中心和熔断机制。

边界追问

  1. 如果广告系统需要支持实时竞价(RTB),微服务架构如何调整以应对低延迟需求?
  2. 在微服务间通信中,REST和gRPC各自优劣,广告系统更适合哪种?
  3. 如果把 说清广告系统设计思想与微服务架构选型 落到真实项目,应该继续追问哪些输入条件、失败前提或成本取舍? 回答时请结合原文机制、适用边界、易混点和工程取舍。

边界答案

  1. 对于实时竞价,需优化网络延迟和使用异步通信,微服务可拆分更细或引入消息队列;
  2. REST简单通用,gRPC高效但复杂,广告系统根据团队技能和性能需求选择,高吞吐场景倾向gRPC。 判断原则是先确认原文对象、输入条件和适用边界是否成立;前提成立时按该机制处理,前提不成立时说明例外、风险和替代方案。

记忆锚点

记住:设计分模块,微服务拆注册网关,平衡功能与性能。,先抓问题,再验机制,最后查边界。

衍生拓展

  • 复习重点:微服务拆分原则和领域驱动设计(DDD)在广告系统中的应用;- 易混点:服务注册与配置中心的区别;- 面试延伸:如何设计一个高可用的广告检索服务;- 实践扩展:使用SpringCloud Gateway替代Zuul实现网关功能。

落地场景

例如,使用SpringCloud Eureka进行服务注册,配置如下:

YAML
1# application.yml for Eureka server
2eureka:
3  client:
4    register-with-eureka: false
5    fetch-registry: false
6  server:
7    enable-self-preservation: false
打开资料
02
外部资料

搭建SpringCloud微服务注册中心、网关和业务服务

微服务体系搭建包括服务注册平台(如Eureka)、服务网关(如Zuul)和业务系统。服务注册允许服务实例动态注册和发现,网关提供统一入口、路由和过滤。业务系统基于SpringBoot实现,通过Feign进行服务间调用。常见误区是网关过度集中逻辑,应保持轻量。

诊断题

  1. Eureka的服务注册与发现机制是如何工作的,如何保证高可用?
  2. Zuul网关中,如何配置路由规则和过滤器链,实现广告请求的鉴权和限流?
  3. 继续追问 搭建SpringCloud微服务注册中心、网关和业务服务 时,哪些边界、误区或应用判断最容易答错? 回答时请结合原文机制、适用边界、易混点和工程取舍。

答案骨架

我能搭建微服务体系:

  1. 服务注册中心Eureka使用心跳机制检测服务存活,客户端缓存注册表
  2. 网关Zuul通过路由映射将请求转发到后端服务,并支持前置和后置过滤器
  3. 适用边界是微服务数量多时,但网关可能成为单点故障,需集群部署
  4. 易混点是Eureka与Consul的选型,Eureka更简单,Consul支持多数据中心
  5. 衍生关联到熔断器Hystrix和链路追踪Sleuth。

边界追问

  1. 在广告系统中,如何实现灰度发布通过网关路由?
  2. 服务间调用失败时,如何设计重试和熔断策略?
  3. 如果把 搭建SpringCloud微服务注册中心、网关和业务服务 落到真实项目,应该继续追问哪些输入条件、失败前提或成本取舍? 回答时请结合原文机制、适用边界、易混点和工程取舍。

边界答案

  1. 灰度发布可通过网关路由规则匹配请求头或IP,将部分流量导到新版本服务;
  2. 使用Hystrix熔断,设置失败阈值和超时,快速失败避免雪崩。 判断原则是先确认原文对象、输入条件和适用边界是否成立;前提成立时按该机制处理,前提不成立时说明例外、风险和替代方案。

记忆锚点

记住:注册心跳,网关路由过滤,业务Feign调用。,先抓问题,再验机制,最后查边界。

衍生拓展

  • 复习重点:SpringCloud组件版本兼容性;- 常见误区:过度依赖网关处理业务逻辑;- 面试延伸:比较SpringCloud与Dubbo架构;- 实践扩展:集成SpringCloud Config实现配置动态刷新。

落地场景

网关路由配置示例:

YAML
1# application.yml for Zuul
2zuul:
3  routes:
4    ad-service:
5      path: /ad/**
6      service-id: ad-service
7      strip-prefix: false
打开资料
03
外部资料

实现广告投放数据存储设计与ORM服务接口

广告投放模块涉及广告主、广告计划、创意等数据存储。使用MySQL 8.0存储结构化数据,JPA作为ORM框架实现数据访问层。设计数据表时需考虑查询效率和扩展性,例如广告计划表索引优化。响应与异常统一实现通过ControllerAdvice处理异常,返回标准格式。常见误区是N+1查询问题,需使用JOIN FETCH或@BatchSize。

诊断题

  1. 在JPA中,如何避免广告查询时的N+1问题,有哪些优化策略?
  2. 设计广告主和广告计划表时,如何平衡范式与反范式以提升检索性能?
  3. 继续追问 实现广告投放数据存储设计与ORM服务接口 时,哪些边界、误区或应用判断最容易答错? 回答时请结合原文机制、适用边界、易混点和工程取舍。

答案骨架

我能实现广告投放数据存储:

  1. 使用JPA实体映射数据库表,如AdPlan实体对应广告计划表
  2. 通过Spring Data JPA的Repository接口进行CRUD操作
  3. 适用边界是关系型数据存储,但高写入场景可考虑NoSQL
  4. 易混点是JPA与MyBatis选型,JPA全自动但性能控制弱,MyB灵活
  5. 衍生关联到数据库索引设计和事务管理。

边界追问

  1. 如果广告计划数据量巨大,如何进行分库分表?
  2. 在广告投放中,如何保证广告创建操作的事务一致性?
  3. 如果把 实现广告投放数据存储设计与ORM服务接口 落到真实项目,应该继续追问哪些输入条件、失败前提或成本取舍? 回答时请结合原文机制、适用边界、易混点和工程取舍。

边界答案

  1. 分库分表使用ShardingSphere或手动分片,按广告主ID哈希分表;
  2. 使用Spring @Transactional注解管理事务,确保广告和创意数据原子性。 判断原则是先确认原文对象、输入条件和适用边界是否成立;前提成立时按该机制处理,前提不成立时说明例外、风险和替代方案。

记忆锚点

记住:JPA实体映射,Repository操作,N+1用JOIN FETCH。,先抓问题,再验机制,最后查边界。

衍生拓展

  • 复习重点:JPA缓存机制(一级缓存、二级缓存);- 易混点:@Transactional的传播行为;- 面试延伸:如何优化大数据量下的广告查询;- 实践扩展:集成Flyway进行数据库迁移管理。

落地场景

JPA实体示例:

Java
1@Entity
2@Table(name = "ad_plan")
3public class AdPlan {
4    @Id
5    @GeneratedValue(strategy = GenerationType.IDENTITY)
6    private Long id;
7    private String name;
8    // 其他字段
9}

查询时使用@Query避免N+1:

Java
1@Query("SELECT p FROM AdPlan p JOIN FETCH p.creatives")
2List<AdPlan> findAllWithCreatives();
打开资料
04
外部资料

设计广告检索数据索引与实现检索服务

广告检索模块负责根据用户特征匹配合适广告。数据索引设计包括全量索引加载和增量数据投递,使用Kafka处理实时更新。检索服务实现基于倒排索引或内存索引,快速响应请求。常见误区是索引更新延迟导致数据不一致,需设计容错机制。

诊断题

  1. 在广告检索中,全量索引加载和增量更新如何协调,如何保证数据最终一致性?
  2. 如何设计广告匹配策略,考虑用户画像和广告定向条件?
  3. 继续追问 设计广告检索数据索引与实现检索服务 时,哪些边界、误区或应用判断最容易答错? 回答时请结合原文机制、适用边界、易混点和工程取舍。

答案骨架

我能设计广告检索索引:

  1. 全量索引从数据库加载到内存或搜索引擎如Elasticsearch
  2. 增量数据通过Kafka消息队列实时投递,更新索引
  3. 适用边界是读多写少场景,索引需定期重建
  4. 易混点是内存索引与ES选型,内存快但数据量有限,ES可扩展
  5. 衍生关联到缓存策略和搜索算法。

边界追问

  1. 如果广告检索需要支持实时竞价(RTB),索引设计如何优化低延迟?
  2. 在索引数据不一致时,如何快速恢复和校验?
  3. 如果把 设计广告检索数据索引与实现检索服务 落到真实项目,应该继续追问哪些输入条件、失败前提或成本取舍? 回答时请结合原文机制、适用边界、易混点和工程取舍。

边界答案

  1. 对于RTB,使用内存索引和预加载,减少磁盘I/O;
  2. 数据不一致时,触发全量重建或使用版本号校验,结合监控告警。 判断原则是先确认原文对象、输入条件和适用边界是否成立;前提成立时按该机制处理,前提不成立时说明例外、风险和替代方案。

记忆锚点

记住:全量加载内存,增量Kafka投递,检索匹配快速。,先抓问题,再验机制,最后查边界。

衍生拓展

  • 复习重点:倒排索引原理与广告系统应用;- 常见误区:忽略索引碎片化问题;- 面试延伸:比较Lucene和Solr在广告检索中的优劣;- 实践扩展:使用Redis缓存热门广告索引提升性能。

落地场景

增量数据投递示例,使用Kafka生产者:

Java
1@Service
2public class IndexUpdateService {
3    @Autowired
4    private KafkaTemplate<String, String> kafkaTemplate;
5
6    public void sendAdUpdate(AdCreative creative) {
7        kafkaTemplate.send("ad-index-topic", JSON.toJSONString(creative));
8    }
9}
打开资料
05
外部资料

设计广告系统功能测试与接口验证

功能测试包括mock测试数据、应用服务接口测试和各模块HTTP接口测试。使用JUnit和Mockito进行单元测试,确保代码质量。接口测试通过Postman或自动化脚本验证HTTP端点。常见误区是测试覆盖不全,需结合集成测试和端到端测试。

诊断题

  1. 在广告系统中,如何mock外部依赖如Kafka或数据库进行单元测试?
  2. 设计广告接口测试时,如何保证测试数据隔离和可重复性?
  3. 继续追问 设计广告系统功能测试与接口验证 时,哪些边界、误区或应用判断最容易答错? 回答时请结合原文机制、适用边界、易混点和工程取舍。

答案骨架

我能设计功能测试策略:

  1. mock测试使用Mockito模拟服务依赖,如@MockBean注入模拟对象
  2. 接口测试使用RestAssured或SpringBootTest验证HTTP响应
  3. 适用边界是CI/CD流程中自动化测试
  4. 易混点是单元测试与集成测试边界,单元测单个类,集成测模块交互
  5. 衍生关联到测试覆盖率和性能测试。

边界追问

  1. 广告检索服务如何进行压力测试和性能基准?
  2. 在微服务环境下,如何实现契约测试确保服务兼容性?
  3. 如果把 设计广告系统功能测试与接口验证 落到真实项目,应该继续追问哪些输入条件、失败前提或成本取舍? 回答时请结合原文机制、适用边界、易混点和工程取舍。

边界答案

  1. 压力测试使用JMeter模拟高并发请求,监控响应时间和错误率;
  2. 契约测试通过Pact或Spring Cloud Contract定义接口契约,自动验证。 判断原则是先确认原文对象、输入条件和适用边界是否成立;前提成立时按该机制处理,前提不成立时说明例外、风险和替代方案。

记忆锚点

记住:mock依赖,接口验证,自动化测试全覆盖。,先抓问题,再验机制,最后查边界。

衍生拓展

  • 复习重点:测试驱动开发(TDD)在广告系统中的应用;- 易混点:测试替身(mock、stub、spy)的区别;- 面试延伸:如何设计广告系统的A/B测试框架;- 实践扩展:集成SonarQube进行代码质量检查。

落地场景

使用Mockito测试广告服务:

Java
1@SpringBootTest
2public class AdServiceTest {
3    @MockBean
4    private AdRepository adRepository;
5
6    @Autowired
7    private AdService adService;
8
9    @Test
10    public void testGetAdById() {
11        when(adRepository.findById(1L)).thenReturn(Optional.of(new Ad()));
12        Ad ad = adService.getAdById(1L);
13        assertNotNull(ad);
14    }
15}
打开资料
06
外部资料

说清 掌握Spring事务处理机制与分布式日志收集 的核心机制和失效边界

彩蛋内容涵盖Spring事务处理机制和分布式日志收集系统。Spring事务通过@Transactional注解管理,支持声明式事务。分布式日志使用ELK(Elasticsearch、Logstash、Kibana)实现日志收集、存储和可视化。常见误区是事务传播行为理解错误,导致数据不一致。

诊断题

  1. Spring中@Transactional的传播行为有哪些,在广告系统中如何选择?
  2. 搭建ELK分布式日志系统时,Logstash如何配置输入和输出以收集微服务日志?

答案骨架

我能掌握Spring事务和日志:

  1. Spring事务传播行为包括REQUIRED、REQUIRES_NEW等,在广告创建中常用REQUIRED保证原子性
  2. ELK中Logstash通过Filebeat或直接输入收集日志,输出到Elasticsearch
  3. 适用边界是需要强一致性时用事务,日志用于监控和调试
  4. 易混点是事务隔离级别与传播行为区别,隔离级别控制并发,传播行为控制事务边界
  5. 衍生关联到分布式事务解决方案如Saga模式。

边界追问

  1. 在微服务间调用中,如何实现分布式事务保证广告数据一致性?
  2. 日志系统如何设置告警规则,及时发现广告系统异常?
  3. 如果把 掌握Spring事务处理机制与分布式日志收集 落到真实项目,应该继续追问哪些输入条件、失败前提或成本取舍? 回答时请结合原文机制、适用边界、易混点和工程取舍。

边界答案

  1. 分布式事务可使用最终一致性模式,通过消息队列和补偿操作;
  2. 在Kibana中配置告警,基于日志关键词或阈值触发通知。 判断原则是先确认原文对象、输入条件和适用边界是否成立;前提成立时按该机制处理,前提不成立时说明例外、风险和替代方案。

记忆锚点

记住:事务注解管理,ELK日志收集,监控告警及时。,先抓问题,再验机制,最后查边界。

衍生拓展

  • 复习重点:Spring事务的异常回滚规则;- 常见误区:ELK部署中的性能瓶颈;- 面试延伸:比较ELK与EFK栈;- 实践扩展:使用Prometheus和Grafana监控广告系统指标。

落地场景

Spring事务示例:

Java
1@Service
2public class AdService {
3    @Transactional(propagation = Propagation.REQUIRED)
4    public void createAd(Ad ad) {
5        adRepository.save(ad);
6        // 其他操作
7    }
8}

ELK配置片段(logstash.conf):

TEXT
1input {
2  file {
3    path => "/var/log/ad-service/*.log"
4    start_position => "beginning"
5  }
6}
7output {
8  elasticsearch {
9    hosts => ["localhost:9200"]
10    index => "ad-logs"
11  }
12}
打开资料
SpringCloud 微服务广告系统设计与实现 | 博击长空