OpenResty在騰訊遊戲營銷技術中的應用和實踐
- 2020 年 2 月 13 日
- 筆記
很高興今天能有這個機會來到網易大廈來分享騰訊遊戲營銷技術和 OpenResty 一些應用案例。
先做一個簡單的自我介紹。我在加入到騰訊之前一直在通訊行業裏面從事通信軟件的研發工作,包括在華為,還有UT斯達康。
2012年10月份我加入到騰訊,現在在騰訊互動娛樂事業群負責部分的營銷技術相關的工作。我接觸的技術工作比較多、也比較雜,所以我自稱是全「沾」工程師,不敢自稱是全棧工程師。從底層的單片機到嵌入式、協議棧開發,再到上層應用開發,也做過遊戲的後台,現在在做營銷相關的一些技術,所以各種技術都沾過,不一定很深入,但是都接觸過一些。
我今天要分享的內容主要包括兩大塊:
- 第一塊就是 OpenResty 在騰訊遊戲營銷 類API 網關中的應用
- 第二塊是 OpenResty 在騰訊遊戲廣告投放系統中的應用
我的分享會偏重 OpenResty 的應用,不會涉及到太多 OpenResty 具體的技術細節方面,主要是想通過一些應用的案例來把一些優化的思想跟大家做一個分享,來拋磚引玉。
OpenResty 在騰訊遊戲營銷 API 網關中的一個應用
進入到第一個分享案例, OpenResty 在騰訊遊戲營銷 API 網關中的一個應用,下面有一個一個帽子,可能大家會比較奇怪,如果大家看過《海賊王》的同學可能就會比較熟悉,這個就是《海賊王》裏面路飛的帽子,也是我們內部 API 網關的 logo,我們團隊把所有做的公共性的組件、平台性的東西都以《海賊王》裏面的名字進行命名,當然還有很多。
接下來就看一看我們為什麼也要做 API 網關,做 API 網關的業務背景是怎麼樣的,因為我們是業務開發團隊,一個新遊戲上線之前,它是需要做大量的營銷推廣類活動,包括各種簽到、運營、抽獎等活動。形態也各有不同,比如小遊戲、小程序這種推廣類的、H5l引導類的等等。
除此之外,每個遊戲它都有一個自己的微社區,在每個遊戲的 APP 的入口可以進到裏面去,提供一些資訊、攻略、個人數據,還有一些積分,排名等等的功能,也包括賽事直播的一些內容在裏面。
每個遊戲都有這樣大量的活動,並且這個遊戲的數量還是非常大的。然後它訪問的後台的流量也是非常大的,會遠遠超過這裏面提到的數字。
面對這樣一個比較複雜的業務,我們一開始的時候是怎麼樣做的呢?在功能的層面,我們就把它劃分了很多這樣相似的功能模塊,大概有二三十個這樣的功能模塊,模塊化之後是不是就沒有問題呢?但其實問題依然存在,主要包括兩個方面:
- 第一個方面:在開發階段還是有大量重複性的、非功能性的模塊的開發,比如:身份驗證、登陸校驗、流量控制、頻次控制、安全等等這樣的事情要做。
- 第二個方面:就是線上運行的時候也存在大量的防刷,異常用戶行為,需要進行行為控制和分析,包括防刷、秒殺、抽獎類活動的一些流量控制等干預。
這樣的問題都讓我們去思考,怎麼樣去做到功能性的開發和非功能性保障的獨立,以及怎麼樣去做統一的流量控制,那這個其實就是 API 網關要做的事情了,所以接下來我們對業界 API 網關的方案做了大量的考察和分析,大概會分為2大類:

第一類就是開源的方案,開源方案裏面有我們比較熟悉的基於 OpenResty 的orange、KONG,還有其他語言的,比如 go 語言、Java 語言都有自己的 API 網關的方案。
第二個就是雲的方案,各個主流的雲廠商都有自己的 API 網關的解決方案,這些方案都有各自的優缺點,但是都有一個共同的問題,就是都不能滿足我們業務個性化的需求,包括很多定製化的需求。另外還有一個問題,它不能和我們現有的,特別是大公司裏面,現有的組件、平台要去做對接,要去做一個融合,這個很難做得到,因為它不是開源的。
所以我們基於此選擇一個最簡單的、最簡化版的開源方案,就是 orange 的方案去做一個完全的定製化。
在定製化之前,我們看一下 orange 這個方案會有哪些問題或者不能滿足需求的方面,我們從五個方面去看,這五個方面也是我們做任何技術方案選型或者考察評估的時候,可以去分析的點:

