自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

OpenResty在騰訊游戲營銷技術(shù)中的應(yīng)用和實(shí)踐

開發(fā) 開發(fā)工具 前端
我的分享會(huì)偏重 OpenResty 的應(yīng)用,不會(huì)涉及到太多 OpenResty 具體的技術(shù)細(xì)節(jié)方面,主要是想通過一些應(yīng)用的案例來把一些優(yōu)化的思想跟大家做一個(gè)分享,來拋磚引玉。

大家上午好,我是來自騰訊的Shawn顧小平。先做一個(gè)簡單的自我介紹。我在加入到騰訊之前一直在通訊行業(yè)里面從事通信軟件的研發(fā)工作,包括在華為,還有UT斯達(dá)康。

2012年10月份我加入到騰訊,現(xiàn)在在騰訊互動(dòng)娛樂事業(yè)群負(fù)責(zé)部分的營銷技術(shù)相關(guān)的工作。我接觸的技術(shù)工作比較多、也比較雜,所以我自稱是全“沾”工程師,不敢自稱是全棧工程師。從底層的單片機(jī)到嵌入式、協(xié)議棧開發(fā),再到上層應(yīng)用開發(fā),也做過游戲的后臺(tái),現(xiàn)在在做營銷相關(guān)的一些技術(shù),所以各種技術(shù)都沾過,不一定很深入,但是都接觸過一些。

[[261864]]

我今天要分享的內(nèi)容主要包括兩大塊:

  • 第一塊就是 OpenResty 在騰訊游戲營銷 類API 網(wǎng)關(guān)中的應(yīng)用
  • 第二塊是 OpenResty 在騰訊游戲廣告投放系統(tǒng)中的應(yīng)用

我的分享會(huì)偏重 OpenResty 的應(yīng)用,不會(huì)涉及到太多 OpenResty 具體的技術(shù)細(xì)節(jié)方面,主要是想通過一些應(yīng)用的案例來把一些優(yōu)化的思想跟大家做一個(gè)分享,來拋磚引玉。

OpenResty 在騰訊游戲營銷 API 網(wǎng)關(guān)中的一個(gè)應(yīng)用

進(jìn)入到第一個(gè)分享案例, OpenResty 在騰訊游戲營銷 API 網(wǎng)關(guān)中的一個(gè)應(yīng)用,下面有一個(gè)一個(gè)帽子,可能大家會(huì)比較奇怪,如果大家看過《海賊王》的同學(xué)可能就會(huì)比較熟悉,這個(gè)就是《海賊王》里面路飛的帽子,也是我們內(nèi)部 API 網(wǎng)關(guān)的 logo,我們團(tuán)隊(duì)把所有做的公共性的組件、平臺(tái)性的東西都以《海賊王》里面的名字進(jìn)行命名,當(dāng)然還有很多。

接下來就看一看我們?yōu)槭裁匆惨?API 網(wǎng)關(guān),做 API 網(wǎng)關(guān)的業(yè)務(wù)背景是怎么樣的,因?yàn)槲覀兪菢I(yè)務(wù)開發(fā)團(tuán)隊(duì),一個(gè)新游戲上線之前,它是需要做大量的營銷推廣類活動(dòng),包括各種簽到、運(yùn)營、抽獎(jiǎng)等活動(dòng)。形態(tài)也各有不同,比如小游戲、小程序這種推廣類的、H5l引導(dǎo)類的等等。

除此之外,每個(gè)游戲它都有一個(gè)自己的微社區(qū),在每個(gè)游戲的 APP 的入口可以進(jìn)到里面去,提供一些資訊、攻略、個(gè)人數(shù)據(jù),還有一些積分,排名等等的功能,也包括賽事直播的一些內(nèi)容在里面。

每個(gè)游戲都有這樣大量的活動(dòng),并且這個(gè)游戲的數(shù)量還是非常大的。然后它訪問的后臺(tái)的流量也是非常大的,會(huì)遠(yuǎn)遠(yuǎn)超過這里面提到的數(shù)字。

面對這樣一個(gè)比較復(fù)雜的業(yè)務(wù),我們一開始的時(shí)候是怎么樣做的呢?在功能的層面,我們就把它劃分了很多這樣相似的功能模塊,大概有二三十個(gè)這樣的功能模塊,模塊化之后是不是就沒有問題呢?但其實(shí)問題依然存在,主要包括兩個(gè)方面:

  • 第一個(gè)方面:在開發(fā)階段還是有大量重復(fù)性的、非功能性的模塊的開發(fā),比如:身份驗(yàn)證、登陸校驗(yàn)、流量控制、頻次控制、安全等等這樣的事情要做。
  • 第二個(gè)方面:就是線上運(yùn)行的時(shí)候也存在大量的防刷,異常用戶行為,需要進(jìn)行行為控制和分析,包括防刷、秒殺、抽獎(jiǎng)?lì)惢顒?dòng)的一些流量控制等干預(yù)。

這樣的問題都讓我們?nèi)ニ伎?,怎么樣去做到功能性的開發(fā)和非功能性保障的獨(dú)立,以及怎么樣去做統(tǒng)一的流量控制,那這個(gè)其實(shí)就是 API 網(wǎng)關(guān)要做的事情了,所以接下來我們對業(yè)界 API 網(wǎng)關(guān)的方案做了大量的考察和分析,大概會(huì)分為2大類:

API

第一類就是開源的方案,開源方案里面有我們比較熟悉的基于 OpenResty 的orange、KONG,還有其他語言的,比如 go 語言、Java 語言都有自己的 API 網(wǎng)關(guān)的方案。

