如何深入理解、應用及擴展 Twemproxy?no.15

Twemproxy 架構及應用

Twemproxy 是 Twitter 的一個開源架構,它是一個分片資源訪問的代理組件。如下圖所示,它可以封裝資源池的分布及 hash 規則,解決后端部分節點異常后的探測和重連問題,讓 client 訪問盡可能簡單,同時資源變更時,只要在 Twemproxy 變更即可,不用更新數以萬計的 client,讓資源變更更輕量。最后,Twemproxy 跟后端通過單個長連接訪問,可以大大減少后端資源的連接壓力。

系統架構

接下來分析基于 Twemproxy 的應用系統架構,以及 Twemproxy 組件的內部架構。

如下圖所示, 在應用系統中,Twemproxy 是一個介于 client 端和資源端的中間層。它的后端,支持Memcached 資源池和 Redis 資源池的分片訪問。Twemproxy 支持取模分布和一致性 hash 分布,還支持隨機分布,不過使用場景較少。

在這里插入圖片描述
應用前端在請求緩存數據時,直接訪問 Twemproxy 的對應端口,然后 Twemproxy 解析命令得到 key,通過 hash 計算后,按照分布策略,將 key 路由到后端資源的分片。在后端資源響應后,再將響應結果返回給對應的 client。

在系統運行中,Twemproxy 會自動維護后端資源服務的狀態。如果后端資源服務異常,會自動進行剔除,并定期探測,在后端資源恢復后,再對緩存節點恢復正常使用。

組件架構

Twemproxy 是基于 epoll 事件驅動模型開發的,架構如下圖所示。它是一個單進程、單線程組件。核心進程處理所有的事件,包括網絡 IO,協議解析,消息路由等。Twemproxy 可以監聽多個端口,每個端口接受并處理一個業務的緩存請求。Twemproxy 支持 Redis、Memcached 協議,支持一致性 hash 分布、取模分布、隨機分布三種分布方案。Twemproxy 通過 YAML 文件進行配置,簡單清晰,且便于人肉讀寫。

在這里插入圖片描述
Twemproxy 與后端資源通過單個長連接訪問,在收到業務大量并發請求后,會通過 pipeline 的方式,將多個請求批量發到后端。在后端資源持續訪問異常時,Twemproxy 會將其從正常列表中剔除,并不斷探測,待其恢復后再進行請求的路由分發。

Twemproxy 運行中,會持續產生海量請求及響應的消息流,于是開發者精心設計了內存管理機制,盡可能的減少內存分配和復制,最大限度的提升系統性能。Twemproxy 內部,請求和響應都是一個消息,而這個消息結構體,以及消息存放數據的緩沖都是重復使用的,避免反復分配和回收的開銷,提升消息處理的性能。為了解決短連接的問題,Twemproxy 的連接也是復用的,這樣在面對 PHP client 等短連接訪問時,也可以反復使用之前分配的 connection,提升連接性能。

另外,Twemproxy 對消息還采用了 zero copy(即零拷貝)方案。對于請求消息,只在client 接受時讀取一次,后續的解析、處理、轉發都不進行拷貝,全部共享最初的那個消息緩沖。對于后端的響應也采用類似方案,只在接受后端響應時,讀取到消息緩沖,后續的解析、處理及回復 client 都不進行拷貝。通過共享消息體及消息緩沖,雖然 Twemproxy 是單進程/單線程處理,仍然可以達到 6~8w 以上的 QPS。

Twemproxy 請求及響應

接下來看一下 Twemproxy 是如何進行請求路由及響應的。

Twemproxy 監聽端口,當有 client 連接進來時,則 accept 新連接,并構建初始化一個 client_conn。當建連完畢,client 發送數據到來時,client_conn 收到網絡讀事件,則從網卡讀取數據,并記入請求消息的緩沖中。讀取完畢,則開始按照配置的協議進行解析,解析成功后,就將請求 msg 放入到 client_conn 的 out 隊列中。接下來,就對解析的命令 key 進行 hash 計算,并根據分布算法,找到對應 server 分片的連接,即一個 server_conn 結構體,如下圖。

