极光笔记 | DSP高并发应用实践

作者:极光高级工程师 ——陈策




导言



 

  • 广告业务简介

 

SSP:供应方平台,互联网有大量拥有用户流量的媒体网站和APP,他们可以通过发布广告进行流量变现。而SSP就是可以实现流量变现的媒体服务平台,媒体可以通过它进行广告资源的管理,分配,定价,筛选。

DSP: 需求放平台,互联网有大量的广告主需要寻找优质的媒体和用户来推广自己的产品,并产生收益。而DSP就是为广告主提供服务的平台,他们可以在平台上设置自己的广告、目标受众、地域、出价等。

ADX:广告交易平台,连接买方和卖方,ADX以拍卖的方式为各个DSP提供SSP委托管理的广告位和流量并最终决定竞得者。

  • 广告核心竞价流程

  1. 用户A访问媒体

  2. 媒体向ADX请求广告展示给用户A

  3. ADX向各个DSP发起竞价请求,询问是否需要竞价并传输用户A的设备信息、广告位信息等。

  4. DSP的竞价引擎接收到请求后,将用户数据和投放需求进行匹配,决定是否参与出价并作出响应,返回广告物料。这个过程必须在100ms内返回,否则会被ADX自动判定为放弃此次竞价。

  5. ADX接收到所有DSP的出价响应后由竞价决策服务进行竞拍,价高着得。并返回广告物料给APP。

  6. 用户A看到APP的广告,当前竞价流程结束。

下面主要介绍极光DSP系统实战。

DSP业务系统架构


DSP的高可用网络架构


内部服务使用kubernetes集群进行管理,可做到如下几点:

1. 水平扩缩容

通过k8s管理平台对应用进行扩容和缩容。

2. 故障转移

当node节点关机或挂掉后,node节点上的服务会自动转移到另一个node节点上,这个过程所有服务不中断。

3. 服务发现和负载均衡

当发生扩缩容时,无需配置自动实现服务发现和负载均衡。

4. 资源调度

当node节点上的cpu、内存不够用的时候,可以扩充node节点,新建的pod就会被kube-schedule调度到新扩充的node节点上。

DSP高性能技术框架及服务治理


极光DSP的技术框架选用了vert.x-web, vert.x-grpc并通过集成springcloud微服务组件对服务进行治理。

Vert.x


vert.x是基于事件模型的异步非阻塞框架,具有异步编程和高并发的特性,能够充分利用多核CPU的优势,支持海量连接。工作原理如下:

Vert.x 中主要有两种线程:Event Loop 线程 和 Worker 线程。其中,Event Loop 线程结合了 Netty 的 EventLoop,用于处理事件。每一个 EventLoop 都与唯一的线程相绑定,这个线程就叫 Event Loop 线程。Event Loop 线程不能被阻塞,否则事件将无法被处理,它是典型的异步步编程模型。为了充分利用多核 CPU 的性能,Vert.x 中提供了一组 Event Loop 线程。每个 Event Loop 线程都可以处理事件。为了保证线程安全,防止资源争用,Vert.x 保证了某一个 Handler 总是被同一个 Event Loop 线程执行,这样不仅可以保证线程安全,而且还可以在底层对锁进行优化提升性能。所以,只要开发者遵循 Vert.x 的线程模型,开发者就不需要再担心线程安全的问题,这是非常方便的。

Verticle 是vert.x的部署单元,网络请求通过acceptor线程将请求放到事件队列中,然后verticle进行处理。verticle可以被deploy多个实例,每个verticle从属于一个event loop线程,无论有多少请求处理,都只会被 这个event loop线程来处理。Acceptor线程也会轮询将事件发放给不通的verticle实例。

一个应用程序通常是由在同一个 Vert.x 实例中同时运行的许多 Verticle 实例组合而成。不同的 Verticle 实例通过向 Event Bus 上发送消息来相互通信。

总的来说,它以非阻塞IO的思想来实现高性能,非阻塞IO的实现,基于Event Loop Vertical和Worker Vertical的分离,在Vert.x中,Event Loop用于接收,并将短业务操作交由其内部的Vertical来处理,该模块是非阻塞的,这样可以保证请求的处理效率;阻塞任务通过Vert.x的事件机制脱离当前线程,转移到Worker Vertical中执行,并将执行结果返回给Event Loop Vertical。这一过程完成的核心是Event Bus,Event Bus中注册了所有的事件,通过事件匹配完成事件转移和结果返回,从而将整个流程衔接起来。相比传统的阻塞模型,相同的资源配置下,它能处理更高的并发。

当前极光实时竞价服务一个实例配置6c,12G。Verticle 类型使用standard verticle,服务启动发布12个verticle实例,内部使用future进行异步编程,对于IO阻塞操作(如redis,rpc)采用异步回调的同时设置超时时间。经测试,响应时间在100ms内,一个实例最高能处理到2800左右 的qps。

Grpc


特点:

1. Grpc 基于http2协议实现,在性能上比http1高出许多。

2. 使用protobuf进行数据传输,传递的数据量相比json要少很多

3. 支持异步请求

4. 允许在客户端取消rpc通信或者设置超时时间

5. 支持多语言

调用模型

Grpc 原理

gRPC 的客户端请求消息由 Netty Http2ConnectionHandler 接入,由gRPC 服务端负责将 PB 消息(或者 JSON)反序列化为 POJO 对象,然后通过服务定义查询到该消息对应的接口实例,发起本地 Java 接口调用,调用完成之后,将响应消息序列化为 PB(或者 JSON),通过 HTTP2 Frame 发送给客户端。

