本文根據第16期美團技術線上沙龍OnLine演講內容整理而成。
應用性能是產品用戶體驗的基石,性能優化的終極目標是優化用戶體驗。當我們談及性能,最直觀能想到的一個詞是“快”,Strangeloop在對眾多的網站做性能分析之后得出了一個著名的3s定律“頁面加載速度超過3s,57%的訪客會離開”,可見頁面加載速度對于互聯網產品的重要性。速度在Google、百度等搜索引擎的PR評分中也占有一定的比例,會影響到網站的SEO排名。“天下武功,唯快不破”,套在性能上面也非常適用。
性能優化是個系統性工程,涉及到后端、前端、移動端、系統網絡及各種基礎設施,每一塊都需要做各自的性能優化。當我們系統的分析性能問題時,可以通過以下指標來衡量:
Web端:首屏時間、白屏時間、可交互時間、完全加載時間等。
首屏時間是指從用戶打開網頁開始到瀏覽器第一屏渲染完成的時間,是最直接的用戶感知體驗指標,也是性能領域公認的最重要的核心指標。
首屏時間 = DNS時間 + 建立連接時間 + 后端響應時間 + 網絡傳輸時間 + 首屏頁面渲染時間
移動端:Crash率、內存使用率、FPS(Frames Per Second, 每秒傳輸幀數)、端到端響應時間等。
Native相比于H5在交互體驗方面有更多的優勢,FPS是體現頁面順暢程度的一個重要指標,另外移動端開發同學還需要關注App進程的CPU使用率、內存使用率等系統性能指標。端到端響應時間是衡量一個API性能的關鍵指標,比純后端響應時間更全面,它會受到DNS、網絡帶寬、網絡鏈路、HTTP Payload等多個因素的影響。端到端響應時間是DNS解析時間、網絡傳輸時間及后端響應時間的總和。
后端:響應時間(RT)、吞吐量(TPS)、并發數等。
后端系統響應時間是指系統對請求做出響應的時間(應用延遲時間),對于面向用戶的Web服務,響應時間能很好度量應用性能,會受到數據庫查詢、RPC調用、網絡IO、邏輯計算復雜度、JVM垃圾回收等多方面因素影響。對于高并發的應用和系統,吞吐量是個非常重要的指標,它與request對CPU、內存資源的消耗,調用的外部接口及IO等緊密關聯。
影響性能的因素
互聯網產品是創意、設計、研發、系統、網絡、硬件、運維等眾多資源相互交織的集合體,性能受多方面因素影響,猶如一只木桶,木桶能盛多少水,取決于最短的那塊木板,也可稱之為短板效應。影響產品性能的因素有:
1. 產品邏輯與用戶行為
產品邏輯過于復雜、功能交互過于豐富、產品設計過于絢麗、頁面元素素材過多等都會影響產品性能。
2. 基礎網絡
中國的基礎網絡是世界上最復雜的基礎網絡,國內的網絡運營商眾多且各自為政,互聯互通成本很高。對于境外業務來說更是要面對國內國際網絡交互的情況,再加上GFW的存在,網絡延遲、丟包現象非常嚴重。
3. 代碼及應用
開發語言瓶頸、代碼質量及系統架構等都會影響系統性能,常見的代碼及應用問題有:
- 架構不合理。業務發展超越架構支撐能力而導致系統負荷過載,進而導致出現系統奔潰、響應超時等現象。另外不合理的架構如:單點、無cache、應用混部署、沒有考慮分布式、集群化等也都會影響性能。
- 研發功底和經驗不足。開發的App、Server效率和性能較低、不穩定也是常見的事情。
- 沒有性能意識,只實現了業務功能不注意代碼性能,新功能上線后整體性能下降,或當業務上量后系統出現連鎖反應,導致性能問題疊加,直接影響用戶體驗。
- 多數的性能問題發生在數據庫上。由慢SQL(詳情可以參考美團技術團隊博客的經典文章《MySQL索引原理及慢查詢優化》)、過多查詢等原因造成的數據庫瓶頸,沒有做讀寫分離、分庫分表等。
4. 移動端環境
移動互聯網時代,移動端環境的復雜性對產品的性能影響也很大,比如用戶的設備類型、設備性能、操作系統類型、系統版本及網絡類型(電信/移動/聯通,Wi-Fi/4G/3G/2G)等。
5. 硬件及云環境
硬件的發展遵循著摩爾定律,生命周期一般都很短,服務器老化或其他硬件問題經常會導致應用故障。IDC、機架、服務器、內存、磁盤、網卡等不同硬件和操作系統上運行的應用性能差距可以達到數十倍之多。
關于性能優化這個主題,美團技術團隊博客之前也發表過不少系統闡述的文章,比如《常見性能優化策略的總結》 和 《性能優化模式》,可以參考。
美團旅行境外業務主要包含商戶信息、用戶評論、特色美食、出境線路、境外當地玩樂、購物優惠券等6大板塊,滿足用戶行前到行中的出境場景。在覆蓋城市上,目前已經100%覆蓋全球熱門旅游目的地,大家出境游玩時都可以體驗使用。根據官方提供的數據,超過30%的自由行游客在出境時會選擇使用美團,當前美團已經成為除微信之外,國人在境外最喜歡打開的移動App之一。
境外業務與其他境內業務相比,區別主要表現在以下及方面:
用戶在境外訪問
境外業務很大一部分流量來自境外訪問,國外網絡情況十分復雜,一些國家的網絡基礎設施很差,4G覆蓋率很低,從國外訪問國內機房,不僅網絡鏈路長,還涉及到跨網跨運營商跨GFW的訪問情況,訪問延遲、網絡丟包等情況非常嚴重。
大量使用Hybrid實現
由于業務發展很快,業務新增及變更也相對頻繁,為適應業務的快速發展,我們大量采用的是H5方式實現,大量使用Hybrid模式。H5相比Native頁面需要加載的內容更多,對網絡環境的要求更高。
與境外商家對接
除了用戶在境外訪問,境外業務還會和很多境外的商家、供應商或代理商有合作對接,同樣面臨著跨國網絡訪問的問題。
基于以上背景,如何提升產品性能,做到像國內業務一樣,其中面臨了很多的技術挑戰。本文將從網絡優化、前端優化、后端優化幾個方面來介紹境外業務在性能優化方面的做過的一些事情。
影響網絡性能的問題有很多,常見的網絡問題有以下幾類:
問題一:DNS問題
DNS問題最容易被大家所忽視,而實際上DNS出問題的概率非常大,DNS問題主要有2類:
一類是DNS解析慢或解析失敗,我們統計過一些數據,我們的域名在國內DNS解析耗時大概在30-120ms之間,而國外網絡下耗時達到200-300ms左右。在2G/3G等弱網環境下,DNS解析失敗非常常見。DNS對于首次網絡訪問的耗時及網絡成功率會有很大的影響。
下圖是我們利用頁面測速工具(GTmatrix)在加拿大溫哥華節點測試的一個頁面首次訪問時的網絡請求情況,可以看出當用戶在加拿大第一次訪問且運營商LocalDNS無NS緩存記錄時,DNS解析耗時2.36s。
另一類常見問題是DNS劫持或失效,烏云(WooYun)上曾報過多起因域名服務商安全漏洞被黑客利用導致網站NS記錄被篡改的case。而更多的DNS劫持問題則是來自于網絡運營商的作惡,主要有以下幾種:
- 本地緩存,各運營商確保網內訪問,同時減少跨網結算,運營商在網內搭建了內容緩存服務器,把用戶域名強行指向內容緩存服務器。
- 內容劫持,有部分LocalDNS會把部分域名解析指向內容緩存,并替換成第三方廣告聯盟的廣告。
- 解析轉發,運營商的LocalDNS還存在解析轉發的形象。指運營商自身不進行域名遞歸解析,而是把域名解析請求轉發到其他運營商的遞歸DNS上,解析請求的來源IP成了其他運營商的IP,從而導致用戶請求跨網訪問,性能變差。
問題二:網絡鏈路問題
鏈路過長、請求經過的路由轉發跳數過多、跨網訪問等都是影響網絡傳輸性能的關鍵因素。另外網絡攻擊(主要是DDoS、CC攻擊等洪水攻擊)流量也影響著網絡鏈路的穩定性。據統計,骨干網上每天有數百G的流量為攻擊流量。
問題三:傳輸Payload大小
移動設備的網絡在非Wi-Fi環境下時通常不太穩定,再加上有TCP擁塞策略的限制,數據傳輸量越大,傳的就越慢。我們需要盡量的減少數據傳輸量。通常的做法有:數據壓縮、圖片壓縮、選擇更高效的序列化算法(比如Protocol Buffers)等。
我們在網絡優化方面主要做了以下幾件事情:
- CDN優化:海外CDN加速、CDN緩存預熱。
- DNS Prefetch:DNS預熱,刷新移動設備系統/VM的DNS緩存。
- 長連接:“代理長連接”Shark,專線鏈路優化,并且有效解決了DNS的瓶頸問題。
- 網絡鏈路優化:通過專線和代理,解決公網鏈路長及網絡抖動不穩定的問題。
接下來,我們分別詳細闡述一下。
CDN服務的好壞主要取決于節點部署的覆蓋程度、帶寬以及調度算法。對國內業務而言,使用藍汛、網宿、帝聯等老牌CDN服務商或騰訊云、阿里云、UPYUN等云CDN服務商性能都很好,但這些CDN服務商在境外的節點很少。為了提升境外的靜態資源加速效果,我們嘗試對接了很多國外的知名CDN服務商。通過智能DNS解析用戶的IP來源,如果是境外訪問則CNAME到國外CDN,國內訪問時仍然走的是國內CDN。
CDN也是一種緩存,是緩存就不得不談命中率的問題。 如果用戶在境外訪問時CDN未命中,靜態資源從境外回源到國內源站獲取,成本非常高。為了提升緩存命中率,我們的做法是在香港搭了一個CDN中間源,在前端資源發布時會調用CDN的push接口把資源預熱到中間源,保證當境外邊緣節點緩存未命中時無需再回源到國內IDC,只需從中間源獲取。
由于DNS的種種問題,騰訊推出了HttpDNS服務,使用HTTP協議向DNS服務器的80端口進行請求,代替傳統的DNS協議向DNS服務器的53端口進行請求,繞開Local DNS,避免網絡劫持和跨網訪問等問題。但HttpDNS需要能夠獲取CDN邊緣節點的IP,這就限制了只有像騰訊、阿里這種有自建CDN的大廠才能實現。
另外W3C也提供了DNS預讀的方案,可以通過在服務器端發送 X-DNS-Prefetch-Control 報頭,或是在文檔中使用值為 http-equiv 的 <meta> 標簽:
<meta http-equiv=“x-dns-prefetch-control” content=“on”> 的方式來打開瀏覽器的DNS預讀取功能,但是該API功能目前在移動端瀏覽器內核中實現支持的較少。
我們采取的是一種輕量級的方案,如下:
- 利用App啟動時的config接口,下發DNS Prefetch的配置參數:開關、時間間隔、需要進行prefetch的域名列表等。
- 監聽App啟動、網絡變化、定位城市變化、配置文件變化、前后臺切換等事件,在獨立的線程中執行DNS Prefetch的邏輯。
- 如果開關打開,且上次Prefetch的時間距離當前的時間大于閾值,則刷新DNS,觸發操作系統/VM層的緩存功能。
DNS Prefetch上線后境外域名解析時間RT90從350ms下降至250ms左右。
HTTP請求重度依賴DNS,DNS劫持、移動端網絡不穩定使建連失敗,以及公網鏈路質量差等因素,導致移動端的網絡成功率一直不高。HTTP 2.0可以通過SSE、WebSocket等方式與服務端保持長連接,并且可以做到請求多路復用,但HTTP 2.0對運維、前端、后端的改造成本非常高。基于此背景美團自研了Shark服務。一種“代理長連接”的模式,主要用于解決移動設備網絡通信質量差的問題。
- Shark在國內和境外部署了多個接入點,類似于CDN的就近訪問,用戶可以就近連接到Shark節點。
- Shark各節點的IP會在App啟動時加載到設備,客戶端通過“跑馬測試”(ping各節點)的方式選擇最優節點,建立并保持TCP長連接。
- Shark節點和IDC之間通過專線連接,從而保證了網絡鏈路的質量。
- 客戶端Shark的網絡層會攔截App內的HTTP請求,通過特定的協議格式將HTTP請求信息轉化成TCP包傳到Shark節點,Shark節點再將TCP請求“還原”成HTTP,再通過專線請求后端服務。
- 當Shark通道出問題的時候,可以failover到普通的HTTP模式,從而實現高可用。
這種“代理長連接”的模式,對后端業務是無感知的,業務無需做任何改造。另外也巧妙的繞開了DNS、公網質量差等問題,極大的提升了Native API請求的網絡成功率。
關于Shark的詳情,可以參考之前發表的文章《美團移動網絡優化實踐》。
Ajax接長連
目前美團大部分的App都接入了Shark SDK基礎網絡庫,Native API(我們內部叫Mobile API,MAPI)的網路請求由Shark SDK統一解決,使用的是自定義的序列化方式(內部稱DPObject,比JSON效率高)。但對于H5頁面中的Ajax請求,是沒法直接享受到Shark帶來的“福利”的。先看一下Hybrid模式下一次Ajax請求的過程:
上圖可以看出,一次普通的Ajax請求會由WebView的內置瀏覽器內核來發送接受請求,一般是JSON格式的數據,和PC瀏覽器的一次HTTP請求過程差別不大,都是要經過DNS、TCP建連以及要面對公網鏈路差等問題,另外Ajax請求沒法復用TCP連接,意味著每次請求都要重新建連。有了MAPI的經驗,我們很容易想到,能否像MAPI一樣利用長連通道來提升性能呢?
一種方式是在WebView中攔截頁面的HTTP請求,在容器層做請求代理并處理序列化反序列化等事情。這種方式對業務比較友好,業務方幾乎不需要做什么事情。但WKWebView的限制比較多,所以該方案目前很難推行。另一種方式是通過JsBridge來實現,缺點是對業務侵入性較高,業務方需要手動控制橋API的調用,一期我們選擇的是“較笨拙”的方案二。
用戶境外訪問
Ajax接長連解決了Hybrid模式下App內的H5場景,而對于App外的入口場景,如M站(針對手機的網站)、微信朋友圈分享等,我們沒法使用到Shark長連接,跨網跨國訪問的問題依然存在。這種情況下我們的優化主要是“利用專線”:
- 我們的后臺應用和數據部署在上海機房,在香港機房(香港IDC是個租用機房,未部署數據和應用,非“異地多活”)內部署了一組SLB(反向代理和七層負載均衡,基于tenginx實現)。
- 利用專線連接上海和香港的機房,解決了GFW攔截過濾、跨境網絡訪問及公網鏈路差的問題。
- 當用戶在境外訪問時,智能DNS會解析出香港機房的IP,請求經香港SLB走專線轉發到境內服務器;而當用戶在境內訪問時,則直接請求到上海的機房。
境外直連對接
另一個場景是,我們和很多的境外供應商有直連對接,通過HttpClient的方式后端發起調用對方的Open API接口,這種場景優化前接口延遲及網絡成功率都非常不理想(很多和國外對接的業務應該都遇到過類似的問題),我們的優化方案是:
在香港部署一個正向代理Squid,請求先由內網專線轉發到香港的Squid服務器,再從香港機房的網絡出口出去。以與香港迪士尼的對接為例,優化前的API接口RT95:9s+(迪士尼接口傳輸的數據非常多),優化后降到2.3s,效果非常明顯。
CDN動態加速
除了專線方案,我們還測試CDN動態加速。
CDN不僅可以用來對靜態資源做緩存加速,也可以對動態數據接口起加速作用,原理如下:
用戶請求耗時=用戶和邊緣交互的時間 + 1*RTT(邊緣到源站)+ 源站處理時間
HTTP請求中,建連是個非常耗時的事,普通HTTP請求TCP 3次握手要消耗2個RTT時間,如果用戶和服務器位置很遠,比方說用戶在美國,服務在中國,請求走海底光纜的話一次RTT理論值是150ms左右(光波信號傳輸速度結合物理距離計算得出),實際肯定大于理論值。
CDN動態加速主要在以下幾方面起到優化效果:
- 用戶與服務器的建連改成與CDN邊緣節點建連(就近訪問),縮短了建連時間,同時也提升了建連成功率。
- CDN與源站之間通信相比公網網絡鏈路質量有保證。
- CDN節點和源站的連接可復用。
我們實測下來CDN動態加速在部分國家和地區有明顯的加速效果,但整體的效果不夠明顯,所以最終未投入規模使用。
前端優化我們主要做了下面幾件事情:
- 前后端分離
- 圖片優化
- 域名收斂、減少請求
- 離線化
- 首屏Node后端同構渲染
在之前的項目中,頁面是“Java直出”的方式,由Java后端項目中通過FTL模板引擎拼裝,前端團隊會維護另外一個前端的項目,存放相應的CSS和JS文件,最后通過公司內部的Cortex系統打包發布。
這個流程的問題在于前端對于整個頁面入口沒有控制力,需要依賴后端的FTL拼裝,頁面的內容需要更改時,前后端同學就要反復溝通協調,整體效率比較差,容易出錯,也不方便實現前端相關的優化,前端做模塊組件化的成本較高。
前后端分離的關鍵點在于前端擁有完整獨立的開發、測試、部署的流程,與后端完全分離。我們把頁面的組裝完全放置到了前端項目,后端只提供Ajax的接口用于獲取和提交數據。前端頁面完全靜態化,構建完畢之后連同相應的靜態資源通過CI直接發布到CDN。這樣的好處有:
- 前后端同學的開發工作解耦,只需要約定好API,兩邊即可并行開發。
- 后端API可以做到多端復用,比如PC、H5、M站、小程序等。
- 前端主文檔HTML頁面可以利用CDN加速。
前后端分離架構有諸多的優點,但有一個坑需要注意:SEO的問題,無法提供給搜索引擎可收錄的頁面,因為主文檔HTML基本為空頁面,需要搜索引擎蜘蛛擁有執行JavaScript的能力才行,現實是大部分的搜索引擎都不支持。所以對于一些需要搜索引擎引流的頁面不推薦用前后端分離。
在一些重體驗的網頁上,圖片資源的占比通常較大,一些高清大圖動則幾十上百K大小。 針對圖片這塊我們主要做了以下幾點優化:
圖片尺寸按屏幕大小自適應。原先我們圖片的尺寸都是由后端控制,由服務在代碼中寫死下發給前端,這樣帶來問題是:
- 不同設備不同大小的屏幕上使用的圖片尺寸一樣,無法滿足所有設備。
- 一些沒經驗的開發同學經常亂用尺寸,比如我們POI列表頁的商戶頭圖只需要200 * 200就夠了。
而新手工程師可能使用的是800 * 800的圖片,導致頁面加載慢、用戶流量白白被浪費且客戶端還需要做圖片壓縮剪裁。
美團云的圖片服務提供了實時剪裁功能,后端在下發圖片URL時不需要指定尺寸,由客戶端根據屏幕尺寸做自適應計算,這樣可保證每臺設備上的圖片都“剛好合適”。
CDN加速:前面CDN優化章節已介紹,通過接入境外CDN服務商及CDN預熱的方式做CDN加速。
圖片壓縮:境外業務內部已在全面使用WebP,經測試WebP格式能夠優化圖片大小25%-50%,清晰度基本沒有影響。
懶加載:圖片資源通常比較大,選用懶加載可有效縮短頁面可交互時間。
域名和請求數過多會帶來以下問題:
- DNS解析成本高。
- CDN加速一般都是按域名來做配置,過多的域名無形增加了CDN接入的成本。
- 瀏覽器的并發加載數限制,瀏覽器對單域名的并發度是有限的,超過限制的請求需要等待串行加載,頁面加載速度會變慢。
我們做了以下幾件事:
- 去掉一些直接引入的第三方腳本,將腳本直接打包到我們的代碼中(可以利用CDN)。
- 所有靜態資源共用一個域名。
- 將一些尺寸較小的腳本和CSS構建過程中內聯到主文檔中。
通過域名收斂/減少請求數,我們商品詳情頁的頁面請求數從8個減少到4個、域名數也減少一半,頁面完全加載時間下降了約1000ms。
離線化可以減少網絡請求,加速頁面加載速度。另外當用戶網絡不穩定或斷網時也可以訪問已被緩存的頁面和資源,我們先后使用了2種離線化方案:
AppCache(HTML Application Cache API),在前端項目構建流程中,通過分析頁面資源依賴關系,自動生成資源manifest文件,這樣就能夠確保頁面及資源發生變更時,manifest文件內容同步更新。當瀏覽器監測到manifest文件有更新時,會自動重新下載manifest里面的文件。AppCache的一個缺點是緩存文件會越來越多,緩存不容易清理。AppCache未來會逐步被Service Worker所取代,無論從靈活性還是可擴展性而言,SW都更勝一籌。
目前在使用的是公司平臺自研的離線包框架,相比于AppCache,離線包框架在資源更新,離線配置,內存管理等方面都做了很大的改善。另外AppCache對于用戶第一次加載頁面是沒有加速效果的,因為只有第一次訪問之后才會把資源緩存下來。而離線包框架則可以做到真正的預加載,它會監聽APP正常啟動事件,當APP啟動后即可開始加載更新離線資源。
前面介紹了前后端分離的架構,HTML主文檔可以利用CDN加速,另外前后端同學很好的解耦開了,前端可以更方便的做組件化沉淀。但這種架構除了SEO時的問題還有另外一個問題,先看一下前后端分離下的一個頁面加載過程:
當遇到頁面引入的外部依賴很多時,這種架構性能可能還不如”Java直出”:
同構渲染,結合了Java直出和前后端分離的優勢:
- 通過在Java API之前加入Node層,Node由前端同學來維護,這樣仍然可以做到前后端解耦,后端同學只需要寫Ajax返回JSON,甚至只需要通過RPC接口。
- 縮短并優化了前端串行請求的鏈路,首屏數據可以更早的展示。
- 相比于服務端,移動端設備的性能較弱,頁面在服務端渲染比在前端渲染會快很多。配合上Ajax長連等網絡優化技術,Node同構首屏后端渲染提升了首屏加載速度。
Node同構和一開始的Java freemark后端渲染Java直出的方式對比,最大的區別在于:Node項目可由前端同學來維護,用的是前端工程師熟悉的JS語言。另外前端生態較好,React、Vue等框架都提供了豐富的渲染模板供前端工程師選擇。
后端優化的思路相對比較比較通用,和境外業務的特點關系性并不大,文中的前言部分“影響性能的因素”章節有簡單描述,本文將不對各種后端優化手段做詳細介紹, 只挑幾件我們做過的事情做下簡單介紹:
1. 硬件升級
硬件問題對性能的影響不容忽視,早期的時候,我們的一個DB集群經常有慢SQL報警,業務排查下來發現SQL都很簡單,該做的索引優化也都做了。后來DBA同學幫忙定位到問題是硬件過舊導致,將機械硬盤升級成固態硬盤之后報警立馬消失了,效果立竿見影!
2. 緩存化
緩存可以稱的上是性能優化的利器,使用緩存時需要考慮緩存命中率、緩存更新、數據一致性、緩存穿透及雪崩、Value過大等問題,可以通過mutiGet將多次請求合并一次、異步訪問等方式來提升緩存讀取的性能。
3. 產品邏輯優化
業務邏輯優化經常會容易被忽略,但效果卻往往比數據庫調優、JVM調優之類的來的更明顯。
舉個例子,我們的商家系統有一個商家導出歷史訂單的功能,接口經常超時。排查下來是由于功能上默認是導出商家的全部歷史訂單,數據量過大導致。而實際業務上幾個月之前已完成的訂單對商家來說并沒有什么意義,如果是要看統計數據我們有專門的統計功能。后來和PM商量后在導出時增加了時間段選擇項,默認只會導出最近3個月的訂單,超時問題順利解決。
再比如,12306春運搶火車票的場景,由于訪問的人多,用戶點擊“查票”之后系統會非常卡,進度條非常慢,作為用戶,我們會習慣性的再去點“查票”,可能會連續點個好幾次。假設平均一個用戶點5次,則后端系統負載就增加了5倍!而其中80%的請求是重復請求。這個時候我們可以通過產品邏輯的方式來優化,比如,在用戶點擊查詢之后將“按鈕置灰”,或者通過JS控制xx秒只能只能提交一次請求等,有效的攔截了80%的無效流量。
4. 服務化
我們做服務化最基礎的是按業務做服務拆分,避免跨業務間的互相影響,數據和服務同時拆分。同一個業務內部我們還按計算密集型/IO密集型的服務拆分、C端/B端服務拆分、核心/非核心服務拆分、高頻服務單獨部署等原則做拆分。
5. 異步化
異步化可以利用線程池、消息隊列等方式實現。使用線程池的時候一定要注意核心參數的設置,可以通過監控工具去觀測實際創建、活躍、空閑的線程數,結合CPU、內存的使用率情況來做線程池調優。
另一種是通過NIO實現異步化,一切網絡IO皆可異步:RPC框架、Servlet 3.0提供的異步技術、Apache HttpAsyncClient、緩存異步接口等等。
6. 搜索引擎
復雜查詢以及一些聚合計算不適合在數據庫中做,可以利用搜索引擎來實現,另外搜索引擎還可以幫我們很好的解決跨庫、跨數據源檢索的場景。
問題背景
美團在上海、北京兩地都有機房,以我們的商品服務為例,商品服務會同時被上海和北京的兩側的應用依賴調用。一開始我們的服務只部署在上海機房,由于上海、北京兩地機房間地理間隔較遠(北京-上海專線ping延遲30ms左右),當北京的應用調服務時就會有較高的延遲,如果一個API內多次跨地域調用則性能會非常差。
為此我們做了如下的緩存雙集群加異地模式部署:
- 商品靜態信息全緩存,緩存未命中時再查DB。
- DB以主從的方式部署,北京機房也部署了一套從庫。
- 緩存數據更新使用Databus,基于binglog數據同步的方式,保障DB和Redis數據的“準實時”同步。
- 服務、緩存、DB均兩地部署,調用方就近訪問(RPC、Cache、DAL等基礎組件支持就近路由)。
- 緩存更新利用Client提供的雙寫模式。當DB數據有變更,Databus監聽到數據更新后,消費程序通過緩存Client提供的雙寫功能往兩個緩存集群同時寫入,服務層讀數據時會選擇就近的緩存集群。
通過這種雙緩存加異地部署的“異地多活”模式(實際是異地只讀),提升了我們服務在跨地域場景下調用時的性能。
結合境外業務特點,本文從網絡優化、前端優化、后端優化幾個角度介紹了境外業務在性能優化上的一些實踐,重點篇幅放在了網絡優化部分。性能優化是一個系統性工程,需要前端、后端和SRE一起協作才能做好。得益于公司強大的高性能前端框架、BGP網絡、高性能應用組件、云平臺等基礎設施,以及在靠譜的運維保障SRE團隊、基礎架構團隊以及平臺團隊支持下,我們境外業務的性能優化取得了階段性的成果,后續還要繼續努力。
- 云霜,美團后臺開發工程師,美團旅行境外度假業務交易后臺組技術負責人,2012年加入原大眾點評。
最后,打一波廣告,美團旅行境外度假業務正在招人,歡迎志同道合的朋友加入我們(簡歷傳送門:yunshuang.tao#dianping.com),加入美團旅行,一起來做改變世界的事。