在這里插入圖片描述
如果 server_conn的 in 隊列為空,首先對 server_conn 觸發一個寫事件。然后將 req msg 存入到 server_conn 的 in 隊列。Server_conn 在處理寫事件時,會對 in 隊列中的 req msg 進行聚合,按照 pipeline 的方式批量發送到后端資源。待發送完畢后,將該條請求 msg 從 server_conn 的 in 隊列刪除,并插入到 out 隊列中。 后端資源服務完成請求后,會將響應發送給 Twemproxy。當響應到 Twemproxy 后,對應的 server_conn 會收到 epoll 讀事件,則開始讀取響應 msg。響應讀取并解析后,會首先將server_conn 中,out 隊列的第一個 req msg 刪除,并將這個 req msg 和最新收到的 rsp msg 進行配對。在 req 和 rsp 匹配后,觸發 client_conn 的寫事件,如下圖。

在這里插入圖片描述
然后 client_conn 在處理 epoll 寫事件時,則按照請求順序,批量將響應發送給 client 端。發送完畢后,將 req msg 從 client 的 out 隊列刪除。最后,再回收消息緩沖,以及消息結構體,供后續請求處理的時候復用。至此一個請求的處理徹底完成。

Twemproxy 安裝和使用

Twemproxy 的安裝和使用比較簡單。首先通過 Git,將 Twemproxy 從 GitHub clone 到目標服務器,然后進入 Twemproxy 路徑,首先執行 $ autoreconf -fvi,然后執行 ./configure ,最后執行 make(當然,也可以再執行 make install),這樣就完成了 Temproxy 的編譯和安裝。然后就可以通過 src/nutcracker -c /xxx/conf/nutcracker.yml 來啟動 Twemproxy 了。

Twemproxy 代理后端資源訪問,這些后端資源的部署信息及訪問策略都是在 YAML 文件中配置。所以接下來,我們簡單看一下 Twemproxy 的配置。如圖所示,這個配置中代理了 2 個業務數據的緩存訪問。一個是 alpha,另一個是 beta。在每個業務的配置詳情里。首先是 listen 配置項,用于設置監聽該業務的端口。然后是 hash 算法和分布算法。Auto_eject_hosts 用于設置在后端 server 異常時,是否將這個異常 server 剔除,然后進行 rehash,默認不剔除。Redis配置項用于指示后端資源類型,是 Redis 還是 Memcached。最后一個配置項 servers,用于設置資源池列表。

以 Memcached 訪問為例,將業務的 Memcached 資源部署好之后,然后將 Mc 資源列表、訪問方式等設到 YAML 文件的配置項,然后啟動 Twemproxy,業務端就可以通過訪問 Twemproxy ,來獲取后端資源的數據了。后續,Mc 資源有任何變更,業務都不用做任何改變,運維直接修改 Twemproxy 的配置即可。

Twemproxy 在實際線的使用中,還是存在不少問題的。首先,它是單進程/單線程模型,一個 event_base 要處理所有的事件,這些事件包括 client 請求的讀入,轉發請求給后端 server,從 server 接受響應,以及將響應發送給 client。單個 Twemproxy 實例,壓測最大可以到 8w 左右的 QPS,出于線上穩定性考慮,QPS 最多支撐到 3~4w。而 Memcached 的線上 QPS,一般可以達到 10~20w,一個 Mc 實例前面要掛 3~5 個 Twemproxy 實例。實例數太多,就會引發諸如管理復雜、成本過高等一系列問題。

其次,基于性能及預防單點故障的考慮,Twemproxy 需要進行多實例部署,而且還需要根據業務訪問量的變化,進行新實例的加入或冗余實例的下線。多個 Twemproxy 實例同時被訪問,如果 client 訪問策略不當,就會出現有些 Twemproxy 壓力過大,而有些卻很空閑,造成訪問不均的問題。

再次,后端資源在 Twemproxy 的 YAML 文件集中配置,資源變更的維護,比直接在所有業務 client 端維護,有了很大的簡化。但在多個 Twemproxy 修改配置,讓這些配置同時生效,也是一個復雜的工作。

最后,Twemproxy 也無法支持 Mc 多副本、多層次架構的訪問策略,無法支持 Redis 的Master-Slave 架構的讀寫分離訪問。

為此,你可以對 Twemproxy 進行擴展,以更好得滿足業務及運維的需要。

Twemproxy 擴展

多進程改造

性能首當其沖。首先可以對 Twemproxy 的單進程/單線程動刀,改為并行處理模型。并行方案可以用多線程方案,也可以采用多進程方案。由于 Twemproxy 只是一個消息路由中間件,不需要額外共享數據,采用多進程方案會更簡潔,更適合。

