理解web服務(wù)器和數(shù)據(jù)庫的負(fù)載均衡以及反向代理
但是若該網(wǎng)站平均每秒的請求是200多次,那么問題就來了:這已經(jīng)是最好的web服務(wù)器了,我該怎么辦?同樣的情景也適用于數(shù)據(jù)庫。要解決這種問題,就需要了解“負(fù)載均衡”的原理了。
web服務(wù)器如何做負(fù)載均衡
為web服務(wù)器做負(fù)載均衡適用的的較多的方式是DNS重定向和反向代理,其他的方式原理也是很類似。
我們多次ping一下百度,會發(fā)現(xiàn)回復(fù)的IP會有所不同,例如第一次的結(jié)果為:
正在 Ping baidu.com [220.181.111.86] 具有 32 字節(jié)的數(shù)據(jù):
來自 220.181.111.86 的回復(fù): 字節(jié)=32 時(shí)間=27ms TTL=51
來自 220.181.111.86 的回復(fù): 字節(jié)=32 時(shí)間=27ms TTL=51
來自 220.181.111.86 的回復(fù): 字節(jié)=32 時(shí)間=27ms TTL=51
過一會再Ping一次,結(jié)果可能就變了:
正在 Ping baidu.com [220.181.111.85] 具有 32 字節(jié)的數(shù)據(jù):
來自 220.181.111.85 的回復(fù): 字節(jié)=32 時(shí)間=27ms TTL=51
來自 220.181.111.85 的回復(fù): 字節(jié)=32 時(shí)間=27ms TTL=51
來自 220.181.111.85 的回復(fù): 字節(jié)=32 時(shí)間=29ms TTL=51
使用nslookup命令可以看到多個(gè)ip與baidu.com對應(yīng)。在這里用到的就是DNS重定向技術(shù),原理很簡單:DNS服務(wù)器保存某域名對應(yīng)的多個(gè)IP,客戶端發(fā)出DNS請求時(shí)DNS服務(wù)器根據(jù)算法將IP發(fā)回給客戶端;發(fā)送回的一般是一個(gè)IP地址集合,但是每次的排序不同,第一次的第一個(gè)IP為201.11.11.1,第二次的第一個(gè)可能是201.11.11.2,客戶端使用的是第一個(gè)IP——簡單地說,就是客戶端每次獲取的域名的IP可能不同。不同的IP對應(yīng)不同的web服務(wù)器,但是這些web服務(wù)器的內(nèi)容應(yīng)該是一樣的。
我們從下圖理解反向代理:

客戶端向反向代理發(fā)送HTTP請求報(bào)文(若該網(wǎng)站有域名,域名的IP是反向代理服務(wù)器的外網(wǎng)IP),反向代理將請求報(bào)文隨機(jī)發(fā)送給一個(gè)web服務(wù)器,web服務(wù)器將HTTP響應(yīng)報(bào)文發(fā)送給反向代理,反向代理再將這報(bào)文返回給客戶端。既然這樣簡單,我們就可以著手實(shí)現(xiàn)一個(gè)簡單的反向代理。
在linux mint 15 下安裝apache和nginx服務(wù)器,在apache的80端口的文檔根目錄下創(chuàng)建文件index.html,內(nèi)容如下:
<html>
<head>
<title>index</title>
</head>
<body>
<h1>hello, i am apache</h1>
</body>
</html>
在nginx的8080端口的文檔根目錄下創(chuàng)建文件index.html,內(nèi)容如下:
<html>
<head>
<title>index</title>
</head>
<body>
<h1>hello, i am nginx</h1>
</body>
</html>
創(chuàng)建源文件simple_reverse_proxy.py,內(nèi)容如下:
#!/usr/bin/python
#-*-encoding:utf8-*-
'''
這是一個(gè)簡單的反向代理服務(wù)器
'''
import BaseHTTPServer
import urllib2
HOST_NAME = '127.0.0.1'
PORT_NUMBER = 8081 #端口
SERVER_URL=('http://127.0.0.1:80','http://127.0.0.1:8080')
server_choice = 0
class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(s):
"""response to a GET request"""
global server_choice
url = SERVER_URL[server_choice]
print url
server_choice = (server_choice + 1) % 2
headers = {'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'}
try:
req = urllib2.Request(url, None, headers)
response = urllib2.urlopen(req)
html = response.read()
#print html
s.send_response(200);
s.send_header("Content-type", "text/html")
s.end_headers()
s.wfile.write(html)
except:
s.send_response(404);
s.send_header("Content-type", "text/html")
s.end_headers()
s.wfile.write('<h2>404</h2>')
if __name__ == '__main__':
server_class = BaseHTTPServer.HTTPServer
httpd = server_class((HOST_NAME, PORT_NUMBER), MyHandler)
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
啟動apache、nginx,并運(yùn)行simple_reverse_proxy.py。我們在瀏覽器中打開http://127.0.0.1:8081,我們可以看到:

刷新一下可以看到:

