人物 | 盧克:58同城搜索雲--雲搜核心技術揭祕


10月31日-11月1日,第三屆2020 AI Pioneer Con技術峰會線下場在杭州成功舉行。本次大會聚焦AI與5G最前沿技術及產業落地,邀請全球頂尖技術企業及全球開發者共同參與。


58同城高級架構師盧克受邀在本次大會“AI平臺+數據科學”專場分享了《58同城搜索雲核心技術揭秘》。


本文根據此演講實錄整理而成,圖文詳實,歡迎閱讀分享。


背景

58同城是綜合生活信息服務平臺,主要業務包括房產、招聘、汽車、本地服務等。58搜索承載著58列表頁關鍵詞搜索和點擊篩選搜索的主要流量,早期的58搜索系統是基於solr實現,隨著業務和流量增長,solr的性能捉襟見肘。

2012年底自研的esearch檢索系統上線,近實時分佈式搜索系統,很好的支撐了業務的發展。由於其出色的性能,在搜索內部開始廣泛使用。

截止2016年,內部基於esearch檢索系統,創建了30多個垂直搜索服務,如簡歷搜索、企業搜索等。站在服務的角度看,各個垂直檢索系統性能出色,但站在業務的角度看,迭代還不夠快,使用不夠方便。

因為每當創建一個業務的搜索服務,都需要搜索開發同學先確認需求,如哪些索引字段,如何排序,然後在基礎的搜索系統上適配/構建某個業務的檢索服務,業務上線後還需監控和運維等,創建一個業務的搜索服務大概需要一個月時間。

但這些垂搜檢索服務,其實邏輯上大同小異,底層都是統一個檢索系統,系統整體架構基本一樣。為了方便用戶更快的接入搜索,服務更多的業務需求,需要在平臺化和服務效率上更進一步,基於以上需求,58雲搜索平臺(內部簡稱WCS)應運而生。


58雲搜是58搜索團隊基於k8s(即kubernetes,下同)和docker技術,以及內部的搜索引擎實現的全自助化的搜索服務平臺,為各業務開發者提供實時索引、動態摘要、自定義排序、運營監控、運維託管等全套解決方案。使用方僅需通過界面配置索引結構、api上傳源數據兩個步驟,即可在數分鐘內構建完成一個自有的搜索服務。

2017年上線至今,已經接入了兩百多個搜索業務,實現了為業務快速創建搜索服務。使用方如果需要創建一個搜索服務,只需要登錄雲搜的管理系統,填寫目標流量和索引字段等信息,雲搜系統收到請求後,即自動拉取相應鏡像進行遠程部署,隨後一個搜索實例即可上線使用。

人物 | 盧克:58同城搜索雲--雲搜核心技術揭秘


人物 | 盧克:58同城搜索雲--雲搜核心技術揭秘


雲搜整體架構

下面是雲搜的整體系統架構。首先,雲搜採用k8s實現資源管理和自動調度,k8s是整個系統的大腦。雲搜所有的服務都是運行在容器中,通過容器的方式自動調度和維護,k8s自身也是運行在容器之中。

圖中紅色方框部分即k8s和雲搜管理中心,它控制索引創建和管理各服務模塊。其次,對外提供統一的接入api,和系統自助管理功能,屏蔽了內部一個個獨立的索引實現,方便用戶使用。

第三,在離線索引過程,引入hdfs和分佈式消息隊列等外部通用的基礎服務,存儲源數據和實現索引流程,簡化了系統設計,同時也保證了源數據的可靠性,相當於源數據做了離線備份。

人物 | 盧克:58同城搜索雲--雲搜核心技術揭秘


k8s是整個系統的核心,所以保證k8s master系統的高可用非常重要。

雲搜的k8s master是3副本冗餘,k8s master所有的信息都是存儲在etcd集群中,關於etcd部分不單獨介紹。

雲搜如何實現master 多副本的負載均衡和高可用性?

我們使用了haproxy和keepalived兩個開源組件,以及虛ip技術來做load balance,實現master節點的負載均衡和高可用。