多進程改造中,可以分別構建一個 master 進程和多個 worker 進程來進行任務處理,如下圖所示。每個進程維護自己獨立的 epoll 事件驅動。其中 master 進程,主要用于監聽端口,accept 新連接,并將連接調度給 worker 進程。

在這里插入圖片描述
而 worker 進程,基于自己獨立的 event_base,管理從 master 調度給自己的所有 client 連接。在 client 發送網絡請求到達時,進行命令讀取、解析,并在進程內的 IO 隊列流轉,最后將請求打包,pipeline 給后端的 server。

在 server 處理完畢請求,發回響應時。對應 worker 進程,會讀取并解析響應,然后批量回復給 client。

通過多進程改造,Twemproxy 的 QPS 可以從 8w 提升到 40w+。業務訪問時,需要部署的Twemproxy 的實例數會大幅減少,運維會更加簡潔。

增加負載均衡

對于多個 Twemproxy 訪問,如何進行負載均衡的問題。一般有三種方案。

第一種方案,是在 Twemproxy 和業務訪問端之間,再增加一組 LVS,作為負載均衡層,通過 LVS 負載均衡層,你可以方便得增加或減少 Twemproxy 實例,由 LVS 負責負載均衡和請求分發,如下圖。

在這里插入圖片描述
第二種方案,是將 Twemproxy 的 IP 列表加入 DNS。業務 client 通過域名來訪問 Twemproxy,每次建連時,DNS 隨機返回一個 IP,讓連接盡可能均衡。

第三種方案,是業務 client 自定義均衡策略。業務 client 從配置中心或 DNS 獲取所有的Twemproxy 的 IP 列表,然后對這些 Twemproxy 進行均衡訪問,從而達到負載均衡。

方案一,可以通過成熟的 LVS 方案,高效穩定的支持負載均衡策略,但多了一層,成本和運維的復雜度會有所增加。方案二,只能做到連接均衡,訪問請求是否均衡,無法保障。方案三,成本最低,性能也比前面 2 個方案更高效。推薦使用方案三,微博內部也是采用第三種方案。

增加配置中心

對于 Twemproxy 配置的維護,可以通過增加一個配置中心服務來解決。將 YAML 配置文件中的所有配置信息,包括后端資源的部署信息、訪問信息,以配置的方式存儲到配置中心,如下圖。

在這里插入圖片描述
Twemproxy 啟動時,首先到配置中心訂閱并拉取配置,然后解析并正常啟動。Twemproxy 將自己的 IP 和監聽端口信息,也注冊到配置中心。業務 client 從配置中心,獲取Twemproxy 的部署信息,然后進行均衡訪問。

在后端資源變更時,直接更新配置中心的配置。配置中心會通知所有 Twemproxy 實例,收到事件通知,Twemproxy 即可拉取最新配置,并調整后端資源的訪問,實現在線變更。整個過程自動完成,更加高效和可靠。

支持 M-S-L1 多層訪問

前面提到,為了應對突發洪水流量,避免硬件局部故障的影響,對 Mc 訪問采用了Master-Slave-L1 架構。可以將該緩存架構體系的訪問策略,封裝到 Twemproxy 內部。實現方案也比較簡單。首先在 servers 配置中,增加 Master、Slave、L1 三層,如下圖。
在這里插入圖片描述
Twemproxy 啟動時,每個 worker 進程預連所有的 Mc 后端,當收到 client 請求時,根據解析出來的指令,分別采用不同訪問策略即可。

  • 對于 get 請求,首先隨機選擇一個 L1 來訪問,如果 miss,繼續訪問 Master 和 Slave。中間在任何一層命中,則回寫。
  • 對于 gets 請求,需要以 master 為準,從 master 讀取。如果 master 獲取失敗,則從 slave獲取,獲取后回種到 master,然后再次從 master 獲取,確保得到 cas unique id 來自 master。
  • 對于 add/cas 等請求,首先請求 master,成功后,再將 key/value 通過 set 指令,寫到 slave 和所有 L1。
  • 對于 set 請求,最簡單,直接 set 所有資源池即可。
  • 對于 stats 指令的響應,由 Twemproxy 自己統計,或者到后端 Mc 獲取后聚合獲得。

Redis 主從訪問