我們具體來看一下,orange 在這五個方面的不足吧
- 易用性:orange 還是沒有面向我們業務同學比較熟悉的基於應用、服務、API的配置和管理的操作界面
- 可用性:orange 把網關本身的可用性和配置節點的可用性都交給我們自己來保證。
- 性能:隨着規則數增加,性能下降是非常明顯的。
- 安全性:僅有一些黑白名單和一些通用的認證規則、認證的插件,用不太上。
- 可維護性:也是有一些缺失,在錯誤日誌和染色日誌,還有調用跟蹤定位等等方面還是有缺失的。
接下來我們就從五個方面來說一下,我們是怎麼樣做優化和思考的:
易用性方面優化
第一個是在易用性方面優化,這裏面有兩張圖,左邊這張圖是 orange管理端的截圖,我們看得出來里有提供了很豐富的技術型的插件,有URL的重定向、重寫,還有各種認證,還有限速,還有安全等等。那麼它存的問題是什麼呢?舉個簡單例子,就是我們要添加一個新的 API,那我要到所有的插件裏面配置這個API 的 URL,插件下面還有選擇器,以及規則都要去操作一遍,非常的重複和麻煩。
第二個問題就是對業務開發人員來說,他的思維和操作習慣,會更加關注業務,比如更加關注我的某個個應用,某個應用下面的某個服務,某個服務於下面的某個API的使用情況(認證、校驗、安全、流控、統計等等方面的運行情況或者執行情況)。
所以這裡有一句話就是在做易用方面的設計的時候要更加多的去考慮面向業務,而不是面向技術,我看好像KONG的配置界面也有做service的概念,越是有這個方面的考慮。
可用性方面的優化
第二個就是可用性方面的優化,可用性這個事情,大公司裏面會相對比較容易一點,因為大公司有自己更加可靠的設備或者是組件來保證底層、下面節點的可用性。而騰訊內部有這樣一個接入層網關的組件叫做 TWG/STGW,它們一開始是為了把不同的運營商的流量彙集到騰訊自己的機房裏面來,同時也來做負載均衡、容錯等等一些可用性的保障。所以網關本身節點的可用性這個事情就很簡單,直接把這個 API 網關節點掛到這個 TGW/STGW 上面來就可以了,最後三台網關機器跨機房部署,在容災層面做了進一步的可用性的保證。
第二個方面就是配置節點的可用性的優化,配置節點存放配置信息,配置信息雖然很小的,但也可以做一些簡單的優化,最簡單就是獨立部署 MySQL 或者是 Redis,把配置信息放到這些地方去,然後自己去保證mysql/redis的可用性。
第三個還可以用 MySQL 或者更輕量級的 sqlite 去存放這個配置的信息,由管理端自己去保證它的可用性,管理端每次添加新的 API 的時候,同時去寫入到這三個配置節點裏面去,然後同時寫入到 API 網關的共享內存裏面去,這樣輸入粗暴,但是簡單省事,對我們快速上線的東西來說還是可以用的。
最後一個方法就是用ETCD ,把配置信息存放到ETCD裏面,利用ETCD去中心化的協議去做保證它的可用性,以及一致性。這個方案相對會比較完美一點,但是它有一個問題就是我們要去 API 網關裏面編寫新的代碼監聽 ETCD等操作,我們也在逐步地向這個方案過渡。
性能優化
第三個就是性能優化,一開始我們隊orange 的性能做了一個初步的測試,發現Orange性能隨着它的規則數量增加,QPS 下降還是比較明顯的,然後我們就去做火焰圖的分析,分析之後發現 60% 的操作都會消耗在 json 操作和正則表達式的匹配操作中去,並且 json 操作佔了大頭。
對我們來說第一反應就是 json 操作花了這麼多時間,我們是不是可以去用一個更加高性能的 json 的處理庫去替換 orange 裏面的 Cjson呢,對於騰訊的同學來說,都比較熟悉的是RapidJSON,因為這是騰訊第一個開源的項目,很快就把 RapidJSON 替換掉 orange 裏面的cJSON,發現效果還非常明顯,一下子就提升了 10%+ 的性能。
接下來是不是這樣就 OK 了呢?我們繼續問一下為什麼要做這件事情,簡單閱讀了下代碼,原因是還是非常簡單,就是orange 自己每一次 http 請求的時候,每一個 worker 收到請求的時候都會到共享內存裏面去拉取配置信息,然後去做一個json反系列化操作,變成每個 worker 的數據結構,不管這個配置信息有沒有更新,都去做這件事情,作者可能是為了自己的考慮,有配置更新的時候,這樣實時能知道。
我們接下來再去問自己第二個問題,就是能否不做這件事情,對我們來說,犧牲一點實時性,一個配置更新過半分鐘或者隔幾秒鐘得到這個配置最新信息,我們是可以接受的。所以我們很簡單就可以去掉上面頻繁的系列化操作,就是直接起一個 Timer 去過一段時間 check 一下這個共享內存裏面有沒有配置信息的更新標誌即可,非常簡單的這樣一個優化就直接把這部分的 JSON 操作直接去掉了。
所以這裡有一個體會是最大的優化是不做或者是柔性的平衡,這種柔性平衡可能會包括很多方面,犧牲一些其他的資源來得到性能,犧牲內存得到性能,或者犧牲一些實時性得到性能,還包括犧牲一些產品的體驗得到性能,這些都是柔性的平衡,可能需要我們花更多時間去思考。
接下來我們就去做進一步的優化,因此我們做一個完整的性能測試,一個完整的性能測試主要會包括這麼七個環節,前面的三個環節都是為了第四個環節的壓力測試做準備的,包括環境準備、配置調優、靜態檢查等等。
這裏面環節當然也有自己要去注意的事情,環境準備雖然很簡單,但也要考慮一些問題,就是測試機的性能和壓測工具的性能往往也會有問題裏面。還有測試機和被測試機的時延等等,都需要考慮,否則會影響我們測試出來的真實性。
其他的話配置調優和靜態檢查這兩塊參考一些通用總結的經驗就可以去做了。
下面就開始做壓力測試,壓力測試需要注意的是要盡量去模擬現網的真實環境和現網的處理流程去做,如果我們只是簡單做一個echo測試的話,雖然這個性能數據很高,但不一定很真實,有參考價值。所以我們在騰訊內部的一個C1的機型上面,模擬真實現網流量和配置,大概測試出來的數據在18000 QPS。這個數據比之前採用了 PHP 的同步阻塞的傳統的 CGI 的方式肯定是要高一個數量級的,但不一定就沒有優化的空間了。
所以接下來我們繼續去做瓶頸分析、性能分析。性能分析就用到了我們性能分析神器:火焰圖,OpenResty社區的同學都非常熟悉火焰圖