第二個(gè)就是云的方案,各個(gè)主流的云廠商都有自己的 API 網(wǎng)關(guān)的解決方案,這些方案都有各自的優(yōu)缺點(diǎn),但是都有一個(gè)共同的問題,就是都不能滿足我們業(yè)務(wù)個(gè)性化的需求,包括很多定制化的需求。另外還有一個(gè)問題,它不能和我們現(xiàn)有的,特別是大公司里面,現(xiàn)有的組件、平臺(tái)要去做對接,要去做一個(gè)融合,這個(gè)很難做得到,因?yàn)樗皇情_源的。

所以我們基于此選擇一個(gè)最簡單的、最簡化版的開源方案,就是 orange 的方案去做一個(gè)完全的定制化。

在定制化之前,我們看一下 orange 這個(gè)方案會(huì)有哪些問題或者不能滿足需求的方面,我們從五個(gè)方面去看,這五個(gè)方面也是我們做任何技術(shù)方案選型或者考察評估的時(shí)候,可以去分析的點(diǎn):

orange

我們具體來看一下,orange 在這五個(gè)方面的不足吧:

  • 易用性:orange 還是沒有面向我們業(yè)務(wù)同學(xué)比較熟悉的基于應(yīng)用、服務(wù)、API的配置和管理的操作界面
  • 可用性: orange 把網(wǎng)關(guān)本身的可用性和配置節(jié)點(diǎn)的可用性都交給我們自己來保證。
  • 性能:隨著規(guī)則數(shù)增加,性能下降是非常明顯的。
  • 安全性:僅有一些黑白名單和一些通用的認(rèn)證規(guī)則、認(rèn)證的插件,用不太上。
  • 可維護(hù)性:也是有一些缺失,在錯(cuò)誤日志和染色日志,還有調(diào)用跟蹤定位等等方面還是有缺失的。

接下來我們就從五個(gè)方面來說一下,我們是怎么樣做優(yōu)化和思考的:

易用性方面優(yōu)化

第一個(gè)是在易用性方面優(yōu)化,這里面有兩張圖,左邊這張圖是 orange管理端的截圖,我們看得出來里有提供了很豐富的技術(shù)型的插件,有URL的重定向、重寫,還有各種認(rèn)證,還有限速,還有安全等等。那么它存的問題是什么呢?舉個(gè)簡單例子,就是我們要添加一個(gè)新的 API,那我要到所有的插件里面配置這個(gè)API 的 URL,插件下面還有選擇器,以及規(guī)則都要去操作一遍,非常的重復(fù)和麻煩。

第二個(gè)問題就是對業(yè)務(wù)開發(fā)人員來說,他的思維和操作習(xí)慣,會(huì)更加關(guān)注業(yè)務(wù),比如更加關(guān)注我的某個(gè)個(gè)應(yīng)用,某個(gè)應(yīng)用下面的某個(gè)服務(wù),某個(gè)服務(wù)于下面的某個(gè)API的使用情況(認(rèn)證、校驗(yàn)、安全、流控、統(tǒng)計(jì)等等方面的運(yùn)行情況或者執(zhí)行情況)。

所以這里有一句話就是在做易用方面的設(shè)計(jì)的時(shí)候要更加多的去考慮面向業(yè)務(wù),而不是面向技術(shù),我看好像KONG的配置界面也有做service的概念,越是有這個(gè)方面的考慮。

可用性方面的優(yōu)化

第一個(gè)就是可用性方面的優(yōu)化,可用性這個(gè)事情,大公司里面會(huì)相對比較容易一點(diǎn),因?yàn)榇蠊居凶约焊涌煽康脑O(shè)備或者是組件來保證底層、下面節(jié)點(diǎn)的可用性。而騰訊內(nèi)部有這樣一個(gè)接入層網(wǎng)關(guān)的組件叫做 TWG/STGW,它們一開始是為了把不同的運(yùn)營商的流量匯集到騰訊自己的機(jī)房里面來,同時(shí)也來做負(fù)載均衡、容錯(cuò)等等一些可用性的保障。所以網(wǎng)關(guān)本身節(jié)點(diǎn)的可用性這個(gè)事情就很簡單,直接把這個(gè) API 網(wǎng)關(guān)節(jié)點(diǎn)掛到這個(gè) TGW/STGW 上面來就可以了,最后三臺(tái)網(wǎng)關(guān)機(jī)器跨機(jī)房部署,在容災(zāi)層面做了進(jìn)一步的可用性的保證。

第二個(gè)方面就是配置節(jié)點(diǎn)的可用性的優(yōu)化,配置節(jié)點(diǎn)存放配置信息,配置信息雖然很小的,但也可以做一些簡單的優(yōu)化,最簡單就是獨(dú)立部署 MySQL 或者是 Redis,把配置信息放到這些地方去,然后自己去保證mysql/redis的可用性。

第三個(gè)還可以用 MySQL 或者更輕量級的 sqlite 去存放這個(gè)配置的信息,由管理端自己去保證它的可用性,管理端每次添加新的 API 的時(shí)候,同時(shí)去寫入到這三個(gè)配置節(jié)點(diǎn)里面去,然后同時(shí)寫入到 API 網(wǎng)關(guān)的共享內(nèi)存里面去,這樣輸入粗暴,但是簡單省事,對我們快速上線的東西來說還是可以用的。