haproxy是一個高可靠性代理軟件,使用它實現對api server的負載均衡和流量轉發,所有訪問api server的請求,都會經過haproxy進行代理轉發。keepalived 是一個高可用的路由軟件,用它來對haproxy做健康檢查和故障切換。集群中的所有node節點通過vip訪問haproxy,keepalived負責搶佔vip,兩個keepalived互為主備,正常情況都會搶佔vip成功,兩個haproxy都會均勻的獲得流量。當一個haproxy節點故障時,keepalived檢測到haproxy故障,自動漂移vip,這樣故障haproxy上即沒有了流量,實現自動故障切換。

人物 | 盧克:58同城搜索雲--雲搜核心技術揭秘


隨著雲搜規模的增長,我們發現開源的網絡組件flannel有一個bug,只能支持100臺物理機,無法進行再擴容。同時我們也考慮到k8s master出現故障,整個雲搜將出現不可用。

由於當時集群聯邦的模式還不可用,我們構建了完全獨立的多k8s集群來提升系統的可用性。多集群的模式,我們的架構主要的升級點是把原來的api層拆分為兩層,頂層api根據業務id把真正的流量轉發到各個集群,實現了多集群的升級過程對業務無感知。構建多集群的另外一個好處就是,我們能夠通過遷移一個集群的服務到另外一個集群實現滾動升級,這對快速更新的k8s非常重要。

截止目前我們已經進行了2輪的遷移服務,滾動升級k8s或linux 內核。

人物 | 盧克:58同城搜索雲--雲搜核心技術揭秘


自動索引流程和故障恢復

我們簡單介紹下一般的檢索系統是什麼樣,有了這個基礎然後再詳細介紹,在環境下怎麼構建搜索系統。

一般來說,搜索系統都包含兩部分,離線倒排索引構建和在線檢索服務

在離線階段批量的獲取所有的文檔,通過索引程序生成倒排索引文件,然後把倒排索引文件推送給在線檢索程序去加載,檢索程序加載倒排文件後對外提供檢索服務。離線構建的倒排索引是靜態的不能被改變的,但在很多的應用場景中,文檔會有實時的更新或者新增,所以會啟動一個實時的索引流程,在檢索服務內部實時構建小的倒排索引,即增量索引,全量索引和增量索引合在一起,實現了索引的完整性。

人物 | 盧克:58同城搜索雲--雲搜核心技術揭秘


有了前面的基礎,我們現在來介紹下,如何利用k8s和容器技術,自動化的創建檢索服務,讓複雜的檢索系統通過k8s實現自動運維。搜索是有狀態的服務,它有如下3個特徵:(1)服務存儲持久化數據,(2)數據有分片,不同分片包含不同數據,(3)數據在持續更新。

所以我們核心問題就是,實現檢索服務的容器化部署,同時保證容器中檢索服務中的數據的正確性和完整性,從而實現服務的可用性。我們的實現方案是利用k8s一個pod內部可包含多個容器的特性,多容器分工合作實現自動構建檢索服務。

首先,一個檢索pod啟動後,裡面是沒有倒排索引數據,相應檢索服務也還運行,這時先啟動初始化容器,初始化容器完成本服務參數配置,同時根據自己分片拉取倒排數據文件,完成配置和數據的初始化。

有了倒排索引數據,第二步啟動主檢索容器,加載索引文件啟動服務。第三步再啟動一個數據更新容器,從外部消息隊列中,拉取屬於本檢索分片的數據,發給檢索進程實時構建索引,實現數據更新。

3個容器配合實現了檢索服務的自動構建,有狀態的服務轉換成了無狀態的實現,整個實現過程對原來索引、檢索模塊和k8s無侵入、無感知。

擴容過程類似,當需要擴容時,只需在k8s中增加副本數,k8s自動生成新的檢索pod,擴容出來的檢索pod也是沒有數據,這是由初始化容器從其他分片同步過來相應的倒排數據(這樣效率更高),然後啟動檢索服務容器和數據更新容器,實現了擴容副本和原副本的數據最終一致。

人物 | 盧克:58同城搜索雲--雲搜核心技術揭秘


再來看下雲搜如何實現自動故障恢復。

如果一個物理機出現了故障,該機器上的服務都不可用了。系統的liveness探針發現該pod不再存活,這個應用可用的pod數目和系統設定的數目差了一個,於是就在其他物理機上啟動了新的pod。