Redis 支持主從復制,為了支持更大并發訪問量,同時減少主庫的壓力,一般會部署多個從庫,寫操作直接請求 Redis 主庫,讀操作隨機選擇一個 Redis 從庫。這個邏輯同樣可以封裝在Twemproxy 中。如下圖所示,Redis 的主從配置信息,可以用域名的方式,也可以用 IP 端口的方式記錄在配置中心,由 Twemproxy 訂閱并實時更新,從而在 Redis 增減 slave、主從切換時,及時對后端進行訪問變更。
在這里插入圖片描述
本課時,講解了大數據時代下大中型互聯網系統的特點,訪問 Memcached 緩存時的經典問題及應對方案;還講解了如何通過分拆緩存池、Master-Slave 雙層架構,來解決 Memcached 的容量問題、性能瓶頸、連接瓶頸、局部故障的問題,以及 Master-Slave-L1 三層架構,通過多層、多副本 Memcached 體系,來更好得解決突發洪峰流量和局部故障的問題。

本節課重點學習了基于 Twemproxy 的應用系統架構方案,學習了 Twemproxy 的系統架構和關鍵技術,學習了 Twemproxy 的部署及配置信息。最后還學習了如何擴展 Twemproxy,從而使 Twemproxy 具有更好的性能、可用性和可運維性。

可以參考下面的思維導圖,對這些知識點進行回顧和梳理。
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/18187.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/18187.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/18187.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C語言之宏詳解(超級詳細!)

目錄 一、用宏前須知-#define相關知識 大致結構: 對預定義符號的補充: 二、用#define定義宏 什么是宏? #define的替換規則: 三、常用的宏定義 1、宏定義常量 2、定義一個宏語句 3、宏定義函數 宏與函數的對比: …

29【PS 作圖】宮燈 夜景轉換

夜景轉化 1 原圖 2 選中要變換的圖層,然后點擊“顏色查找” 再3DLUT文件中,選擇moonlight.3DL,可以快速把圖層變成偏夜景的顏色 結果如下: 3 選擇“曲線” 把曲線 右邊往上調【亮的更亮】,左邊往下調【暗的更暗】 4 添加燈光 新建一個圖層

前端面試題大合集8----性能優化篇

一、哪些方法可以提升網站前端性能 1、Http請求優化 主要分為減少Http請求次數,減小請求數據量和緩存三方面。 減少Http請求次數,可以通過以下方法實現: 合并js、css文件;使用css-spirites技術合并圖片;壓縮圖片大…

HTML+CSS+JS簡易計算器

HTMLCSSJS簡易計算器 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>簡易計算器</t…

AAA實驗配置

一、實驗目的 掌握AAA本地認證的配置方法 掌握AAA本地授權的配置方法 掌握AAA維護的方法 1.搭建實驗拓撲圖 2.完成基礎配置&#xff1a; 3.使用ping命令測試兩臺設備的連通性&#xff1a; 二、配置AAA 1.打開R1&#xff1a;配置AAA方案 這兩個方框內的可以改名&#xff0c…

百度頁面奔跑的白熊html、css

一、相關知識-動畫 1.基本使用&#xff1a;先定義再調用 2. 調用動畫 用keyframes定義動畫&#xff08;類似定義類選擇器&#xff09; keyframes動畫名稱{ 0%{ width:100px&#xff1b; } 100%{ width:200px; } } 使用動畫 div { width:200px; height:200px; background-…

前端面試題日常練-day28 【面試題】

題目 希望這些選擇題能夠幫助您進行前端面試的準備&#xff0c;答案在文末。 1. 在Vue中&#xff0c;以下哪個選項用于監聽組件生命周期鉤子函數&#xff1f; a) watch b) computed c) lifecycle d) created 2. 在Vue中&#xff0c;以下哪個選項用于在列表渲染時為每個元素…

Pytorch線性模型(Linear Model)

基本步驟 ①首先準備好數據集&#xff08;DataSet&#xff09; ②模型的選擇或者設計&#xff08;Model&#xff09; ③進行訓練&#xff08;Train&#xff09;大部分模型都需要訓練&#xff0c;有些不需要。這一步后我們會確定不同特征的權重 ④推理&#xff08;inferring…

開封旅游三天兩夜旅游攻略

開封是一座歷史悠久的城市&#xff0c;有著豐富的文化遺產和美食。以下是一個三天兩夜的開封旅游攻略&#xff0c;供你參考&#xff1a; 一、行程安排 第一天&#xff1a; 上午&#xff1a;抵達開封&#xff0c;前往酒店辦理入住手續。隨后參觀開封博物館&#xff0c;了解開封…

【Python安全攻防】【網絡安全】一、常見被動信息搜集手段