最后一個(gè)方法就是用ETCD ,把配置信息存放到ETCD里面,利用ETCD去中心化的協(xié)議去做保證它的可用性,以及一致性。這個(gè)方案相對會(huì)比較完美一點(diǎn),但是它有一個(gè)問題就是我們要去 API 網(wǎng)關(guān)里面編寫新的代碼監(jiān)聽 ETCD等操作,我們也在逐步地向這個(gè)方案過渡。

性能優(yōu)化

第三個(gè)就是性能優(yōu)化,一開始我們對orange 的性能做了一個(gè)初步的測試,發(fā)現(xiàn)Orange性能隨著它的規(guī)則數(shù)量增加,QPS 下降還是比較明顯的,然后我們就去做火焰圖的分析,分析之后發(fā)現(xiàn) 60% 的操作都會(huì)消耗在 json 操作和正則表達(dá)式的匹配操作中去,并且 json 操作占了大頭。

對我們來說第一反應(yīng)就是 json 操作花了這么多時(shí)間,我們是不是可以去用一個(gè)更加高性能的 json 的處理庫去替換 orange 里面的 Cjson呢,對于騰訊的同學(xué)來說,都比較熟悉的是RapidJSON,因?yàn)檫@是騰訊第一個(gè)開源的項(xiàng)目,很快就把 RapidJSON 替換掉 orange 里面的cJSON,發(fā)現(xiàn)效果還非常明顯,一下子就提升了 10%+ 的性能。

接下來是不是這樣就 OK 了呢?我們繼續(xù)問一下為什么要做這件事情,簡單閱讀了下代碼,原因是還是非常簡單,就是orange 自己每一次 http 請求的時(shí)候,每一個(gè) worker 收到請求的時(shí)候都會(huì)到共享內(nèi)存里面去拉取配置信息,然后去做一個(gè)json反系列化操作,變成每個(gè) worker 的數(shù)據(jù)結(jié)構(gòu),不管這個(gè)配置信息有沒有更新,都去做這件事情,作者可能是為了自己的考慮,有配置更新的時(shí)候,這樣實(shí)時(shí)能知道。

我們接下來再去問自己第二個(gè)問題,就是能否不做這件事情,對我們來說,犧牲一點(diǎn)實(shí)時(shí)性,一個(gè)配置更新過半分鐘或者隔幾秒鐘得到這個(gè)配置最新信息,我們是可以接受的。所以我們很簡單就可以去掉上面頻繁的系列化操作,就是直接起一個(gè) Timer 去過一段時(shí)間 check 一下這個(gè)共享內(nèi)存里面有沒有配置信息的更新標(biāo)志即可,非常簡單的這樣一個(gè)優(yōu)化就直接把這部分的 JSON 操作直接去掉了。

所以這里有一個(gè)體會(huì)是最大的優(yōu)化是不做或者是柔性的平衡,這種柔性平衡可能會(huì)包括很多方面,犧牲一些其他的資源來得到性能,犧牲內(nèi)存得到性能,或者犧牲一些實(shí)時(shí)性得到性能,還包括犧牲一些產(chǎn)品的體驗(yàn)得到性能,這些都是柔性的平衡,可能需要我們花更多時(shí)間去思考。

接下來我們就去做進(jìn)一步的優(yōu)化,因此我們做一個(gè)完整的性能測試,一個(gè)完整的性能測試主要會(huì)包括這么七個(gè)環(huán)節(jié),前面的三個(gè)環(huán)節(jié)都是為了第四個(gè)環(huán)節(jié)的壓力測試做準(zhǔn)備的,包括環(huán)境準(zhǔn)備、配置調(diào)優(yōu)、靜態(tài)檢查等等。

這里面環(huán)節(jié)當(dāng)然也有自己要去注意的事情,環(huán)境準(zhǔn)備雖然很簡單,但也要考慮一些問題,就是測試機(jī)的性能和壓測工具的性能往往也會(huì)有問題里面。還有測試機(jī)和被測試機(jī)的時(shí)延等等,都需要考慮,否則會(huì)影響我們測試出來的真實(shí)性。

其他的話配置調(diào)優(yōu)和靜態(tài)檢查這兩塊參考一些通用總結(jié)的經(jīng)驗(yàn)就可以去做了。

下面就開始做壓力測試,壓力測試需要注意的是要盡量去模擬現(xiàn)網(wǎng)的真實(shí)環(huán)境和現(xiàn)網(wǎng)的處理流程去做,如果我們只是簡單做一個(gè)echo測試的話,雖然這個(gè)性能數(shù)據(jù)很高,但不一定很真實(shí),有參考價(jià)值。所以我們在騰訊內(nèi)部的一個(gè)C1的機(jī)型上面,模擬真實(shí)現(xiàn)網(wǎng)流量和配置,大概測試出來的數(shù)據(jù)在18000 QPS。這個(gè)數(shù)據(jù)比之前采用了 PHP 的同步阻塞的傳統(tǒng)的 CGI 的方式肯定是要高一個(gè)數(shù)量級的,但不一定就沒有優(yōu)化的空間了。

所以接下來我們繼續(xù)去做瓶頸分析、性能分析。性能分析就用到了我們性能分析神器:火焰圖,OpenResty社區(qū)的同學(xué)都非常熟悉火焰圖

我們把 CPU 消耗前10的操作做一個(gè)歸納,歸納出來有這么幾類操作,第一個(gè)是 JSON 的操作占了9.18%。第二是 L5 的操作占了4.74%(L5是騰訊內(nèi)部的一個(gè)負(fù)載均衡服務(wù)的組件),另外一個(gè)就是正則表達(dá)式匹配占了 10.36%。其他的就是nginx的操作以及系統(tǒng)調(diào)用等。