新的pod啟動后里面的索引數據還不完整,不能對外提供服務,pod內部獨立的容器會從其他正常節點和消息隊列同步數據,數據同步完成後,k8s通過readiness 探針發現pod準備就緒,於是將新啟動pod加入到服務中,完成故障恢復。可以看到,擴容過程本質上和故障自動恢復一樣。

從自動部署和故障恢復,我們就可以看到利用k8s實現自動運維的優勢和便利性。


人物 | 盧克:58同城搜索雲--雲搜核心技術揭秘


服務質量和資源利用優化

前面也提到了,檢索系統包含離線全量倒排索引構建和在線檢索服務兩個過程。實際線上出現離線全量建索引過程佔用資源高,影響在線查詢服務的情況。究其原因是調度器非搜索專用,並不知道是在線還是離線。

為了保證在線服務的質量,我們將在線pod和離線pod進行隔離,不讓兩種類型的pod調度到同一個node上。

解決方案,給node節點分別打上在線和離線的標籤,pod也打上標籤,利用pod和pod之間的親和力機制,離線pod調度到離線機器,在線pod調度到在線機器上。

人物 | 盧克:58同城搜索雲--雲搜核心技術揭秘


有時,我們會收到個別機器資源利用率過高的報警,追查之後發現是高流量pod堆積在一臺節點,造成資源利用率不均。這是因為scheduler不瞭解實時流量,不保證大量pod不堆積 。

這裡的解決方案,使用了pod之間的反親和力機制,給部分流量比較大的業務打上標籤,讓大流量pod調度到不同機器上。

人物 | 盧克:58同城搜索雲--雲搜核心技術揭秘


前面介紹的兩種優化的機制,有時候還不能滿足我們的需求。

實際線上的情況,仍然會出現會調度到高負載機器上,有的機器負載比較低但是卻沒有調度過去,造成資源利用不均衡。其原因是調度器是根據已分配出去的資源,來決定新的調度。

但實際情況是,線上大部分業務申請了資源,實際上使用不了那麼多,所以分配出去的資源量是不準確的,並不代表真實的使用量。為了解決這個問題,我們決定自定義調度器。

調度器根據特定的調度算法將 pod 調度到合適的 node 節點上去,調度過程看來好像比較簡單,但在實際需要考慮的因素很多,非常複雜。

我們採用了調度框架+自定義插件方式。k8s提供可插拔架構的調度框架,使得定製調度器這個任務變得更加的容易。調度框架大概是這樣:整個調度分為調度過程和綁定過程,這兩個過程合在一起,稱之為調度上下文。

調度過程為 pod選擇一個合適的節點,綁定過程則將調度過程的決策應用到集群中(也就是在被選定的節點上運行 pod)。這兩個階段都定義了一些擴展點,用戶可以實現擴展點定義的接口來定義自己的調度邏輯。遇到對應的擴展點時,將調用用戶註冊的擴展。

經過分析,我們選擇在打分這個擴展點上定義自己的擴展。根據打分的分值對節點進行排序,選擇最合適的node節點進行調度。所以這裡我們使用了真正的cpu和內存使用情況來打分。

剛才說了整個調度過程非常複雜,為了減少影響,保證上線的穩定性,我們選擇只針對部分業務應用自定義調度,同時只修改了打分這一個地方。相當於是一個灰度控制,有效保障了自定義調度的安全性。

人物 | 盧克:58同城搜索雲--雲搜核心技術揭秘


總結

58雲搜的整體實現,是利用了容器編排和調度技術,在不侵入原有的檢索系統(esearch)情況下,將有狀態的檢索模塊轉換為無狀態的pod或者容器化部署,實現檢索系統的自動創建和自動維護,極大節省了人力,快速創建一個搜索服務,實現了業務的快速接入,體現了雲技術對搜索效率的提升。

同時在雲環境下,不斷提升服務整體可用性,優化編排調度,不斷提升系統資源利用。目前58雲搜平臺已經接入內部搜索業務200多個,日均查詢量70億,峰值QPS15萬,我們將持續迭代升級雲搜功能,為58業務創造價值。


盧克

TEG技術工程平臺群雲搜索、搜索排序負責人,高級架構師;專注搜索引擎相關技術,目前致力於自然語言處理技術和搜索引擎的結合,主要負責58搜索召回和排序效果優化,58雲搜索平臺建設。

人物 | 盧克:58同城搜索雲--雲搜核心技術揭秘


全文完


分享到:


相關文章: