Golang在京東列表頁實踐總結
作者:張洪濤
原文:http://studygolang.com/articles/4744
10餘年軟體開發和設計經驗,曾就職於搜狐、搜狗、前matrixjoy公司聯合創始人、甘普科技CTO。
目前線上狀態
基於搜索實現;
全量數據,搜索結果不理想;
介面響應時間長,影響了用戶體驗;
沒法針對數據做二次優化;
轉化率相對較低;
基於以上原因,需要做出改變,所以就需要對老進行重構,如下
重構版本
非全量數據,線下非同步根據數據模型進行進行篩選部分最優數據;
要求時時過濾計算,介面相應時間要快,保證用戶體驗;
數據進行優化,提高轉換率,提搞GMV;
為何選擇golang
golang語言強大的並發能力;
與C相媲美的性能,新版對cpu計算要求較高;
基於以上兩點,所以選擇了golang語言作為服務端計算使用的語言。
重構後的架構圖
解釋下架構圖各個模塊功能
Nginx+Lua: 用來渲染頁面,拿到go計算服務的json數據渲染到頁面端,最終呈現給終端用戶;
Config Center 是用來協調worker、lua服務以及go計算服務的控制中心;
Score Worker、Data Worker 是一個用來線下非同步計算數據的2個worker,從數據平台拿到數據加上各種數據模型計算最優數據,計算完成後會通知 Config Center,同時數據會進入DB,進行持久化;
深黃色部分是go計算服務,只要分2個集群,一個線上集群、一個線下集群,非同步計算服務根據配置中心選擇一個線下集群進行數據計算,計算完成後會通知Config Center,然後相應的線下集群會進行數據預載入到分片的redis以及go計算服務的各個節點中,然後線下集群準備就緒,可以隨時切到線上提供服務;
MQ Worker是一個處理消息的服務,主要包括sku上架、下架、庫存變動、以及價格變動等消息;
Msg Receiver 接受到MQ worker的消息後進行消息處理,然後發送的go計算服務的各個節點中;
線上部署的多個機房,避免單機房故障;
數據處理流程如下圖所示:
上圖是一個完整的數據處理流程,整個流程中最核心的部分是架構圖中的Config Center,數據流程中的每一步操作都依賴於配置中心。所以整個架構中配置中心非常重要。
內存計算模型圖
簡單介紹下計算過程:
解析頁面傳過來的參數,整理成相應的結構體;
格式化的結構體,比如品牌、價格、sku屬性、庫存、產品標籤、排序類型等;
通過格式化的結構體進行內存中計算,包括過濾、排序等計算操作;
計算完成後會拿到當前頁面需要的產品ids;
然後通過id列表獲取到產品的詳細信息,並對產品屬性過過濾;
最終把結構化的json數據返回給lua,進行頁面渲染;
內存計算數據結構
如下圖所示:
以上結構是go的一個結構體,包括了頁面上所有要進行計算的屬性,後續所有的內存中計算過濾、排序都是基於此結構體進行,每個商品對應一個相應的結構體,每個分類大約有幾萬個商品,內存中也有對應的結構體。這些結構體是在數據異構完成後,數據預先載入內存,避免在提供服務的時候再去初始化。
開發過程中遇到的問題
遇到2個比較嚴重的問題:
Golang自身序列化性能低下
GolangGC困擾
針對第一個序列化、反序列化問題,我們嘗試過golang內置的encoding/json、encoding/gob兩種方式,但是效果都特別不理想,耗費cpu過多,qps 一直上不去。
後來請教beego作者的謝大同學,給推薦了ffjson,也親自寫了一些測試ffjson的代碼,最終ffson以3倍優勢完勝golang內置json序列化,所以最後採用了ffjson。
第二個問題,golang GC問題,相信不少同學在開發的過程中也遇到過這個問題,其實我們認真分析,發現GC時候很大部分時間是浪費的Marking階段,所以我們可以從以下幾個點優化我們的代碼:
減少內存中對象數量
盡量重複內存申請,採用對象池,避免重複申請、釋放內存,可以非常有效的減少GC;
開啟GODEBUG=gctrace=1,可以非常清晰的看到內存中對象數量、內存使用情況。以及各個階段的時間開銷;
另外可以使用golang內置的性能監控工具pprof包,可以方便得監控到內存、cpu的是使用情況。
Go 技術棧選擇
web框架,採用Asta的beego(http://beego.me)裡邊的orm部分寫的很贊,建議大家仔細讀讀裡邊的源碼,對lua部分的API設計都是採用beego現成的MVC設計,可以方便得定義介面,並在路由中配置即可提供服務;具體github地址:http://github.com/astaxie/beego
json序列化,https://github.com/pquerna/ffjson,裡邊有詳細的使用說明文檔;
redis:http://github.com/go-redis/redis 在這之上我們內部又對主從操作封裝了一層;
※黑客是如何發現女朋友出軌的?
※Linux 文件管理
※Linux 下網路協議分析器 Wireshark 使用基礎
TAG:程序源 |
※Google SRE最佳實踐之On-Call
※vue Router在新標籤打開頁面的實踐
※Spring Cloud Contract 在永輝雲創的研發實踐
※華為在OpenStack Days China上分享混合雲行業場景及優秀實踐
※Georgia Tech-真正的理論與實踐結合
※技術解析系列PouchContainer Goroutine Leak 檢測實踐
※第55期:Python機器學習實踐指南、Tensorflow 實戰Google深度學習框架
※實踐秘籍:Boosting 與 AdaBoost
※GemFire與Greenplum的最佳集成實踐之實施經驗談
※Epic Games發布《虛擬製片實踐指南》
※從選擇到實踐——It』s now or never
※Apache Storm流計算模型 及WordCount源碼實踐
※打包優化實踐(如何Code Spliting)
※Uber Hadoop 文件系統最佳實踐
※TalkingData的Spark On Kubernetes實踐
※傳統數倉從 Teradata 遷移到 Hadoop平台實踐
※Github 代碼實踐:Pytorch 實現的語義分割器
※Github代碼實踐:Pytorch實現的語義分割器
※BGP Confederation原理實踐
※Istio技術與實踐02:源碼解析之Istio on Kubernetes 統一服務發現