HAproxy 代理技術原理探究

HAproxy 技術分享

簡介

HAProxy是一款提供高可用性、負載均衡以及基於TCP(第四層)和HTTP(第七層)應用的代理軟件java


Features

1.免費
2.可以作到4層以上代理
3.高性能
4.高穩定性node


使用案例

淘寶CDN(HTTP反向代理)nginx


測試:

HTTP代理 ab -i -c 500 -n 100000

| --- node 8910 URL = / HAproxy| --- node 8911 URL = / | --- node 8912 URL = / | --- node 8913 /test/ (reqisetbe ^[^\ ]*\ /(test|uri)/ server_uri_route) #按照規則轉發
####### haproxy : (單獨由haproxy進行均衡負載) Concurrency Level: 500 Time taken for tests: 32.562 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Total transferred: 36606588 bytes HTML transferred: 0 bytes Requests per second: 3071.02 [#/sec] (mean) Time per request: 162.812 [ms] (mean) Time per request: 0.326 [ms] (mean, across all concurrent requests) Transfer rate: 1097.85 [Kbytes/sec] received ####### nginx : (單獨由nginx進行均衡負載) Concurrency Level: 500 Time taken for tests: 36.539 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Total transferred: 38600000 bytes HTML transferred: 0 bytes Requests per second: 2736.82 [#/sec] (mean) Time per request: 182.694 [ms] (mean) Time per request: 0.365 [ms] (mean, across all concurrent requests) Transfer rate: 1031.65 [Kbytes/sec] received

對比Nginx

 

Name Nginx HAproxy
HTTP代理性能 9 10
TCP 代理性能 0 10
穩定性 10 10
轉發規則 10 7
HTTP代理性能 9 10
平滑升級 10 8

原理 epoll 轉發

驗證 轉發方式爲以下
經過TCP代理請求 www.baidu.com算法

client HAProxy Backend curl |----------------->| accept(client) recvfrom(client) sendto(Backent) |-------->| dowith(HAProxy) |<--------| recvfrom(Backend) sendto(Client) |<-----------------| 

strace 查看系統調用負載均衡

zhangbo3@vm-222:/etc/haproxy$ sudo strace -p 7876
    
    epoll_wait(0, {{EPOLLIN, {u32=5, u64=5}}}, 7, 1000) = 1
 *** (事件循環,監聽鏈接事件) accept(5, { sa_family=AF_INET, sin_port=htons(56479), sin_addr=inet_addr("127.0.0.1") }, [16]) = 1  *** (來自客戶端[127.0.0.1]的請求, 端口56479[隨機端口]) fcntl(1, F_SETFL, O_RDONLY|O_NONBLOCK) = 0  *** (設置鏈接socket爲非阻塞) setsockopt(1, SOL_TCP, TCP_NODELAY, [1], 4) = 0  *** (設置TCP鏈接爲 NODELAY, 禁止Nagle算法) accept(5, 0x7fff8da2d7a0, [128]) = -1 EAGAIN (Resource temporarily unavailable)  *** (再次去accept鏈接失敗,由於accept被循環包裹,須要返回 EAGAIN才break) recvfrom(1, "GET HTTP://www.baidu.com HTTP/1."..., 8192) = 212  *** (收到來自客戶端的請求 curl -x 127.0.0.1:1180 www.baidu.com) recvfrom(1, 0x2560ac4, 7980, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)  *** (返回EAGAIN後break,表示收到完整的TCP數據, 開始處理請求數據) epoll_ctl(0, EPOLL_CTL_ADD, 1, {EPOLLIN, {u32=1, u64=1}}) = 0  *** (未來自客戶端的socket加入epoll監聽隊列) socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 2 fcntl(2, F_SETFL, O_RDONLY|O_NONBLOCK) = 0 setsockopt(2, SOL_TCP, TCP_NODELAY, [1], 4) = 0 connect(2, { sa_family=AF_INET, sin_port=htons(8912), sin_addr=inet_addr("127.0.0.1") }, 16) = -1 EINPROGRESS (Operation now in progress)  *** (建立到backend的socket鏈接,這裏backend配置爲8912)  *** (server server3 127.0.0.1:8912) sendto(2, "GET HTTP://www.baidu.com HTTP/1."..., 212, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 212  *** (發送數據到backend) epoll_wait(0, {}, 7, 0) = 0  *** (繼續進入epoll_wait,等待來自backend的數據返回) gettimeofday({1413020002, 322710}, NULL) = 0 recvfrom(2, 0x255c960, 16384, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)  *** (Backend數據來了) epoll_ctl(0, EPOLL_CTL_ADD, 2, {EPOLLIN, {u32=2, u64=2}}) = 0 epoll_wait(0, {{EPOLLIN, {u32=2, u64=2}}}, 7, 1000) = 1 gettimeofday({1413020003, 308930}, NULL) = 0 recvfrom(2, "HTTP/1.1 200 OK\r\nDate: Sat, 11 O"...,16384) = 2896  *** (backend 返回 HTTP 200, 這是標準HTTP協議頭) recvfrom(2, 0x255d4b0, 13488, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable) sendto(1, "HTTP/1.1 200 OK\r\nDate: Sat, 11 O"...) = 2896  *** (將backend返回的數據發送到front end) epoll_wait(0, {{EPOLLIN, {u32=2, u64=2}}}, 7, 1000) = 1  *** (繼續進入epoll_wait) gettimeofday({1413020003, 309695}, NULL) = 0  *** (客戶端鏈接超時,關閉鏈接) shutdown(2, 1 /* send */) = 0 close(2) = 0 shutdown(1, 1 /* send */) = 0 close(1) = 0 

驗證單進程模型 -> 查看線程數
cat /proc/7878/statuscurl

Name:   haproxy
    State:  S (sleeping)
    ...
    Threads:        1 SigQ: 0/15594 SigPnd: 0000000000000000 ShdPnd: 0000000000000000 ...
相關文章
相關標籤/搜索