我們把 CPU 消耗前10的操作做一個歸納,歸納出來有這麼幾類操作,第一個是 JSON 的操作佔了9.18%。第二是 L5 的操作佔了4.74%(L5是騰訊內部的一個負載均衡服務的組件),另外一個就是正則表達式匹配佔了 10.36%。其他的就是nginx的操作以及系統調用等。
接下來我們就對這三個方面的操作,看看是不是有優化的空間。首先我們看一下 L5 的這個操作有沒有優化的空間,剛剛說 L5 是騰訊內部的一個負載均衡的組件,我們就把它也集成到 API 網關裏面來了,他們的工作原理會跟本機的 L5agent 進行通訊,所以我們在做壓力測試的時候要去看一下,在壓力測試這麼大流量的情況下,L5agent 是不是有 CPU 消耗,或者它有沒有出錯,接下來再看一下它的日誌和出錯情況是否正常的,然後再把這個用 FFI 的方式替換我們之前的Lua C/API的方式,看看有沒有性能的提升。我們又再進一步去分析 L5 這個操作,發現它是用了阻塞的 UDP 的調用,所以這裡是有風險的,它會影響到其他的協程的執行的,所以我們需要盡量地把它的超時時間設得更短一點,也嘗試看看能否用 cosocket 的方式去實現 L5 的API,但發現協議沒有開源等等,經過這一些列的嘗試,最後放棄了這部分的優化。
接下來就是 JSON 操作的優化,有前面的經驗之後,我們做性能優化的時候就會問自己兩個問題。第一個問題為什麼要做這件事情,分析發現,是因為我們後端的服務把所有響應的數據都做了一個JSON encode,然後API網關會進行JSON decode然後去去提取裏面的一個返回碼,根據後端返回的返回碼的不同,向前端返回是200OK還是其他的HTTP的不同的響應碼,僅僅做這樣一件事情。那繼續問第二個問題能否不做,很顯然是可以的,就是我們可以直接讓後端返回數據的時候把返回碼字段獨立出來, API 網關的直接拿到返回碼做一個判斷即可,然後把數據字段直接轉發給前端就 OK 了。非常簡單的一個優化,直接就可以省掉了這部分的 JSON 操作。
另外 JSON 操作確實會消耗我們很多 CPU 的性能,我們一些同學也經常在 debug 裏面去打印,想把這個 debug 日誌裏面去打印很多數據結構裏面的內容(用json.encode來打印),然後放到生成環境上去,雖然這個 debug 操作是不會執行,但是這個函數,JSON encode操作是會執行的,這樣的話會導致生產環境極大的性能損耗,等等這樣類似的情況還是非常多的,所以我們在實際過程當中還是要去留意這樣一些不好的編碼的習慣。
正則表達式匹配的優化
第三個就是正則表達式匹配的優化。大家知道正則表達式匹配都是由正則表達式引擎來做的,常用的正則表達式引擎就是PCRE,於是我們就去考慮有沒有更加高性能的正則表達式匹配的引擎呢?我們也去做了一些調研,正則表達式應用最多的領域其實是在安全領域裏面,安全領域裏面有這樣的的IPS、IDS 這樣的一些安全檢測和防禦性的產品裏面會大量地使用正則表達式匹配的操作,它之前也是用 PCRE 來做正則表達式的匹配。後來就是在這兩年的時候,都統一切換到了英特爾開源的 Hyperscan 這樣的正則表達式引擎來了。

為什麼它會去做這樣的改變呢?Hyperscan 正則表達式引擎比這個PCRE有哪些優勢呢?分析後發現它有這麼幾個方面的不一樣或者說優點。
- 第一個就是它不僅僅是支持塊模式,還支持流模式。所謂的流模式就是跨不同的網絡包去做一個匹配,這個對安全產品是非常有用的。
- 第二個就是它一次可以編譯多個規則,大家知道正則表達式最後都會編譯成狀態機到內部去做匹配的操作。
- 第三個就是一個輸入多個規則只匹配1次,它可以並行匹配多個規則,這個是很厲害的。它的性能可能會很高,所以我們接下來我們就去做了這樣一個驗證,就是把30萬條http get 請求(包括 URL),寫到一個文本裏面去。然後每個參數都做一個正則表達式的匹配,用 PCRE 的代碼和 Hyperscan 的代碼去讀這個文件,一條條讀,然後匹配每一個規則。發現 Hyperscan 匹配正則表達式所以花費的時間確實比PCRE所花的時間低很多,大概只有後者的30%左右的樣子。所以接下來我們就非常果斷地把它引入到我們的 API 網關裏面來,用火焰圖繼續驗證, CPU 的消耗,從之前的10%+降低到7%只有了。
所以接下來是不是還有可以優化的空間?當然有,就是開啟它的並性匹配度規則的操作,這個 Hyperscan 裏面也是提供了回調,然後我們只需要把每個規則設置一個標誌位,然後去匹配完之後檢查這個標誌位以後就OK了,就可以做得到了。
另外還有一件事情是什麼呢?就是正則表達式規則編寫難度的問題,我們不能要求業務開發同學每次都要去編寫正則表達式,這個對他們來說也不一定編寫得正確,也有一些學習的成本在裏面。所以我們就去看了一下大部分的參數還是比較類似的,所以就把這些參數的正則表達式做一些歸納,然後用一些文字性的描述,做了一個模板,業務人員就可以直接去選擇這些模板就OK了,也很好的解決了這個問題。
安全性方面的優化
第四個方面的優化就是安全性方面的優化。安全性方面的優化要做的一件事情就是,它需要把我們這個 API 網關的安全策略去和公司現有的一些安全的產品做結合。騰訊內部有這樣的自己的安全產品,叫門神,所以我們在 http 請求進來post read階段就去和安全產品做一個交互,讓它去過濾流量。它過濾的流量沒有問題之後,再進入到我們的安全策略裏面。當然這個安全策略也相對會比較簡單,包括有 API 白名單,配置到 API 的流量才可以進到裏面來。然後還有基於用戶過濾的黑白名單,還有登錄校驗,支持騰訊的手Q、微信等的多種校驗方式,也都把它集成進來了。
另外去做參數校驗,參數校驗則用前面提到的正則表達式做非常嚴格的必選參數的校驗。另外就是如果做了非常嚴格的正則表達式匹配的話,SQL 防注入等等這樣的問題也不會有。這個就是安全性方面的優化。
可維護性方面的優化
最後就是可維護性方面的優化,我們也做了兩點:
- 第一是添加了一些日誌和統計的功能。例如,把 4xx/5xx 等一些錯誤日誌獨立出來,另外就是添加基於某個用戶id後者請求id的染色日誌跟蹤打印。
- 第二個方面的優化不一定屬於今天講的內容裏面的,就是我們也做了調用鏈跟蹤系統。API 網關在這個調用鏈跟蹤系統裏面是作為起點,它會去生成Trace id,以及創建調用鏈的上下文,以及結束調用鏈,另外就是還可以控制調用鏈跟蹤的採集的頻率等。
那到這裡就快速簡單介紹了一下第一個應用案例,在易用性、可用性、性能,還有安全性以及可維護性這五點,我們的一些思考和優化的過程。
OpenResty 在騰訊遊戲、廣告投放系統中的應用案例
接下來進入到第二部分,就是 OpenResty 在騰訊遊戲、廣告投放系統中的應用案例。還是和之前的內容一樣,我不會涉及到很多具體的 OpenResty 的技術的細節,主要是想跟大家分享一下案例,以及在這個案例裏面一些優化的思想。
這個案例相對會比較大膽一點,因為大概騰訊遊戲有好幾個億的營銷費用都會通過這個系統投放出去。廣告投放的形式有很多種,有包段廣告位的、包段時間段的、包段流量的,還有普通競價的,還有實時競價的。今天我想跟大家分享的就是實時競價的廣告投放形式和我們 OpenResty 的一個結合,以及 OpenResty 在裏面的優化。