接下來我們就對這三個(gè)方面的操作,看看是不是有優(yōu)化的空間。首先我們看一下 L5 的這個(gè)操作有沒有優(yōu)化的空間,剛剛說 L5 是騰訊內(nèi)部的一個(gè)負(fù)載均衡的組件,我們就把它也集成到 API 網(wǎng)關(guān)里面來了,他們的工作原理會(huì)跟本機(jī)的 L5agent 進(jìn)行通訊,所以我們在做壓力測試的時(shí)候要去看一下,在壓力測試這么大流量的情況下,L5agent 是不是有 CPU 消耗,或者它有沒有出錯(cuò),接下來再看一下它的日志和出錯(cuò)情況是否正常的,然后再把這個(gè)用 FFI 的方式替換我們之前的Lua C/API的方式,看看有沒有性能的提升。我們又再進(jìn)一步去分析 L5 這個(gè)操作,發(fā)現(xiàn)它是用了阻塞的 UDP 的調(diào)用,所以這里是有風(fēng)險(xiǎn)的,它會(huì)影響到其他的協(xié)程的執(zhí)行的,所以我們需要盡量地把它的超時(shí)時(shí)間設(shè)得更短一點(diǎn),也嘗試看看能否用 cosocket 的方式去實(shí)現(xiàn) L5 的API,但發(fā)現(xiàn)協(xié)議沒有開源等等,經(jīng)過這一些列的嘗試,最后放棄了這部分的優(yōu)化。

接下來就是 JSON 操作的優(yōu)化,有前面的經(jīng)驗(yàn)之后,我們做性能優(yōu)化的時(shí)候就會(huì)問自己兩個(gè)問題。第一個(gè)問題為什么要做這件事情,分析發(fā)現(xiàn),是因?yàn)槲覀兒蠖说姆?wù)把所有響應(yīng)的數(shù)據(jù)都做了一個(gè)JSON encode,然后API網(wǎng)關(guān)會(huì)進(jìn)行JSON decode然后去去提取里面的一個(gè)返回碼,根據(jù)后端返回的返回碼的不同,向前端返回是200OK還是其他的HTTP的不同的響應(yīng)碼,僅僅做這樣一件事情。那繼續(xù)問第二個(gè)問題能否不做,很顯然是可以的,就是我們可以直接讓后端返回?cái)?shù)據(jù)的時(shí)候把返回碼字段獨(dú)立出來, API 網(wǎng)關(guān)的直接拿到返回碼做一個(gè)判斷即可,然后把數(shù)據(jù)字段直接轉(zhuǎn)發(fā)給前端就 OK 了。非常簡單的一個(gè)優(yōu)化,直接就可以省掉了這部分的 JSON 操作。

另外 JSON 操作確實(shí)會(huì)消耗我們很多 CPU 的性能,我們一些同學(xué)也經(jīng)常在 debug 里面去打印,想把這個(gè) debug 日志里面去打印很多數(shù)據(jù)結(jié)構(gòu)里面的內(nèi)容(用json.encode來打印),然后放到生成環(huán)境上去,雖然這個(gè) debug 操作是不會(huì)執(zhí)行,但是這個(gè)函數(shù),JSON encode操作是會(huì)執(zhí)行的,這樣的話會(huì)導(dǎo)致生產(chǎn)環(huán)境極大的性能損耗,等等這樣類似的情況還是非常多的,所以我們在實(shí)際過程當(dāng)中還是要去留意這樣一些不好的編碼的習(xí)慣。

正則表達(dá)式匹配的優(yōu)化

第三個(gè)就是正則表達(dá)式匹配的優(yōu)化。大家知道正則表達(dá)式匹配都是由正則表達(dá)式引擎來做的,常用的正則表達(dá)式引擎就是PCRE,于是我們就去考慮有沒有更加高性能的正則表達(dá)式匹配的引擎呢?我們也去做了一些調(diào)研,正則表達(dá)式應(yīng)用最多的領(lǐng)域其實(shí)是在安全領(lǐng)域里面,安全領(lǐng)域里面有這樣的的IPS、IDS 這樣的一些安全檢測和防御性的產(chǎn)品里面會(huì)大量地使用正則表達(dá)式匹配的操作,它之前也是用 PCRE 來做正則表達(dá)式的匹配。后來就是在這兩年的時(shí)候,都統(tǒng)一切換到了英特爾開源的 Hyperscan 這樣的正則表達(dá)式引擎來了。

為什么它會(huì)去做這樣的改變呢?Hyperscan 正則表達(dá)式引擎比這個(gè)PCRE有哪些優(yōu)勢呢?分析后發(fā)現(xiàn)它有這么幾個(gè)方面的不一樣或者說優(yōu)點(diǎn)。

  • 第一個(gè)就是它不僅僅是支持塊模式,還支持流模式。所謂的流模式就是跨不同的網(wǎng)絡(luò)包去做一個(gè)匹配,這個(gè)對安全產(chǎn)品是非常有用的。
  • 第二個(gè)就是它一次可以編譯多個(gè)規(guī)則,大家知道正則表達(dá)式最后都會(huì)編譯成狀態(tài)機(jī)到內(nèi)部去做匹配的操作。
  • 第三個(gè)就是一個(gè)輸入多個(gè)規(guī)則只匹配1次,它可以并行匹配多個(gè)規(guī)則,這個(gè)是很厲害的。它的性能可能會(huì)很高,所以我們接下來我們就去做了這樣一個(gè)驗(yàn)證,就是把30萬條http get 請求(包括 URL),寫到一個(gè)文本里面去。然后每個(gè)參數(shù)都做一個(gè)正則表達(dá)式的匹配,用 PCRE 的代碼和 Hyperscan 的代碼去讀這個(gè)文件,一條條讀,然后匹配每一個(gè)規(guī)則。發(fā)現(xiàn) Hyperscan 匹配正則表達(dá)式所以花費(fèi)的時(shí)間確實(shí)比PCRE所花的時(shí)間低很多,大概只有后者的30%左右的樣子。所以接下來我們就非常果斷地把它引入到我們的 API 網(wǎng)關(guān)里面來,用火焰圖繼續(xù)驗(yàn)證, CPU 的消耗,從之前的10%+降低到7%只有了。