gRPC 线程模型由 Netty 线程 + gRPC 应用线程组成。

Netty  I/O 线程负责gRPC 请求消息的读取、响应消息的发送,HTTP/2 协议消息的编码和解码,NettyServerHandler 的调度。

gRPC service 线程负责将 gRPC 请求消息(PB 码流)反序列化为接口的请求参数对象,将接口响应对象序列化为 PB 码流,gRPC 服务端接口实现类调用。

gRPC 的线程模型遵循 Netty 的线程分工原则,即:协议层消息的接收和编解码由 Netty 的 I/O(NioEventLoop) 线程负责;后续应用层的处理由应用线程负责,防止由于应用处理耗时而阻塞 Netty 的 I/O 线程。

服务治理


缓存设计


1、创意倒排索引

这部分数据主要是指运营人员创建的广告活动、创意。当ADX用户流量过来时,如何快速的匹配到对应的广告活动,极光DSP采用倒排索引以及二级缓存的设计。

倒排索引即通过用户流量的特征去匹配对应的广告活动id,如:匹配定向地域在shenzheng,媒体为com.a 的广告活动,缓存数据类型采用Set,如:

二级缓存

二级缓存是指本地应用缓存和redis缓存。当运营人员添加广告活动后,同步任务每一分钟会将广告活动从mysql按倒排方式写入在redis集群,数据类型为Set。

如:广告活动1001配置定向地域在shenzheng,媒体为com.a;广告活动1002配置定向地域在guangzhou,媒体为com.a。则redis中存储如下:

当流量过来时,直接从本地应用缓存中获取,若获取不到,先设置空集合,防止高并发导致本地缓存击穿,同时从redis中获取并更新本地缓存,缓存有效期设置为 1min。

 

当然由于我们每一次都先从本地缓存获取,若查询不到会先设置空集合再查询redis,虽然保证了我们广告检索的高性能,但同时也丢失了部分并发请求匹配成功的机会。我们的考量是在海量的流量下,具有部分相同特征的流量非常多,因而选择了性能,放弃部分由于并发导致第一次匹配失败的机会,后续可能会有一些优化。业务流程图如下:

2、人群包

作为DSP来说,人群包的准确性很大程度决定了广告的投放精准度。同时不同的广告主有着不同的定向人群,1个人群包量级一般在几千万 到几亿,极光DSP目前在用人群包有100个左右,为了保证RTB在人群过滤时的高性能,人群包数据都是预加载到redis集群,定时进行更新。

Redis存储数据类型为Set,如:

 

注:key 保存的是md5后的设备号再转成16进制字节数组。

另由于人群包数量较大,按当前存储方式,极光DSP人群包占用redis内存约在500G左右,我们使用了100个实例的redis集群(主从)来进行存储,如:

3、人群标签

RTB中人群标签的作用主要有两点:

1. 提高广告投放的精准度

2. 用于CTR预估模型进行出价

人群标签的存储类似人群包也是预加载到redis集群,定时进行更新。

由于人群包标签数量也非常巨大,为了减少redis集群存储,极光DSP采用hash数据类型对人群标签进行存储同时标签value使用bitset。如:

使用hash数据类型主要基于以下两个方面的考虑:

1. 减少存储key 

Redis 使用全局hash表来保存所有的键值对,hash表每一项都是dictEntry结构体,用来指向一个键值对。DictEntry结构中有三个8字节指针,分别指向key,value,下一个dictEntry。若减少key能降低这部分元数据的存储。

2. Hash 底层数据结构使用压缩列表或者hash表,只有当field个数大于hash-max-ziplist-entries或者单个value大于hash-max-ziplist-value 时,hash 底层数据结构才会使用hash表。故只要将field个数以及value大小控制好,使用压缩列表存储可以减少存储空间。

RTA策略设计


极光DSP中RTA是指在广告检索过程中实时询问广告主当前流量是否匹配的功能。但是由于机房位置,广告主接口性能等问题并不是所有RTA接口都能做到实时并满足RTB的性能要求,故我们采用了实时+离线设计方案(如下图)。即当给广告主配置实时RTA标识时,走实时方案,否则走离线方案。

 

异步方案:RTB先从redis中查询RTA缓存结果,若不存在,则根据RTA配置策略判断当前用户流量是否匹配,同时将RTA询问请求异步发送kafka,由RTA处理模块消费消息询问对应广告主结果,最终缓存到redis中,当用户流量第二次过来就能直接从redis中拿到对应结果了。

同步方案:RTB实时请求广告主RTA接口询问当前用户流量是否匹配同时设置超时时间为30ms。若超时,则按RTA配置策略来决策当前流量是否匹配。

总结


极光DSP每天接收100亿级流量而稳定运行,SLA保持在99.9%,主要依赖以上高可用的网络架构,高性能技术框架以及高效的缓存、业务设计的支撑。当然我们也还有很多需要改善的地方如:

1. 为进一步提升服务的可用性可部署同城双活;

2. 对k8s集群节点按业务模块分类,将各业务模块服务部署到指定分类节点,进一步提升节点cpu 和 memery的利用率;

3. 人群包大redis存储的优化。

关于极光

极光(Aurora Mobile,纳斯达克股票代码:JG)成立于2011年,是中国领先的移动开发者服务提供商,专注于为开发者提供稳定高效的消息推送、一键认证以及流量变现等服务,助力开发者的运营、增长与变现。同时,极光的行业应用已经拓展至行业洞察、金融风控与商业地理服务,助力各行各业优化决策、提升效率。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值