什麼是實時競價廣告?以及實時競價廣告的流程是怎麼樣的?這裏面有一個圖。我們從最右邊往左看,最右邊就是我們的用戶打開手機看內容,比如看頭條裏面的內容或者刷新聞。過程中會看到有廣告位的,當刷到有廣告的那個頁面的時候,這個時候 APP 就會向 ADX (廣告交易平台)服務器發一個廣告請求。廣告交易平台服務器收到這個廣告請求之後,它會去把這個廣告請求分發給下面的廣告主的 DSP 服務器,當然DSP 服務器可能會有很多家,一般來說只有大型的廣告主才會有自己的 DSP 服務器。
騰訊遊戲作為一個比較大型的廣告主,它也有自己的 DSP 服務器。它收到的廣告請求之後會怎麼做呢?它會把這個廣告請求裏面的流量到它的DMP(數據管理平台)數據庫裏面去做一個判斷,怎麼判斷?就是這個用戶是不是我需要的,如果是我需要的話,我應該給他評估一個怎樣的價錢,就是說我願意出多少錢給來獲得這個用戶的這個廣告曝光機會。
這裏面會涉及到一些機器學習的算法去評估這個出價,最終確定了出價之後,他會把這個出價原路返回給 ADX 服務器。ADX 服務器收到這個出價之後,它會等待其他廣告主的 DSP服務器的出價,放在一起比較來最終選擇最高出價的廣告主的廣告,然後把這次廣告曝光的機會給到這個廣告主,展示這個廣告主的廣告素材,這個就是一個比較簡化的實時競價廣告的流程。
裏面需要做的一個事情就是,在這個 ADX 和 DSP 服務器之間的交互是通過 OpenRTB 協議來做的,這裏面有兩個問題需要解決:
- 第一個是流量非常大,ADX所有的廣告請求都會發給 DSP 服務器,有些大的媒體可能有好幾萬個QPS,如果好幾家的話加起來很輕鬆會超過十萬QPS。
- 還有一個問題就是 ADX要求所有的DSP 必須在 100 毫秒返回出價響應,這個100ms包括網絡上的時間,如果 100 毫秒之內我沒有收到你響應的話,我就視為你放棄了這個出價。
當然實時競價廣告技術方面有很多挑戰,主要有這麼幾塊的挑戰。
- 第一個就是在數據方面,包括標籤挖掘、人群擴散、畫像分析,還有一些實時分析、透視分析來輔助刷選投放目標人群,這個是在數據方面的技術挑戰。
- 第二個就是算法,算法會包括兩個比較核心的算法。第一個就是 pCTR,第二個就是pCVR,pCTR 就是點擊率預估算法,pCVR是轉化率預估算法,這個轉化可能會包括多個,有下載、註冊、付費、活躍等等都屬於轉化。這兩個算法會用到現在比較熱的一些機器學習的算法在裏面。
- 第三個方面的挑戰就是在系統層面的挑戰,剛才提到了 ADX 和 DSP 服務器,它之間會有比較高的QPS,另外就是時延有要求,100毫秒的要求。今天我分享的內容主要是偏重於在第三塊,就是在系統層面怎麼和 OpenResty 進行結合。
這個是實時競價廣告系統在系統側的一個架構簡圖,最上面是流量層,各ADX的廣告請求流量會發到下面的接入層。接入層又包括兩部分,一個是靜態的 CDN,一個是動態的 RTB 網關,CDN 存放廣告的素材,RTB 網關會做一件事情,就是進行 OpenRTB 協議的編解碼,此外還會做一些安全和流量控制等操作。
在邏輯層包括競價引擎,最下面的就是數據層包括 DMP 數據管理平台。這兩個部分做的事情就是我們剛剛說的,一起來確定這個廣告請求是不是我們需要的用戶,如果是我們需要的用戶的話,我們怎麼樣給它估算一個價錢。