所以接下來是不是還有可以優(yōu)化的空間?當(dāng)然有,就是開啟它的并性匹配度規(guī)則的操作,這個(gè) Hyperscan 里面也是提供了回調(diào),然后我們只需要把每個(gè)規(guī)則設(shè)置一個(gè)標(biāo)志位,然后去匹配完之后檢查這個(gè)標(biāo)志位以后就OK了,就可以做得到了。

另外還有一件事情是什么呢?就是正則表達(dá)式規(guī)則編寫難度的問題,我們不能要求業(yè)務(wù)開發(fā)同學(xué)每次都要去編寫正則表達(dá)式,這個(gè)對他們來說也不一定編寫得正確,也有一些學(xué)習(xí)的成本在里面。所以我們就去看了一下大部分的參數(shù)還是比較類似的,所以就把這些參數(shù)的正則表達(dá)式做一些歸納,然后用一些文字性的描述,做了一個(gè)模板,業(yè)務(wù)人員就可以直接去選擇這些模板就OK了,也很好的解決了這個(gè)問題。

安全性方面的優(yōu)化

第四個(gè)方面的優(yōu)化就是安全性方面的優(yōu)化。安全性方面的優(yōu)化要做的一件事情就是,它需要把我們這個(gè) API 網(wǎng)關(guān)的安全策略去和公司現(xiàn)有的一些安全的產(chǎn)品做結(jié)合。騰訊內(nèi)部有這樣的自己的安全產(chǎn)品,叫門神,所以我們在 http 請求進(jìn)來post read階段就去和安全產(chǎn)品做一個(gè)交互,讓它去過濾流量。它過濾的流量沒有問題之后,再進(jìn)入到我們的安全策略里面。當(dāng)然這個(gè)安全策略也相對會(huì)比較簡單,包括有 API 白名單,配置到 API 的流量才可以進(jìn)到里面來。然后還有基于用戶過濾的黑白名單,還有登錄校驗(yàn),支持騰訊的手Q、微信等的多種校驗(yàn)方式,也都把它集成進(jìn)來了。

另外去做參數(shù)校驗(yàn),參數(shù)校驗(yàn)則用前面提到的正則表達(dá)式做非常嚴(yán)格的必選參數(shù)的校驗(yàn)。另外就是如果做了非常嚴(yán)格的正則表達(dá)式匹配的話,SQL 防注入等等這樣的問題也不會(huì)有。這個(gè)就是安全性方面的優(yōu)化。

可維護(hù)性方面的優(yōu)化

最后就是可維護(hù)性方面的優(yōu)化,我們也做了兩點(diǎn):

  • 第一是添加了一些日志和統(tǒng)計(jì)的功能。例如,把 4xx/5xx 等一些錯(cuò)誤日志獨(dú)立出來,另外就是添加基于某個(gè)用戶id后者請求id的染色日志跟蹤打印。
  • 第二個(gè)方面的優(yōu)化不一定屬于今天講的內(nèi)容里面的,就是我們也做了調(diào)用鏈跟蹤系統(tǒng)。API 網(wǎng)關(guān)在這個(gè)調(diào)用鏈跟蹤系統(tǒng)里面是作為起點(diǎn),它會(huì)去生成Trace id,以及創(chuàng)建調(diào)用鏈的上下文,以及結(jié)束調(diào)用鏈,另外就是還可以控制調(diào)用鏈跟蹤的采集的頻率等。

那到這里就快速簡單介紹了一下第一個(gè)應(yīng)用案例,在易用性、可用性、性能,還有安全性以及可維護(hù)性這五點(diǎn),我們的一些思考和優(yōu)化的過程。

OpenResty 在騰訊游戲、廣告投放系統(tǒng)中的應(yīng)用案例

接下來進(jìn)入到第二部分,就是 OpenResty 在騰訊游戲、廣告投放系統(tǒng)中的應(yīng)用案例。還是和之前的內(nèi)容一樣,我不會(huì)涉及到很多具體的 OpenResty 的技術(shù)的細(xì)節(jié),主要是想跟大家分享一下案例,以及在這個(gè)案例里面一些優(yōu)化的思想。

這個(gè)案例相對會(huì)比較大膽一點(diǎn),因?yàn)榇蟾膨v訊游戲有好幾個(gè)億的營銷費(fèi)用都會(huì)通過這個(gè)系統(tǒng)投放出去。廣告投放的形式有很多種,有包段廣告位的、包段時(shí)間段的、包段流量的,還有普通競價(jià)的,還有實(shí)時(shí)競價(jià)的。今天我想跟大家分享的就是實(shí)時(shí)競價(jià)的廣告投放形式和我們 OpenResty 的一個(gè)結(jié)合,以及 OpenResty 在里面的優(yōu)化。

什么是實(shí)時(shí)競價(jià)廣告?以及實(shí)時(shí)競價(jià)廣告的流程是怎么樣的?這里面有一個(gè)圖。我們從最右邊往左看,最右邊就是我們的用戶打開手機(jī)看內(nèi)容,比如看頭條里面的內(nèi)容或者刷新聞。過程中會(huì)看到有廣告位的,當(dāng)刷到有廣告的那個(gè)頁面的時(shí)候,這個(gè)時(shí)候 APP 就會(huì)向 ADX (廣告交易平臺(tái))服務(wù)器發(fā)一個(gè)廣告請求。廣告交易平臺(tái)服務(wù)器收到這個(gè)廣告請求之后,它會(huì)去把這個(gè)廣告請求分發(fā)給下面的廣告主的 DSP 服務(wù)器,當(dāng)然DSP 服務(wù)器可能會(huì)有很多家,一般來說只有大型的廣告主才會(huì)有自己的 DSP 服務(wù)器。

騰訊游戲作為一個(gè)比較大型的廣告主,它也有自己的 DSP 服務(wù)器。它收到的廣告請求之后會(huì)怎么做呢?它會(huì)把這個(gè)廣告請求里面的流量到它的DMP(數(shù)據(jù)管理平臺(tái))數(shù)據(jù)庫里面去做一個(gè)判斷,怎么判斷?就是這個(gè)用戶是不是我需要的,如果是我需要的話,我應(yīng)該給他評估一個(gè)怎樣的價(jià)錢,就是說我愿意出多少錢給來獲得這個(gè)用戶的這個(gè)廣告曝光機(jī)會(huì)。

這里面會(huì)涉及到一些機(jī)器學(xué)習(xí)的算法去評估這個(gè)出價(jià),最終確定了出價(jià)之后,他會(huì)把這個(gè)出價(jià)原路返回給 ADX 服務(wù)器。ADX 服務(wù)器收到這個(gè)出價(jià)之后,它會(huì)等待其他廣告主的 DSP服務(wù)器的出價(jià),放在一起比較來最終選擇最高出價(jià)的廣告主的廣告,然后把這次廣告曝光的機(jī)會(huì)給到這個(gè)廣告主,展示這個(gè)廣告主的廣告素材,這個(gè)就是一個(gè)比較簡化的實(shí)時(shí)競價(jià)廣告的流程。

里面需要做的一個(gè)事情就是,在這個(gè) ADX 和 DSP 服務(wù)器之間的交互是通過 OpenRTB 協(xié)議來做的,這里面有兩個(gè)問題需要解決:

  • 第一個(gè)是流量非常大,ADX所有的廣告請求都會(huì)發(fā)給 DSP 服務(wù)器,有些大的媒體可能有好幾萬個(gè)QPS,如果好幾家的話加起來很輕松會(huì)超過十萬QPS。
  • 還有一個(gè)問題就是 ADX要求所有的DSP 必須在 100 毫秒返回出價(jià)響應(yīng),這個(gè)100ms包括網(wǎng)絡(luò)上的時(shí)間,如果 100 毫秒之內(nèi)我沒有收到你響應(yīng)的話,我就視為你放棄了這個(gè)出價(jià)。

當(dāng)然實(shí)時(shí)競價(jià)廣告技術(shù)方面有很多挑戰(zhàn),主要有這么幾塊的挑戰(zhàn)。

  • 第一個(gè)就是在數(shù)據(jù)方面,包括標(biāo)簽挖掘、人群擴(kuò)散、畫像分析,還有一些實(shí)時(shí)分析、透視分析來輔助刷選投放目標(biāo)人群,這個(gè)是在數(shù)據(jù)方面的技術(shù)挑戰(zhàn)。
  • 第二個(gè)就是算法,算法會(huì)包括兩個(gè)比較核心的算法。第一個(gè)就是 pCTR,第二個(gè)就是pCVR,pCTR 就是點(diǎn)擊率預(yù)估算法,pCVR是轉(zhuǎn)化率預(yù)估算法,這個(gè)轉(zhuǎn)化可能會(huì)包括多個(gè),有下載、注冊、付費(fèi)、活躍等等都屬于轉(zhuǎn)化。這兩個(gè)算法會(huì)用到現(xiàn)在比較熱的一些機(jī)器學(xué)習(xí)的算法在里面。
  • 第三個(gè)方面的挑戰(zhàn)就是在系統(tǒng)層面的挑戰(zhàn),剛才提到了 ADX 和 DSP 服務(wù)器,它之間會(huì)有比較高的QPS,另外就是時(shí)延有要求,100毫秒的要求。今天我分享的內(nèi)容主要是偏重于在第三塊,就是在系統(tǒng)層面怎么和 OpenResty 進(jìn)行結(jié)合。

這個(gè)是實(shí)時(shí)競價(jià)廣告系統(tǒng)在系統(tǒng)側(cè)的一個(gè)架構(gòu)簡圖,最上面是流量層,各ADX的廣告請求流量會(huì)發(fā)到下面的接入層。接入層又包括兩部分,一個(gè)是靜態(tài)的 CDN,一個(gè)是動(dòng)態(tài)的 RTB 網(wǎng)關(guān),CDN 存放廣告的素材,RTB 網(wǎng)關(guān)會(huì)做一件事情,就是進(jìn)行 OpenRTB 協(xié)議的編解碼,此外還會(huì)做一些安全和流量控制等操作。

在邏輯層包括競價(jià)引擎,最下面的就是數(shù)據(jù)層包括 DMP 數(shù)據(jù)管理平臺(tái)。這兩個(gè)部分做的事情就是我們剛剛說的,一起來確定這個(gè)廣告請求是不是我們需要的用戶,如果是我們需要的用戶的話,我們怎么樣給它估算一個(gè)價(jià)錢。

這里面標(biāo)了橙黃色字體的,就是我們用 OpenResty 進(jìn)行過重構(gòu)或者說優(yōu)化過的地方,包括接入層的 RTB 網(wǎng)關(guān),還有邏輯層競價(jià)引擎,以及 DMP 的數(shù)據(jù)管理平臺(tái)的一部分。

我們就一個(gè)個(gè)來看一下我們怎么樣做重構(gòu)和優(yōu)化的:

  • 首先在接入層,我們直接用 OpenResty 定制了 RTB 網(wǎng)關(guān),為什么用 OpenResty 定制 RTB 網(wǎng)關(guān)呢?剛剛提到了,它的流量非常大,這個(gè)可以充分發(fā)揮 OpenResty 的nginx+lua協(xié)程高性能的特性。
  • 另外還有一個(gè)問題就是不同的媒體有不同的 OpenRTB協(xié)議,雖然有標(biāo)準(zhǔn)規(guī)定,但是它們還是會(huì)有一些差別的,對接起來還是非常地麻煩,所以對每家媒體都利用插件化方式做了差別化的處理,來提高開發(fā)聯(lián)調(diào)時(shí)候的效率。
  • 接下來就是在安全方面的一個(gè)優(yōu)化,這里的安全策略跟前面講的安全策略可能不太一樣。這里面主要是基于 OpenRTB協(xié)議本身的安全策略,包括Request id的各個(gè)階段校驗(yàn),還有參數(shù)的非對稱加密做防盜鏈,泄露用戶信息等,另外就是一些防作弊,我們把這些安全性方面的優(yōu)化都放到這個(gè) RTB 網(wǎng)關(guān)里面來做。
  • 另外,RTB 網(wǎng)關(guān)還做了一個(gè)比較大的優(yōu)化,就是把目標(biāo)流量篩選也直接放到了 RTB 網(wǎng)關(guān)里面來了。之前傳統(tǒng)的做法都是怎么做的呢?都是讓流量進(jìn)入到 DMP 數(shù)據(jù)平臺(tái)里面來,經(jīng)過競價(jià)引擎、廣告檢索、標(biāo)簽查詢服務(wù)來到 DMP 數(shù)據(jù)管理平臺(tái)里面去確定這個(gè)用戶是不是我們需要的。因?yàn)镈MP數(shù)據(jù)管理平臺(tái)里面存放了所有用戶的加密ID信息以及一些標(biāo)簽屬性、偏好等等,之前都是這樣來判斷的。

其實(shí)我們可以簡化一點(diǎn),直接把這部分加密數(shù)據(jù)放到 RTB 網(wǎng)關(guān)里面來,當(dāng)然也會(huì)遇到一個(gè)問題就是用戶的加密標(biāo)識(shí)信息非常大,大概會(huì)有十幾億條,另外一個(gè)設(shè)備標(biāo)識(shí)加密后至少是32個(gè)字符串,如果全部存放到內(nèi)存里面的話大概要十幾個(gè)G,當(dāng)然這還不包括查找索引額外的開銷。

那我們就去尋找一個(gè)哈希算法,可以把一個(gè)固定長度的字符串直接轉(zhuǎn)化為一個(gè)整型,然后我們把這個(gè)整型直接通過Bitmap直接映射到 512 兆的內(nèi)存中的一個(gè)bit中去。這樣就可以直接通過 512 兆的內(nèi)存存放40億的加密設(shè)備號,當(dāng)然也會(huì)有不同的加密設(shè)備號映射到相同的比特位里面去了,但這個(gè)沒有關(guān)系,我們還是繼續(xù)走之前原來的路徑,讓它在最后面 DMP 里面再做一次判斷。

經(jīng)過這么一個(gè)簡單的優(yōu)化之后,我們在第一時(shí)間里面可以過濾掉大概80%以上的流量,所以對整個(gè)系統(tǒng)的性能也是有非常大的提升。

接下來就在邏輯層的優(yōu)化,邏輯層主要是競價(jià)引擎,競價(jià)引擎會(huì)涉及到大量的內(nèi)部服務(wù)的訪問,比如標(biāo)簽查詢、廣告檢索,還有點(diǎn)擊率預(yù)估查詢、頻次控制查詢、計(jì)費(fèi)檢查等等這樣一些內(nèi)部服務(wù)訪問,同時(shí)會(huì)涉及到大量的調(diào)DB、調(diào)緩存、調(diào)redis等操作,我們很多的業(yè)務(wù)其實(shí)都是這樣的,大量的I/O操作,非常典型的 IO 密集型的服務(wù),所以我們也是非常果斷地用 OpenResty 把它完全重構(gòu)了,之前都是采用比較傳統(tǒng)、非常老舊的C++的多線程同步框架。當(dāng)然現(xiàn)在內(nèi)部也有很多C++協(xié)程的方案,我們還是選擇用 OpenResty 直接把它重構(gòu)了。

另外一個(gè)方面就是利用 OpenResty 新建一些新的協(xié)程,去把之前一些串行化的操作做并行處理,來降低時(shí)延,可能一兩個(gè)并行化操作就可以降低競價(jià)出價(jià)的時(shí)延10%左右,也是非常可觀的收獲。

最后就是在數(shù)據(jù)層這一塊,我們看看 OpenResty 是否有它的用武之地呢?

