forked from CyC2018/CS-Notes
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy path集群.md
212 lines (109 loc) · 10.1 KB
/
集群.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
<!-- GFM-TOC -->
* [一、負載均衡](#一負載均衡)
* [負載均衡算法](#負載均衡算法)
* [轉發實現](#轉發實現)
* [二、集群下的 Session 管理](#二集群下的-session-管理)
* [Sticky Session](#sticky-session)
* [Session Replication](#session-replication)
* [Session Server](#session-server)
<!-- GFM-TOC -->
# 一、負載均衡
集群中的應用服務器(節點)通常被設計成無狀態,用戶可以請求任何一個節點。
負載均衡器會根據集群中每個節點的負載情況,將用戶請求轉發到合適的節點上。
負載均衡器可以用來實現高可用以及伸縮性:
- 高可用:當某個節點故障時,負載均衡器會將用戶請求轉發到另外的節點上,從而保證所有服務持續可用;
- 伸縮性:根據系統整體負載情況,可以很容易地添加或移除節點。
負載均衡器運行過程包含兩個部分:
1. 根據負載均衡算法得到轉發的節點;
2. 進行轉發。
## 負載均衡算法
### 1. 輪詢(Round Robin)
輪詢算法把每個請求輪流發送到每個服務器上。
下圖中,一共有 6 個客戶端產生了 6 個請求,這 6 個請求按 (1, 2, 3, 4, 5, 6) 的順序發送。(1, 3, 5) 的請求會被髮送到服務器 1,(2, 4, 6) 的請求會被髮送到服務器 2。
<div align="center"> <img src="pics/9daa3616-00a4-48c4-9146-792dc8499be3.jpg" width="500px"/> </div><br>
該算法比較適合每個服務器的性能差不多的場景,如果有性能存在差異的情況下,那麼性能較差的服務器可能無法承擔過大的負載(下圖的 Server 2)。
<div align="center"> <img src="pics/bfea8772-d01b-4a51-8adc-edfd7d3dce84.jpg" width="500px"/> </div><br>
### 2. 加權輪詢(Weighted Round Robbin)
加權輪詢是在輪詢的基礎上,根據服務器的性能差異,為服務器賦予一定的權值,性能高的服務器分配更高的權值。
例如下圖中,服務器 1 被賦予的權值為 5,服務器 2 被賦予的權值為 1,那麼 (1, 2, 3, 4, 5) 請求會被髮送到服務器 1,(6) 請求會被髮送到服務器 2。
<div align="center"> <img src="pics/4ab87717-e264-4232-825d-8aaf08f14e8b.jpg" width="500px"/> </div><br>
### 3. 最少連接(least Connections)
由於每個請求的連接時間不一樣,使用輪詢或者加權輪詢算法的話,可能會讓一臺服務器當前連接數過大,而另一臺服務器的連接過小,造成負載不均衡。
例如下圖中,(1, 3, 5) 請求會被髮送到服務器 1,但是 (1, 3) 很快就斷開連接,此時只有 (5) 請求連接服務器 1;(2, 4, 6) 請求被髮送到服務器 2,只有 (2) 的連接斷開,此時 (6, 4) 請求連接服務器 2。該系統繼續運行時,服務器 2 會承擔過大的負載。
<div align="center"> <img src="pics/e98deb5a-d5d4-4294-aa9b-9220d4483403.jpg" width="500px"/> </div><br>
最少連接算法就是將請求發送給當前最少連接數的服務器上。
例如下圖中,服務器 1 當前連接數最小,那麼新到來的請求 6 就會被髮送到服務器 1 上。
<div align="center"> <img src="pics/43d323ac-9f07-4e4a-a315-4eaf8c38766c.jpg" width="500px"/> </div><br>
### 4. 加權最少連接(Weighted Least Connection)
在最少連接的基礎上,根據服務器的性能為每臺服務器分配權重,再根據權重計算出每臺服務器能處理的連接數。
### 5. 隨機算法(Random)
把請求隨機發送到服務器上。
和輪詢算法類似,該算法比較適合服務器性能差不多的場景。
<div align="center"> <img src="pics/a42ad3a7-3574-4c48-a783-ed3d08a0688a.jpg" width="500px"/> </div><br>
### 6. 源地址哈希法 (IP Hash)
源地址哈希通過對客戶端 IP 計算哈希值之後,再對服務器數量取模得到目標服務器的序號。
可以保證同一 IP 的客戶端的請求會轉發到同一臺服務器上,用來實現會話粘滯(Sticky Session)
<div align="center"> <img src="pics/0f399a9f-1351-4b2d-b8a4-2ebe82b1a703.jpg" width="500px"/> </div><br>
## 轉發實現
### 1. HTTP 重定向
HTTP 重定向負載均衡服務器使用某種負載均衡算法計算得到服務器的 IP 地址之後,將該地址寫入 HTTP 重定向報文中,狀態碼為 302。客戶端收到重定向報文之後,需要重新向服務器發起請求。
缺點:
- 需要兩次請求,因此訪問延遲比較高;
- HTTP 負載均衡器處理能力有限,會限制集群的規模。
該負載均衡轉發的缺點比較明顯,實際場景中很少使用它。
<div align="center"> <img src="pics/02a1fbfd-7a9d-4114-95df-ca2445587a1f.jpg" width="500px"/> </div><br>
### 2. DNS 域名解析
在 DNS 解析域名的同時使用負載均衡算法計算服務器 IP 地址。
優點:
- DNS 能夠根據地理位置進行域名解析,返回離用戶最近的服務器 IP 地址。
缺點:
- 由於 DNS 具有多級結構,每一級的域名記錄都可能被緩存,當下線一臺服務器需要修改 DNS 記錄時,需要過很長一段時間才能生效。
大型網站基本使用了 DNS 做為第一級負載均衡手段,然後在內部使用其它方式做第二級負載均衡。也就是說,域名解析的結果為內部的負載均衡服務器 IP 地址。
<div align="center"> <img src="pics/d2c072cc-8b17-480c-813e-18cdb3b4b51f.jpg" width="500px"/> </div><br>
### 3. 反向代理服務器
反向代理服務器位於源服務器前面,用戶的請求需要先經過反向代理服務器才能到達源服務器。反向代理可以用來進行緩存、日誌記錄等,同時也可以用來做為負載均衡服務器。
在這種負載均衡轉發方式下,客戶端不直接請求源服務器,因此源服務器不需要外部 IP 地址,而反向代理需要配置內部和外部兩套 IP 地址。
優點:
- 與其它功能集成在一起,部署簡單。
缺點:
- 所有請求和響應都需要經過反向代理服務器,它可能會成為性能瓶頸。
### 4. 網絡層
在操作系統內核進程獲取網絡數據包,根據負載均衡算法計算源服務器的 IP 地址,並修改請求數據包的目的 IP 地址,最後進行轉發。
源服務器返回的響應也需要經過負載均衡服務器,通常是讓負載均衡服務器同時作為集群的網關服務器來實現。
優點:
- 在內核進程中進行處理,性能比較高。
缺點:
- 和反向代理一樣,所有的請求和響應都經過負載均衡服務器,會成為性能瓶頸。
### 5. 鏈路層
在鏈路層根據負載均衡算法計算源服務器的 MAC 地址,並修改請求數據包的目的 MAC 地址,並進行轉發。
通過配置源服務器的虛擬 IP 地址和負載均衡服務器的 IP 地址一致,從而不需要修改 IP 地址就可以進行轉發。也正因為 IP 地址一樣,所以源服務器的響應不需要轉發回負載均衡服務器,可以直接轉發給客戶端,避免了負載均衡服務器的成為瓶頸。
這是一種三角傳輸模式,被稱為直接路由。對於提供下載和視頻服務的網站來說,直接路由避免了大量的網絡傳輸數據經過負載均衡服務器。
這是目前大型網站使用最廣負載均衡轉發方式,在 Linux 平臺可以使用的負載均衡服務器為 LVS(Linux Virtual Server)。
參考:
- [Comparing Load Balancing Algorithms](http://www.jscape.com/blog/load-balancing-algorithms)
- [Redirection and Load Balancing](http://slideplayer.com/slide/6599069/#)
# 二、集群下的 Session 管理
一個用戶的 Session 信息如果存儲在一個服務器上,那麼當負載均衡器把用戶的下一個請求轉發到另一個服務器,由於服務器沒有用戶的 Session 信息,那麼該用戶就需要重新進行登錄等操作。
## Sticky Session
需要配置負載均衡器,使得一個用戶的所有請求都路由到同一個服務器,這樣就可以把用戶的 Session 存放在該服務器中。
缺點:
- 當服務器宕機時,將丟失該服務器上的所有 Session。
<div align="center"> <img src="pics/1623f524-b011-40c8-b83f-eab38d538f76.png" width="400px"/> </div><br>
## Session Replication
在服務器之間進行 Session 同步操作,每個服務器都有所有用戶的 Session 信息,因此用戶可以向任何一個服務器進行請求。
缺點:
- 佔用過多內存;
- 同步過程佔用網絡帶寬以及服務器處理器時間。
<div align="center"> <img src="pics/40c6570d-c1d7-4c38-843e-ba991b2328c2.png" width="400px"/> </div><br>
## Session Server
使用一個單獨的服務器存儲 Session 數據,可以使用傳統的 MySQL,也使用 Redis 或者 Memcached 這種內存型數據庫。
優點:
- 為了使得大型網站具有伸縮性,集群中的應用服務器通常需要保持無狀態,那麼應用服務器不能存儲用戶的會話信息。Session Server 將用戶的會話信息單獨進行存儲,從而保證了應用服務器的無狀態。
缺點:
- 需要去實現存取 Session 的代碼。
<div align="center"> <img src="pics/fdc45a09-f838-4348-8959-d2c793727788.png" width="600px"/> </div><br>
參考:
- [Session Management using Spring Session with JDBC DataStore](https://sivalabs.in/2018/02/session-management-using-spring-session-jdbc-datastore/)
# 微信公眾號
更多精彩內容將發佈在微信公眾號 CyC2018 上,你也可以在公眾號後臺和我交流學習和求職相關的問題。另外,公眾號提供了該項目的 PDF 等離線閱讀版本,後臺回覆 "下載" 即可領取。公眾號也提供了一份技術面試複習大綱,不僅系統整理了面試知識點,而且標註了各個知識點的重要程度,從而幫你理清多而雜的面試知識點,後臺回覆 "大綱" 即可領取。我基本是按照這個大綱來進行復習的,對我拿到了 BAT 頭條等 Offer 起到很大的幫助。你們完全可以和我一樣根據大綱上列的知識點來進行復習,就不用看很多不重要的內容,也可以知道哪些內容很重要從而多安排一些複習時間。
<br><div align="center"><img width="320px" src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/other/公眾號海報6.png"></img></div>