這裏面標了橙黃色字體的,就是我們用 OpenResty 進行過重構或者說優化過的地方,包括接入層的 RTB 網關,還有邏輯層競價引擎,以及 DMP 的數據管理平台的一部分。
我們就一個個來看一下我們怎麼樣做重構和優化的
- 首先在接入層,我們直接用 OpenResty 定製了 RTB 網關,為什麼用 OpenResty 定製 RTB 網關呢?剛剛提到了,它的流量非常大,這個可以充分發揮 OpenResty 的nginx+lua協程高性能的特性。
- 另外還有一個問題就是不同的媒體有不同的 OpenRTB協議,雖然有標準規定,但是它們還是會有一些差別的,對接起來還是非常地麻煩,所以對每家媒體都利用插件化方式做了差別化的處理,來提高開發聯調時候的效率。
- 接下來就是在安全方面的一個優化,這裡的安全策略跟前面講的安全策略可能不太一樣。這裏面主要是基於 OpenRTB協議本身的安全策略,包括Request id的各個階段校驗,還有參數的非對稱加密做防盜鏈,泄露用戶信息等,另外就是一些防作弊,我們把這些安全性方面的優化都放到這個 RTB 網關裏面來做。
- 另外,RTB 網關還做了一個比較大的優化,就是把目標流量篩選也直接放到了 RTB 網關裏面來了。之前傳統的做法都是怎麼做的呢?都是讓流量進入到 DMP 數據平台裏面來,經過競價引擎、廣告檢索、標籤查詢服務來到 DMP 數據管理平台裏面去確定這個用戶是不是我們需要的。因為DMP數據管理平台裏面存放了所有用戶的加密ID信息以及一些標籤屬性、偏好等等,之前都是這樣來判斷的。
其實我們可以簡化一點,直接把這部分加密數據放到 RTB 網關裏面來,當然也會遇到一個問題就是用戶的加密標識信息非常大,大概會有十幾億條,另外一個設備標識加密後至少是32個字符串,如果全部存放到內存裏面的話大概要十幾個G,當然這還不包括查找索引額外的開銷。
那我們就去尋找一個哈希算法,可以把一個固定長度的字符串直接轉化為一個整型,然後我們把這個整型直接通過Bitmap直接映射到 512 兆的內存中的一個bit中去。這樣就可以直接通過 512 兆的內存存放40億的加密設備號,當然也會有不同的加密設備號映射到相同的比特位裏面去了,但這個沒有關係,我們還是繼續走之前原來的路徑,讓它在最後面 DMP 裏面再做一次判斷。
經過這麼一個簡單的優化之後,我們在第一時間裏面可以過濾掉大概80%以上的流量,所以對整個系統的性能也是有非常大的提升。