數(shù)據(jù)層DMP 有三個(gè)功能,第一個(gè)是數(shù)據(jù)的采集,第二個(gè)是數(shù)據(jù)的計(jì)算,第三個(gè)就是數(shù)據(jù)的應(yīng)用。在最原始數(shù)據(jù)采集這一塊,因?yàn)槲覀兒竺嬉矔?huì)把 DMP 做得更大,為我們營銷體系做服務(wù)的,所以這里面涉及到大量的數(shù)據(jù)采集的工作,包括廣告曝光、社區(qū)行為、公眾號行為、各種營銷活動(dòng)行為等等,當(dāng)然和之前一樣,經(jīng)過加密處理后進(jìn)行收集。

那在數(shù)據(jù)應(yīng)用這一塊,我們有大量的標(biāo)簽查詢、賬號轉(zhuǎn)化,還有內(nèi)部數(shù)據(jù)合作、實(shí)時(shí)查詢等等操作,這些操作其實(shí)都是非常,也可以直接用這個(gè) OpenResty來做,所以我們用了非常少的服務(wù)器,很輕松的就可以處理數(shù)十億這樣的一些數(shù)據(jù)收集和查詢操作。

那到這里,我的2個(gè)應(yīng)用案例就分享完了,最后用四個(gè)數(shù)字來總結(jié)一下我講的內(nèi)容,以及想表達(dá)的優(yōu)化思想,3527(不是9527):

  • “3”是什么意思?就是剛才提到的我們系統(tǒng)架構(gòu)里面的三層,接入層、邏輯層和數(shù)據(jù)層,這里面三層都可以考慮用 OpenResty 去做優(yōu)化,大家都比較熟悉在OpenResty主要是在接入層 CDN 和 API用的最多,其實(shí)在邏輯層也可以考慮用 OpenResty 去嘗試做一些工作,特別是I/O密集型的邏輯層。并且我們OpenResty 升級了支持TCP/UDP服務(wù)器的stream-module,如果能更加穩(wěn)定的話,我們也會(huì)去嘗試用這個(gè) module直接做我們邏輯層的服務(wù),最后就是在數(shù)據(jù)層也可以去看看有沒有這樣非常簡單的數(shù)據(jù)收集和查詢操作,如果有的話,量也比較大的話也可以考慮用 OpenResty 來輕松實(shí)現(xiàn)。
  • “5”是什么意思呢?我們剛剛說做任何方案選型、考察、評估、深入的時(shí)候都可以從這五個(gè)方面去做。第一個(gè)是易用性,第二個(gè)是可用性,第三個(gè)是性能,第四個(gè)是安全性,第五個(gè)是可維護(hù)性。我們技術(shù)同學(xué)往往考慮得比較多是性能,可用性、安全性這三塊,但其實(shí)在第一點(diǎn)和第五點(diǎn),易用性和可維護(hù)性這一塊需要我們花更多的時(shí)間考慮。特別是對于我們做業(yè)務(wù)開發(fā)的同學(xué)來說,80%以上的時(shí)間可能都是這兩個(gè)方面,如果我們易用性和可維護(hù)性做得好的話會(huì)幫我們節(jié)省大量的時(shí)間。
  • 第三個(gè)數(shù)字就是“2”,“2”就是說我們在做性能優(yōu)化的時(shí)候都要去問自己兩個(gè)問題。第一個(gè)問題就是為什么要做這件事情。第二個(gè)問題就是能否可以不做,能否可以犧牲掉一些其他的資源,比如說內(nèi)存資源來提高性能。能否就是犧牲一些實(shí)時(shí)性來提高性能,或者說我們犧牲產(chǎn)品的體驗(yàn)來提高性能等等,我們需要做性能優(yōu)化的時(shí)候,可以更多地去往上層做一些這樣的考慮和權(quán)衡。
  • “7”是我們在測試性能優(yōu)化的時(shí)候有7個(gè)環(huán)節(jié)。里面每個(gè)環(huán)節(jié)都需要有自己注意的事情,并且可以去做一些歸納和總結(jié)。

【本文是51CTO專欄作者張開濤的原創(chuàng)文章,作者微信公眾號:開濤的博客,id:kaitao-1234567】

戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2024-08-12 09:41:18

2024-08-06 08:34:51

2015-06-11 10:09:04

大數(shù)據(jù)HBase

2022-11-29 19:44:47

WebOpenResty防火墻

2016-05-23 15:42:07

數(shù)據(jù)挖掘

2022-07-14 10:06:20

工作流引擎營銷自動(dòng)化vivo

2016-12-12 17:15:24

游戲大數(shù)據(jù)

2022-05-17 09:43:11

因果模型數(shù)據(jù)建模

2017-01-19 14:45:34

數(shù)據(jù)挖掘Google再營銷

2024-10-21 08:43:16

2014-12-05 11:23:28

docker騰訊云

2022-05-10 15:40:49

素材優(yōu)選算法建模

2023-01-31 15:27:13

數(shù)據(jù)治理數(shù)據(jù)管理

2023-10-08 07:40:29

2024-04-29 11:25:44

AI人工智能數(shù)據(jù)驅(qū)動(dòng)

2025-03-20 10:50:08

RedisCaffeine緩存監(jiān)控

2018-03-19 20:51:07

Weex小程序應(yīng)用開發(fā)

2022-06-09 10:12:01

網(wǎng)絡(luò)安全人工智能威脅監(jiān)測

2017-05-22 08:05:46

HBase阿里搜索實(shí)踐

2015-11-26 16:19:44

云智慧
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號