作者:李想
騰訊人做產品一直是很貼近用戶的需求的,騰訊雲也不例外。負載均衡器作為公有雲上的最基礎的網絡服務,幾乎每家雲廠商都會提供,雖然負載均衡的應用場景和基本功能都大同小異,但在具體的技術實現和特性方面也會有一些差異。今天就聊一聊騰訊雲的負載均衡提供給客戶的那些獨有的特性,大家也可以了解下騰訊雲負載均衡器的優勢所在。
1.四七層LB自帶客戶端源IP獲取功能
四層負載均衡獲取客戶端源IP幾乎各大雲廠商都支持,對於四層LB來講,網絡包是一個轉發的過程,所以盡管會有隧道封裝基本上這個信息不會丟,技術層面實現不難。
七層負載均衡通用的做法是做反向代理,類似於Nginx的proxy_pass實現方式,后端服務器收到的網絡包的三層源地址會變成LB的內網地址,然后通過插入X-Forwarded-For HTTP header來傳遞客戶端源IP,微軟Azure包括國內的某些雲廠商都是這種實現方式。
騰訊雲的七層負載均衡器不僅支持X-Forwarded-For獲取客戶端源IP,同時支持三層直接獲取客戶端源IP,也就是說后端服務器上看到的網絡包的源地址就是客戶的真實訪問地址。
下面的截圖顯示的是從后端服務器的抓包,可以看到X-Forwarded-For記錄的地址是我客戶端的地址180.xxx.219.15,同時數據包的三層源地址也是180.xxx.219.15。

騰訊雲這樣做的好處可以極大方便客戶來統計客戶端的來源,Nginx或者Apache不用做任何特殊配置,直接通過Access log就能統計出客戶端來源。
以Nginx為例,跑一下"awk '{print $1}' access.log |sort |uniq -c |sort -k1 -nr |head -n10" 就能很容易拿到訪問量前10的IP。下圖中的前兩名的源地址是內部健康檢查用的,所以訪問量較大,可以忽略。第三名是我們真實的客戶端訪問,跟上面提到的我這邊測試的客戶端IP一致。

鑒於騰訊雲的實現方式,詳細細節可以參考社區文章
https://cloud.tencent.com/developer/article/1004723
架構圖如下,簡單說一下,其本質就是L7 Nginx群集出來的包經過L7.ko內核模塊封裝為GRE包的時候修改內層源地址仍然為客戶端的源IP。

2.Http/https一鍵強制跳轉
隨着大家對網絡安全的重視,https的網站已經成為主流,http到https的強制跳轉也成為許多客戶的基本需求,騰訊雲考慮到這個這個現狀也是提供了一鍵強制轉換的功能。
實現http到https的跳轉本身並不難,最常見的就是利用Nginx的rewrite功能,如果為了防止LB的HTTPS卸載導致的rewrite循環(后端服務器本身只接受http請求),也可以配合檢查X-Forwarded-Proto或者X-Client-Proto來判斷源是否為https來決定是否需要跳轉。
但是這些畢竟還是需要在后端服務器進行配置,騰訊雲提供了一鍵強制轉換的功能,只需在portal進行簡單配置添加一條自動重定向配置即可,前提是已經配置好了https和http監聽。

3.跨地域綁定負載均衡
公網應用型LB支持跨地域綁定雲主機的能力,允許客戶選取后端服務器的地域類型,跨VPC、跨地域綁定后端實例。該功能通過跨域對等連接來實現,可以實現只在一地部署服務器而在不同地域部署LB來提升不同區域用戶的體驗,實現全球通服的場景。
比如下面的場景,我們將LB建立在華南,可以通過修改后端雲主機的的地域為華東而選擇華東區的服務器。注意該功能目前需要通過工單提前申請才能正常使用。

4.支持QUIC協議
QUIC是由Google提出的基於UDP構建的安全多路並發的傳輸層協議,代表了快速UDP Internet連接。QUIC通過改進TCP的握手及擁塞算法,重構TLS協議,以及吸收HTTP2的大部分特性能夠將弱網絡時的速度提升 20% 以上,非常適合一些游戲或者流媒體對速度要求比較高的場景。
騰訊雲的解決方案並不需要服務本身支持QUIC協議,CLB會負責處理QUIC協議並轉換成HTTP1.1協議發送給后端應用服務器,服務器對用戶到CLB的QUIC協議並無感知。其具體的實現方式如下圖所示:

附QUIC測試方法:
1. 我們采用goquic的方案進行測試,所以要提前安裝好GO環境(Centos為例),這邊不再贅述,開源項目地址如下
https://github.com/devsisters/goquic
2.獲取項目文件到本地,並安裝GCC,G++
yum -y install gcc yum -y install gcc-g++ go get -u -d github.com/devsisters/goquic
3.如果沒有配置Ninja,修改build_libs.sh文件
修改前:
cd libquic/$BUILD_DIR cmake -GNinja $OPT ../.. cd - ninja -Clibquic/$BUILD_DIR
修改后:
cd libquic/$BUILD_DIR cmake $OPT ../.. make -j4
4.編譯靜態庫文件
GOQUIC_BUILD=Release ./build_libs.sh
5.編寫testquic.go文件放入goquic項目目錄下
package main import ( "flag" "fmt" "io/ioutil" "net/http" "github.com/devsisters/goquic" "time" ) var url string var logLevel int var quic bool func init() { flag.StringVar(&url, "url", "http://127.0.0.1:8080/", "host to connect") flag.IntVar(&logLevel, "loglevel", -1, "Log level") flag.BoolVar(&quic, "QUIC", true, "use QUIC protocol") } func main() { flag.Parse() goquic.SetLogLevel(logLevel) client := &http.Client{ Transport: goquic.NewRoundTripper(false), } var resp *http.Response var err error t1 := time.Now() if quic == true { resp, err = client.Get(url) } else { resp, err = http.Get(url) } if err != nil { panic(err) } b, err := ioutil.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println("Duration:",time.Now().Sub(t1).Seconds()) fmt.Println("Body Length:", len(string(b))) }
6.編譯程序並運行
go build testquic.go ./testquic -url https://www.google.com/ -QUIC=true