接下來就在邏輯層的優化,邏輯層主要是競價引擎,競價引擎會涉及到大量的內部服務的訪問,比如標籤查詢、廣告檢索,還有點擊率預估查詢、頻次控制查詢、計費檢查等等這樣一些內部服務訪問,同時會涉及到大量的調DB、調緩存、調redis等操作,我們很多的業務其實都是這樣的,大量的I/O操作,非常典型的 IO 密集型的服務,所以我們也是非常果斷地用 OpenResty 把它完全重構了,之前都是採用比較傳統、非常老舊的C++的多線程同步框架。當然現在內部也有很多C++協程的方案,我們還是選擇用 OpenResty 直接把它重構了。
另外一個方面就是利用 OpenResty 新建一些新的協程,去把之前一些串行化的操作做並行處理,來降低時延,可能一兩個並行化操作就可以降低競價出價的時延10%左右,也是非常可觀的收穫。
最後就是在數據層這一塊,我們看看 OpenResty 是否有它的用武之地呢?

數據層DMP 有三個功能,第一個是數據的採集,第二個是數據的計算,第三個就是數據的應用。在最原始數據採集這一塊,因為我們後面也會把 DMP 做得更大,為我們營銷體系做服務的,所以這裏面涉及到大量的數據採集的工作,包括廣告曝光、社區行為、公眾號行為、各種營銷活動行為等等,當然和之前一樣,經過加密處理後進行收集。
那在數據應用這一塊,我們有大量的標籤查詢、賬號轉化,還有內部數據合作、實時查詢等等操作,這些操作其實都是非常,也可以直接用這個 OpenResty來做,所以我們用了非常少的服務器,很輕鬆的就可以處理數十億這樣的一些數據收集和查詢操作。
那到這裡,我的2個應用案例就分享完了,最後用四個數字來總結一下我講的內容,以及想表達的優化思想,3527(不是9527):
- 「3」是什麼意思?就是剛才提到的我們系統架構裏面的三層,接入層、邏輯層和數據層,這裏面三層都可以考慮用 OpenResty 去做優化,大家都比較熟悉在OpenResty主要是在接入層 CDN 和 API用的最多,其實在邏輯層也可以考慮用 OpenResty 去嘗試做一些工作,特別是I/O密集型的邏輯層。並且我們OpenResty 升級了支持TCP/UDP服務器的stream-module,如果能更加穩定的話,我們也會去嘗試用這個 module直接做我們邏輯層的服務,最後就是在數據層也可以去看看有沒有這樣非常簡單的數據收集和查詢操作,如果有的話,量也比較大的話也可以考慮用 OpenResty 來輕鬆實現。
- 「5」是什麼意思呢?我們剛剛說做任何方案選型、考察、評估、深入的時候都可以從這五個方面去做。第一個是易用性,第二個是可用性,第三個是性能,第四個是安全性,第五個是可維護性。我們技術同學往往考慮得比較多是性能,可用性、安全性這三塊,但其實在第一點和第五點,易用性和可維護性這一塊需要我們花更多的時間考慮。特別是對於我們做業務開發的同學來說,80%以上的時間可能都是這兩個方面,如果我們易用性和可維護性做得好的話會幫我們節省大量的時間。
- 第三個數字就是「2」,「2」就是說我們在做性能優化的時候都要去問自己兩個問題。第一個問題就是為什麼要做這件事情。第二個問題就是能否可以不做,能否可以犧牲掉一些其他的資源,比如說內存資源來提高性能。能否就是犧牲一些實時性來提高性能,或者說我們犧牲產品的體驗來提高性能等等,我們需要做性能優化的時候,可以更多地去往上層做一些這樣的考慮和權衡。
- 「7」是我們在測試性能優化的時候有7個環節。裏面每個環節都需要有自己注意的事情,並且可以去做一些歸納和總結。 ,