而simple_reverse_proxy.py會有以下信息輸出:
bash >> ./simple_reverse_proxy.py
http://127.0.0.1:80
127.0.0.1 - - [05/Sep/2013 19:25:02] "GET / HTTP/1.1" 200 -
http://127.0.0.1:8080
127.0.0.1 - - [05/Sep/2013 19:25:43] "GET / HTTP/1.1" 200 -
當(dāng)然,開源世界里已經(jīng)有很多優(yōu)秀的反向代理服務(wù)器了,例如Nginx。
只要理解了反向代理的原理,更復(fù)雜的架構(gòu)也容易去實(shí)現(xiàn)。
數(shù)據(jù)庫的負(fù)載均衡
對于大型網(wǎng)站,一個(gè)數(shù)據(jù)庫系統(tǒng)肯定會遇到無法負(fù)擔(dān)大量的讀請求、寫請求的情況。那么我們怎么來通過負(fù)載均衡來實(shí)現(xiàn)高并發(fā)的讀寫請求呢?
這其中一個(gè)很好的方法就是讀寫分離:將原本針對一個(gè)數(shù)據(jù)庫服務(wù)器的讀寫請求分成讀請求和寫請求,向一個(gè)(或者多個(gè))數(shù)據(jù)庫服務(wù)器發(fā)送寫請求,向另外一個(gè)(或多個(gè))服務(wù)器發(fā)送讀請求,這可以明顯的提高響應(yīng)時(shí)間。不過其中有一個(gè)難點(diǎn),就是必須保持多個(gè)數(shù)據(jù)庫服務(wù)器中的數(shù)據(jù)是一致的,不用擔(dān)心,很多數(shù)據(jù)庫系統(tǒng)已經(jīng)實(shí)現(xiàn)了這個(gè)功能。下面是一個(gè)架構(gòu)示例:
上圖中其實(shí)有一個(gè)寫寫沖突的問題,想象以下場景:
該系統(tǒng)用于存放某網(wǎng)站的用戶注冊信息,該網(wǎng)站不允許用戶名相同,且以用戶名為唯一主鍵,所以在單數(shù)據(jù)庫架構(gòu)中必須涉及到事務(wù)的處理?,F(xiàn)在在這個(gè)負(fù)載均衡的數(shù)據(jù)庫架構(gòu)中,用戶A要注冊用戶名為xiaoming,這個(gè)寫請求分配給了db server 1;與此同時(shí)用戶B同樣注冊用戶名xiaoming,如果寫請求分配給了db server1,就不會有問題發(fā)生,可是如果分配給db server 2呢?兩個(gè)db server分別存放了不同用戶的用戶名相同的用戶信息!解決的方法很簡單,寫請求的分配不能用隨機(jī)算法,應(yīng)該使用哈希映射,例如注冊的用戶名首字母為x時(shí),寫請求分配各 db server2,其他寫請求一律分配給db server 1。
另外一個(gè)問題,這種架構(gòu)為開發(fā)應(yīng)用提供了很大的靈活性,就是這種架構(gòu)不適用于某些ORM框架,解決方法就是在這個(gè)架構(gòu)上再加上一層——“數(shù)據(jù)庫代理”。例如對于MySQL,就有MySQL Proxy這樣的解決方案。
相關(guān)文章
虛擬主機(jī)應(yīng)該如何解決電信網(wǎng)通間互聯(lián)互通
電信和網(wǎng)通兩大基礎(chǔ)網(wǎng)絡(luò),人為地割裂了整個(gè)中國的網(wǎng)絡(luò)。無論是選擇把網(wǎng)站托管在電信、還是網(wǎng)通,都等于是在拒絕處于另外一個(gè)網(wǎng)絡(luò)中的客戶,因?yàn)閷?shí)在太慢了2011-10-10
VPS主機(jī)快速搬家方法:邊打包邊傳輸邊解壓適合大中型論壇網(wǎng)站
本篇文章給大家分享如何在VPS主機(jī)之間快速搬家,一邊打包壓縮原主機(jī)上的文件,一邊傳輸文件數(shù)據(jù)到新的主機(jī)上,一邊在新的VPS主機(jī)上解壓文件,因?yàn)樗械牟僮鞫际窃赩PS主機(jī)上之間進(jìn)行,傳輸速度可以達(dá)到幾MB/s以上,特別適合一些大中型的論壇和網(wǎng)站搬家2017-07-07
服務(wù)器的硬件配置經(jīng)驗(yàn)分享(如何正確配置服務(wù)器以提高網(wǎng)站性能)
服務(wù)器的配置是互聯(lián)網(wǎng)技術(shù)領(lǐng)域中非常重要的一環(huán),一個(gè)合理配置的服務(wù)器可以提高系統(tǒng)的性能和穩(wěn)定性,保證用戶的訪問體驗(yàn),在本文中,我將介紹服務(wù)器配置的具體步驟和流程2023-08-08
網(wǎng)站下載文件時(shí) 地址加jdfwkey=的說明
因WEB服務(wù)器前置硬防,地址加?jdfwkey=影響收錄的解決辦法2009-12-12
X-Frame-Options頭未設(shè)置 防止網(wǎng)頁被iframe內(nèi)框架調(diào)用
有時(shí)候?yàn)榱朔乐咕W(wǎng)頁被別人的網(wǎng)站iFrame,我們可以通過在服務(wù)器設(shè)置HTTP頭部中的X-Frame-Options信息,需要的朋友可以參考下2017-03-03
ROS參數(shù)服務(wù)器中的理論模型與參數(shù)操作(C++)
在C++中實(shí)現(xiàn)參數(shù)服務(wù)器數(shù)據(jù)的增刪改查,均可以通過兩套API實(shí)現(xiàn)分別是ros::NodeHandle和ros::param,這篇文章主要介紹了ROS參數(shù)服務(wù)器--理論模型與參數(shù)操作(C++),需要的朋友可以參考下2023-08-08
配置Memcache服務(wù)器并實(shí)現(xiàn)主從復(fù)制功能(repcached)
repcached是日本人開發(fā)的實(shí)現(xiàn)memcached復(fù)制功能,它是一個(gè)單 master單 slave的方案,但它的 master/slave都是可讀寫的,而且可以相互同步,如果 master壞掉, slave偵測到連接斷了,它會自動 listen而成為 master2012-03-03

