背景
在美團的價值觀中,“以客戶為中心”被放在一個非常重要的位置,所以我們對服務出現故障越來越不能容忍。特別是目前公司業務正在高速增長階段,每一次故障對公司來說都是一筆非常不小的損失。而整個IT基礎設施非常複雜,包括網路、伺服器、作業系統以及應用層面都可能出現問題。在這種背景下,我們必須對服務進行一次全方位的“體檢”,從而來保障美團多個業務服務的穩定性,提供優質的使用者服務體驗。真正通過以下技術手段,來幫助大家吃的更好,生活更好:
- 驗證峰值流量下服務的穩定性和伸縮性。
- 驗證新上線功能的穩定性。
- 進行降級、報警等故障演練。
- 對線上服務進行更準確的容量評估。
- ……
全鏈路壓測是基於線上真實環境和實際業務場景,通過模擬海量的使用者請求,來對整個系統進行壓力測試。早期,我們在沒有全鏈路壓測的情況下,主要的壓測方式有:
- 對線上的單機或叢集發起服務呼叫。
- 將線上流量進行錄製,然後在單臺機器上進行回放。
- 通過修改權重的方式進行引流壓測。
但以上方式很難全面的對整個服務叢集進行壓測,如果以區域性結果推算整個叢集的健康狀況,往往會“以偏概全”,無法評估整個系統的真實效能水平,主要的原因包括:
- 只關注涉及的核心服務,無法覆蓋到所有的環節。
- 系統之間都是通過一些基礎服務進行串聯,如 Nginx、Redis 快取、資料庫、磁碟、網路等等,而基礎服務問題在單服務壓測中往往不能被暴露出來。
綜合多種因素考慮,全鏈路壓測是我們準確評估整個系統效能水平的必經之路。目前,公司內所有核心業務線都已接入全鏈路壓測,月平均壓測次數達上萬次,幫助業務平穩地度過了大大小小若干場高峰流量的衝擊。
解決方案
Quake (雷神之錘)作為公司級的全鏈路壓測平臺,它的目標是提供對整條鏈路進行全方位、安全、真實的壓測,來幫助業務做出更精準的容量評估。因此我們對 Quake 提出瞭如下的要求:
- 提供模擬線上真實流量的能力
- 壓測和 DDoS 攻擊不同的是,壓測有應用場景,而 DDoS 可能只需要一個請求。為了更真實的還原使用者行為,我們需要獲取線上的真實流量進行壓測。
- 具備快速建立壓測環境的能力
- 這裡的環境指的是線上環境,因為如果壓測的是線下環境,即使不考慮“機器配置是否相同”這個因素,像叢集規模、資料庫體量、網路條件等這些因素,線上下環境下都無法進行模擬,這樣得出壓測結果,其參考價值並不大。
- 支援多種壓測型別
- 壓測型別除了支援標準的 HTTP 協議,還需要對美團內部的 RPC 和移動端協議進行支援。
- 提供壓測過程的實時監控與過載保護
- 全鏈路壓測是一個需要實時關注服務狀態的過程,尤其在探測極限的時候,需要具備精準調控 QPS 的能力,秒級監控的能力,預設熔斷降級的能力,以及快速定位問題的能力。
Quake 整體架構設計
Quake 集資料構造、壓測隔離、場景管理、動態調控、過程監控、壓測報告為一體,壓測流量儘量模擬真實,具備分散式壓測能力的全鏈路壓測系統,通過模擬海量使用者真實的業務操作場景,提前對業務進行高壓力測試,全方位探測業務應用的效能瓶頸,確保平穩地應對業務峰值。
架構圖
Quake 整體架構上分為:
- Quake-Web:壓測管理端,負責壓測資料構造、壓測環境準備、場景管理、壓測過程的動態調整以及壓測報表展示等。
- Quake-Brain:排程中心,負責施壓資源的排程、任務分發與機器資源管理。
- Quake-Agent:壓測引擎,負責模擬各種壓測流量。
- Quake-Monitor:監控模組,統計壓測結果,監控服務各項指標。
管理端核心功能
資料構造
傳統的資料構造,一般由測試人員自己維護一批壓測資料。但這種方式存在很大的弊端,一方面維護成本相對較高,另一方面,其構造出的資料多樣性也不足夠。在真實業務場景中,我們需要的是能直接回放業務高峰期產生的流量,只有面對這樣的流量衝擊,才能真實的反映系統可能會產生的問題。
Quake 主要提供了 HTTP 和 RPC 的兩種資料構造方式:
HTTP 服務的訪問日誌收集
對於 HTTP 服務,在 Nginx 層都會產生請求的訪問日誌,我們對這些日誌進行了統一接入,變成符合壓測需要的流量資料。架構圖如下:
- S3為最終日誌儲存平臺
底層使用了 Hive 作為數倉的工具,使業務在平臺上可以通過簡單的類 SQL 語言進行資料構造。Quake 會從數倉中篩選出相應的資料,作為壓測所需的詞表檔案,將其儲存在 S3 中。
- 詞表:壓測所需的後設資料,每一行代表一個請求,包含請求的 method、path、params、header、body等等。
RPC 線上流量實時錄製
對於 RPC 服務,服務呼叫量遠超 HTTP 的量級,所以線上上環境不太可能去記錄相應的日誌。這裡我們使用對線上服務進行實時流量錄製,結合 RPC 框架提供的錄製功能,對叢集中的某幾臺機器開啟錄製,根據要錄製的介面和方法名,將請求資料上報到錄製流量的緩衝服務(Broker)中,再由 Broker 生成最終的壓測詞表,上傳到儲存平臺(S3)。
- RPC Client:服務的呼叫方
- Server:服務提供方
- Broker:錄製後流量緩衝伺服器
- S3:流量最終儲存平臺
其他優化:
- 流量引數偏移
有些場景下,構造出來的流量是不能直接使用的,我們需要對使用者 ID、手機號等資訊進行資料偏移。Quake 也是提供了包含四則運算、區間限定、隨機數、時間型別等多種替換規則。
- 詞表檔案的分片
資料構造產生的詞表檔案,我們需要進行物理上的分片,以保證每個分片檔案大小盡可能均勻,並且控制在一定大小之內。這麼做的主要原因是,後續壓測肯定是由一個分散式的壓測叢集進行流量的打入,考慮到單機拉取詞表的速度和載入詞表的大小限制,如果將詞表進行分片的話,可以有助於任務排程更合理的進行分配。
壓測隔離
做線上壓測與線下壓測最大不同在於,線上壓測要保證壓測行為安全且可控,不會影響使用者的正常使用,並且不會對線上環境造成任何的資料汙染。要做到這一點,首要解決的是壓測流量的識別與透傳問題。有了壓測標識後,各服務與中介軟體就可以依據標識來進行壓測服務分組與影子表方案的實施。
測試標識透傳
對於單服務來說,識別壓測流量很容易,只要在請求頭中加個特殊的壓測標識即可,HTTP 和 RPC 服務是一樣的。但是,要在整條完整的呼叫鏈路中要始終保持壓測標識,這件事就非常困難。
- 跨執行緒間的透傳:
對於涉及多執行緒呼叫的服務來說,要保證測試標識在跨執行緒的情況下不丟失。這裡以 Java 應用為例,主執行緒根據壓測請求,將測試標識寫入當前執行緒的 ThreadLocal 物件中(ThreadLocal 會為每個執行緒建立一個副本,用來儲存執行緒自身的副本變數),利用 InheritableThreadLocal 的特性,對於父執行緒 ThreadLocal 中的變數會傳遞給子執行緒,保證了壓測標識的傳遞。而對於採用執行緒池的情況,同樣對執行緒池進行了封裝,在往執行緒池中新增執行緒任務時,額外儲存了 ThreadLocal 中的變數,執行任務時再進行替換 ThreadLocal 中的變數。
- 跨服務間的透傳:
對於跨服務的呼叫,架構團隊對所有涉及到的中介軟體進行了一一改造。利用 Mtrace (公司內部統一的分散式會話跟蹤系統)的服務間傳遞上下文特性,在原有傳輸上下文的基礎上,新增了測試標識的屬性,以保證傳輸中始終帶著測試標識。下圖是 Mtrace 上下游呼叫的關係圖:
鏈路診斷
由於鏈路關係的複雜性,一次壓測涉及的鏈路可能非常複雜。很多時候,我們很難確認間接依賴的服務又依賴了哪些服務,而任何一個環節只要出現問題,比如某個中介軟體版本不達標,測試標識就不會再往下進行透傳。Quake 提供了鏈路匹配分析的能力,通過平臺試探性地傳送業務實際需要壓測的請求,根據 Mtrace提供的資料,幫助業務快速定位到標記透傳失敗的服務節點。
- 鏈路診斷總覽
- 鏈路診斷詳情定位
壓測服務隔離
一些大型的壓測通常選擇在深夜低峰時期進行,建議相關的人員要時刻關注各自負責的系統指標,以免影響線上的正常使用。而對於一些日常化的壓測,Quake 提供了更加安全便捷的方式進行。在低峰期,機器基本都是處於比較空閒的狀態。我們將根據業務的需求線上上對整條鏈路快速建立一個壓測分組,隔出一批空閒的機器用於壓測。將正常流量與測試流量在機器級別進行隔離,從而降低壓測對服務叢集帶來的影響。
依賴標識透傳的機制,在 Quake 平臺上提供了基於 IP、機器數、百分比不同方式的隔離策略,業務只需提供所需隔離的服務名,由 Quake 進行一鍵化的開啟與關閉。
壓測資料隔離
還有一個比較棘手的問題是針對寫請求的壓測,因為它會向真實的資料庫中寫入大量的髒資料。我們借鑑了阿里最早提出的“影子表”隔離的方案。“影子表”的核心思想是,使用線上同一個資料庫,包括共享資料庫中的記憶體資源,因為這樣才能更接近真實場景,只是在寫入資料時會寫在了另一張“影子表”中。
對於 KV 儲存,也是類似的思路。這裡講一下 MQ(訊息佇列)的實現,MQ 包括生產和消費兩端,業務可以根據實際的需要選擇在生產端忽略帶測試標識的訊息,或者在消費端接收訊息後再忽略兩種選擇。
排程中心核心設計
排程中心作為整個壓測系統的大腦,它管理了所有的壓測任務和壓測引擎。基於自身的排程演算法,排程中心將每個壓測任務拆分成若干個可在單臺壓測引擎上執行的計劃,並將計劃以指令的方式下發給不同的引擎,從而執行壓測任務。
資源計算
不同的壓測場景,需要的機器資源不一樣。以 HTTP 服務為例,在請求/響應體都在 1K 以內,響應時間在 50ms 以內和 1s 左右的兩個請求,單個施壓機能達到的極限值完全不同。影響壓測能力的因素有很多,計算中心會依據壓測模型的不同引數,進行資源的計算。
主要參考的資料包括:
- 壓測期望到達的 QPS。
- 壓測請求的平均響應時間和請求/響應體大小。
- 壓測的詞表大小、分片數。
- 壓測型別。
- 所需壓測的機房。
事件注入機制
因為整個壓測過程一直處在動態變化之中,業務會根據系統的實際情況對壓力進行相應的調整。在整個過程中產生的事件型別比較多,包括調整 QPS 的事件、觸發熔斷的事件、開啟事故注入、開啟程式碼級效能分析的事件等等,同時觸發事件的情況也有很多種,包括使用者手動觸發、由於系統保護機制觸等等。所以,我們在架構上也做了相應的優化,其大致架構如下:
在程式碼設計層面,我們採用了觀察者和責任鏈模式,將會觸發事件的具體情況作為觀察主題,主題的訂閱者會視情況型別產生一連串執行事件。而在執行事件中又引入責任鏈模式,將各自的處理邏輯進行有效的拆分,以便後期進行維護和能力擴充。
機器管理
排程中心管理了所有的施壓機資源,這些施壓機分佈在北京、上海的多個機房,施壓機採用容器化方式進行部署,為後續的動態擴容、施壓機灰度升級以及異常摘除的提供了基礎保障。
- 動態擴容
業務對壓測的需求有高低峰之分,所以平臺也需要事先部署一部分機器用於日常的業務壓測。當業務申請資源不足時,平臺會按需通過容器化方式動態的進行擴容。這樣做的好處,一方面是節省機器資源,另一方面就是便於升級。不難想象,升級50臺機器相對升級200臺機器,前者付出的代價肯定更小一些。
- 灰度升級
整個機器池維護著幾百臺機器,如果需要對這些機器進行升級操作,難度係數也比較高。我們以前的做法是,在沒有業務壓測的時候,將機器全部下線,然後再批量部署,整個升級過程既耗時又痛苦。為此,我們引入了灰度升級的概念,對每臺施壓機提供了版本的概念,機器選擇時,優先使用穩定版的機器。根據機器目前使用的狀態,分批替換未使用的機器,待新版本的機器跑完基準和迴歸測試後,將機器選擇的策略改為最新版。通過這種方式,我們可以讓整個升級過程,相對平順、穩定,且能夠讓業務無感知。
- 異常摘除
排程中心維持了與所有施壓機的心跳檢測,對於異常節點提供了摘除替換的能力。機器摘除能力在壓測過程中非常有必要,因為壓測期間,我們需要保證所有的機器行為可控。不然在需要降低壓力或停止壓測時,如果施壓機不能正常做出響應,其導致的後果將會非常嚴重。
壓測引擎優化
在壓測引擎的選擇上,Quake 選擇了自研壓測引擎。這也是出於擴充套件性和效能層面的考慮,特別在擴充套件性層面,主要是對各種協議的支援,這裡不展開進行闡述。效能方面,為了保證引擎每秒能產生足夠多的請求,我們對引擎做了很多效能優化的工作。
效能問題
通常的壓測引擎,採用的是 BIO 的方式,利用多執行緒來模擬併發的使用者數,每個執行緒的工作方式是:請求-等待-響應。
通訊圖:
這種方式主要的問題是,中間的等待過程,執行緒資源完全被浪費。這種組合模式下,效能問題也會更嚴重(組合模式:即模擬使用者一連串的使用者行為,以下單為例,請求組中會包含使用者登入、加入購物車、建立訂單、支付訂單、檢視支付狀態。這些請求彼此間是存在先後關係的,下一個請求會依賴於上一個請求的結果。),若請求組中有5個串聯請求,每個請求的時長是200ms,那完成一組請求就需要 1s 。這樣的話,單機的最大 QPS 就是能建立的最大執行緒數。我們知道機器能建立的執行緒數有限,同時執行緒間頻繁切換也有成本開銷,致使這種通訊方式能達到的單機最大 QPS 也很有限。
這種模型第二個問題是,執行緒數控制的粒度太粗,如果請求響應很快,僅幾十毫秒,如果增加一個執行緒,可能 QPS 就上漲了將近100,通過增加執行緒數的方式無法精準的控制 QPS,這對探測系統的極限來說,十分危險。
IO 模型優化
我們先看下 NIO 的實現機制,從客戶端發起請求的角度看,存在的 IO 事件分別是建立連線就緒事件(OP_CONNECT)、IO 就緒的可讀事件 (OP_READ) 和 IO 就緒的可寫事件(OP_WRITE),所有 IO 事件會向事件選擇器(Selector)進行註冊,並由它進行統一的監聽和處理,Selector 這裡採用的是 IO 多路複用的方式。
在瞭解 NIO 的處理機制後,我們再考慮看如何進行優化。整個核心思想就是根據預設的 QPS,保證每秒發出指定數量的請求,再以 IO 非阻塞的方式進行後續的讀寫操作,取消了 BIO 中請求等待的時間。優化後的邏輯如下:
優化一:採用 Reactor 多執行緒模型
這裡主要耗時都在 IO 的讀寫事件上,為了達到單位時間內儘可能多的發起壓測請求,我們將連線事件與讀寫事件分離。連線事件採用單執行緒 Selector 的方式來處理,讀寫事件分別由多個 Worker 執行緒處理,每個 Worker 執行緒也是以 NIO 方式進行處理,由各自的 Selector 處理 IO 事件的讀寫操作。這裡每個 Worker 執行緒都有自己的事件佇列,資料彼此隔離,這樣做主要是為了避免資料同步帶來的效能開銷。
優化二:業務邏輯與 IO 讀寫事件分離
這裡說的業務邏輯主要是針對請求結果的處理,包括對請求資料的取樣上報,對壓測結果的解析校驗,對請求轉換率的匹配等。如果將這些邏輯放在 Worker 執行緒中處理,必然會影響 IO 讀取的速度。因為 Selector 在監聽到 IO 就緒事件後,會進行單執行緒處理,所以它的處理要儘可能的簡單和快速,不然會影響其他就緒事件的處理,甚至造成佇列積壓和記憶體問題。
記憶體優化
壓測引擎另一個重要的指標是 Full GC 的時間,因為如果引擎頻繁出現 Full GC,那會造成實際壓測曲線(QPS)的抖動,這種抖動會放大被壓服務真實的響應時間,造成真實 QPS 在預設值的上下波動。嚴重的情況,如果是長時間出現 Full GC,直接就導致預壓的 QPS 壓不上去的問題。
下面看一組 Full GC 產生的壓測曲線:
為了解決 GC 的問題,主要從應用自身的記憶體管理和 JVM 引數兩個維度來進行優化。
合理分配記憶體物件
- 請求物件載入機制優化:
引擎首先載入詞表資料到記憶體中,然後根據詞表資料生成請求物件進行傳送。對於詞表資料的載入,需要設定一個大小上限,這些資料是會進入“老年代”,如果“老年代”佔用的比例過高,那就會頻發出現 Full GC 的情況。這裡對於詞表資料過大的情況,可以考慮採用流式載入的方式,在佇列中維持一定數量的請求,通過邊回放邊載入的方式來控制記憶體大小。
- 請求物件的快用快銷:
引擎在實際壓測過程中,假設單機是 1W 的 QPS,那它每秒就會建立 1W 個請求物件,這些物件可能在下一秒處理完後就會進行銷燬。如果銷燬過慢,就會造成大量無效物件晉升老年代,所以在對響應結果的處理中,不要有耗時的操作,保證請求物件的快速釋放。
這裡放棄物件複用的原因是,請求的基本資訊佔用的記憶體空間比較小。可一旦轉換成了待傳送物件後,佔用的記憶體空間會比原始資料大很多,在 HTTP 和 RPC 服務中都存在同樣的問題。而且之前使用 Apache HttpAsyncClient 作為 HTTP 請求的非同步框架時,發現實際請求的 Response 物件掛在請求物件身上。也就是說一個請求物件在接收到結果後,該物件記憶體增加了響應結果的空間佔用,如果採用複用請求物件的方式,很容易造成記憶體洩露的問題。
JVM 引數調優
這裡以 JVM 的 CMS 收集器為例,對於高併發的場景,瞬間產生大量的物件,這些物件的存活時間又非常短,我們需要:
- 適當增大新生代的大小,保證新生代有足夠的空間來容納新產生的物件。當然如果老年代設定的過小,會導致頻繁的 Full GC。
- 適當調大新生代向晉升老年代的存活次數,減少無效物件晉升老年代的機率;同時控制新生代存活區的大小,如果設定的過小,很容易造成那些無法容納的新生代物件提前晉升。
- 提前觸發老年代的 Full GC,因為如果等待老年代滿了再開始回收,可能會太晚,這樣很容易造成長時間的 Full GC。一般設在 70% 的安全水位進行回收。而且回收的時候,需要觸發一次 Young GC,這可以減少重新標記階段應用暫停的時間,另一方面,也防止在回收結束後,有大量無效的物件進入老年代中。
- 設定需要進行記憶體壓縮整理的 GC 次數,記憶體整理,很多時候是造成長時間 GC 的主要原因。因為記憶體整理是採用 Serial Old 演算法,以單執行緒的方式進行處理,這個過程會非常慢。尤其是在老年代空間不足的情況下,GC 的時間會變得更長。
監控模組
壓測肯定會對線上服務產生一定的影響,特別是一些探測系統極限的壓測,我們需要具備秒級監控的能力,以及可靠的熔斷降級機制。
客戶端監控
壓測引擎會將每秒的資料彙總後上報給監控模組,監控模組基於所有上報來的資料進行統計分析。這裡的分析需要實時進行處理,這樣才能做到客戶端的秒級監控。監控的資料包括各 TP 線的響應情況、QPS 曲線波動、錯誤率情況以及取樣日誌分析等等。
- 實時 QPS 曲線
- 錯誤率統計
- 取樣日誌
服務端監控
除了通過引擎上報的壓測結果來進行相應的監控分析之外,Quake 還整合了公司內部統一的監控元件,有監控機器指標的 Falcon 系統(小米開源),還有監控服務效能的 CAT系統(美團已經開源)。Quake 提供了統一的管理配置服務,讓業務能在 Quake 上方便觀察整個系統的健康狀況。
熔斷保護機制
Quake 提供了客戶端和服務端兩方面的熔斷保護措施。
首先是客戶端熔斷,根據業務自定義的熔斷闕值,Quake 會實時分析監控資料,當達到熔斷闕值時,任務排程器會向壓測引擎傳送降低 QPS 或者直接中斷壓測的指令,防止系統被壓掛。
被壓服務同樣也提供了熔斷機制,Quake 整合了公司內部的熔斷元件(Rhino),提供了壓測過程中的熔斷降級和限流能力。與此同時,Quake 還提供了壓測故障演練的能力,在壓測過程中進行人為的故障注入,來驗證整個系統的降級預案。
專案總結
最後,總結一下做 Quake 這個專案的一些心得:
小步快跑
其實在 Quake 出來之前,美團公司內部已有一個壓測平臺(Ptest ),它的定位是針對單服務的效能壓測。我們分析了 Ptest 平臺存在的一些問題,其壓測引擎能力也非常有限。在美團發展早期,如果有兩個大業務線要進行壓測的話,機器資源往往會不足,這需要業務方彼此協調。因為準備一次壓測,前期投入成本太高,使用者需要自己構造詞表,尤其是 RPC 服務,使用者還需要自己上傳 IDL 檔案等等,非常繁瑣。
Quake 針對業務的這些痛點,整個團隊大概花費一個多月的時間開發出了第一個版本,並且快速實現了上線。當時,正面臨貓眼十一節前的一次壓測,那也是 Quake 的第一次亮相,而且取得了不錯的成績。後續,我們基本平均兩週實現一次迭代,然後逐步加入了機器隔離、影子表隔離、資料偏移規則、熔斷保護機制、程式碼級別的效能分析等功能。
快速響應
專案剛線上時,客服面臨問題非常多,不僅有使用層面的問題,系統自身也存在一些 Bug 缺陷。當時,一旦遇到業務線大規模的壓測,我們團隊都是全員待命,直接在現場解決問題。後續系統穩定後,我們組內採用了客服輪班制度,每個迭代由一位同學專門負責客服工作,保障當業務遇到的問題能夠做到快速響應。尤其是在專案上線初期,這點非常有必要。如果業務部門使用體驗欠佳,專案口碑也會變差,就會對後續的推廣造成很大的問題。
專案推廣
這應該是所有內部專案都會遇到的問題,很多時候,推廣成果決定專案的生死。前期我們先在一些比較有代表性的業務線進行試點。如果在試點過程中遇到的問題,或者業務同學提供的一些好的想法和建議,我們能夠快速地進行迭代與落地。然後再不斷地擴大試點範圍,包括美團外賣、貓眼、酒旅、金融等幾個大的 BG 都在 Quake 上進行了幾輪全流程、大規模的全鏈路壓測。
隨著 Quake 整體功能趨於完善,同時解決了 Ptest(先前的壓測系統)上的多個痛點,我們逐步在各個業務線進行了全面推廣和內部培訓。從目前收集的資料看,美團超過 90% 的業務已從 Ptest 遷移到了 Quake 。而且整體的統計資料,也比 Ptest 有了明顯的提升。
開放生態
Quake 目標是打造全鏈路的壓測平臺,但是在平臺建設這件事上,我們並沒有刻意去追求。公司內部也有部分團隊走的比較靠前,他們也做一些很多“試水性”的工作。這其實也是一件好事,如果所有事情都依託平臺來完成,就會面臨做不完的需求,而且很多事情放在平臺層面,也可能無解。
同時,Quake 也提供了很多 API 供其他平臺進行接入,一些業務高度定製化的工作,就由業務平臺獨自去完成。平臺僅提供基礎的能力和資料支援,我們團隊把核心精力聚焦在對平臺發展更有價值的事情上。
跨團隊合作
其實,全鏈路壓測整個專案涉及的團隊非常之多,上述提到的很多元件都需要架構團隊的支援。在跨團隊的合作層面,我們應該有“雙贏”的心態。像 Quake 平臺使用的很多監控元件、熔斷元件以及效能分析工具,有一些也是兄弟團隊剛線上沒多久的產品。 Quake 將其整合到平臺中,一方面是減少自身重複造輪子;另一方面也可以幫助兄弟團隊推動產品的研發工作。
作者簡介
耿傑,美團點評高階工程師。2017年加入美團點評,先後負責全鏈路壓測專案和 MagicDB 資料庫代理專案,目前主要負責這兩個專案的整體研發和推廣工作,致力於提升公司的整體研發效率與研發質量。
招聘
團隊長期招聘 Java、Go、演算法、AI 等技術方向的工程師,Base 北京、上海,歡迎有興趣的同學投遞簡歷到gengjie02@meituan.com。