一、IP查詢 原理&#xff1a;通過目標URL查詢目標的IP地址。 所需庫&#xff1a;socket Python代碼示例&#xff1a; import socketip socket.gethostbyname(www.163.com) print(ip)上述代碼中&#xff0c;使用gethostbyname函數。該函數位于Python內置的socket庫中&#xf…

廣場舞團|基于SprinBoot+vue的廣場舞團系統(源碼+數據庫+文檔)

廣場舞團系統 目錄 基于SprinBootvue的廣場舞團系統 一、前言 二、系統設計 三、系統功能設計 1 系統功能模塊 2 后臺登錄模塊 5.2.1管理員功能模塊 5.2.2社團功能模塊 5.2.3用戶功能模塊 四、數據庫設計 五、核心代碼 六、論文參考 七、最新計算機畢設選題推…

Pytorch-06 使用GPU加速計算

要在PyTorch中使用GPU加速計算&#xff0c;需要將模型和數據移動到GPU上進行處理。以下是上一節演示修改后的示例代碼&#xff0c;展示了如何在訓練過程中利用GPU加速計算&#xff1a; import torch import torch.nn as nn import torch.optim as optim import time# 檢查GPU是…

2024-05-28 問AI: 在深度學習中,什么是反向隨機失活?

文心一言 在深度學習中&#xff0c;反向隨機失活&#xff08;Inverse Randomized Elimination&#xff0c;通常稱為Dropout&#xff09;是一種在訓練深度神經網絡時常用的正則化技術&#xff0c;用于防止過擬合。該技術通過隨機將神經網絡中的一部分神經元“失活”或“丟棄”來…

深度剖析:為什么 Spring 和 IDEA 都不推薦使用 @Autowired 注解

目錄 依賴注入簡介 Autowired 注解的優缺點 Spring 和 IDEA 不推薦使用 Autowired 的原因 構造器注入的優勢 Autowired 注解的局限性 可讀性和可測試性的問題 推薦的替代方案 構造器注入 Setter 注入 Java Config Bean 注解 項目示例&#xff1a;Autowired vs 構造器…

Android 項目Gradle文件講解(Groovy和Kotlin)

Android 項目Gradle文件講解&#xff08;Groovy和Kotlin&#xff09; 前言正文一、Gradle的作用二、Gradle的種類① 工程build.gradle② 項目build.gradle③ settings.gradle④ gradle.properties⑤ gradle-wrapper.properties⑥ local.properties 三、Groovy和Kotlin的語言對比…

裝飾模式:雞腿堡

文章目錄 UML類圖目錄結構Humburger.javaChickenBurger.javaCondiment.javaChuilli.javaLettuce.javaTest.java深度理解test怎么寫 UML類圖 目錄結構 我們從指向最多的開始寫 Humburger.java package zsms;public abstract class Humburger {protected String name;public S…

【接口自動化_05課_Pytest接口自動化簡單封裝與Logging應用】

一、關鍵字驅動--設計框架的常用的思路 封裝的作用&#xff1a;在編程中&#xff0c;封裝一個方法&#xff08;函數&#xff09;主要有以下幾個作用&#xff1a;1. **代碼重用**&#xff1a;通過封裝重復使用的代碼到一個方法中&#xff0c;你可以在多個地方調用這個方法而不是…

C++貪心算法(3)

整數區間 #include<bits/stdc.h> using namespace std; int main() {int n;cin>>n;int a[110][10]{0};for(int i0;i<n;i){cin>>a[i][1]>>a[i][2];}int cnt[110]{0};int mi99999;int mii-1;bool f[110]{false,false,false,false,false,false,false,…

debian讓dotnet 程序以守護進程方式運行,如果意外退出主動開啟

創建服務文件: 打開一個新的.service文件在/etc/systemd/system/目錄下&#xff0c;例如myapp.service sudo nano /etc/systemd/system/myapp.service編輯服務文件: 添加以下內容到myapp.service文件&#xff0c;確保修改ExecStart以指向你的.NET Core應用程序的可執行文件&am…

JVM-調優之-高內存占用問題排查

排查思路 1&#xff09;檢查jvm內存的分配情況 2&#xff09;檢查jvm的gc情況 3&#xff09; 找出占用量比較大的對象 第一步&#xff1a;jmap -heap PID 查看jvm內存使用情況 jmap -heap 2525 可以看到老年代年輕代等其他內存區域內存使用率百分比 第二步&#xff1a;jsta…