有一個(gè)計(jì)算機(jī)小白(我們今天的主人公),閑來無聊搭建了一個(gè)化妝品電商網(wǎng)站。他的網(wǎng)站有3個(gè)部分構(gòu)成,一部分是社區(qū)(類似于新浪微博)、另一部分是電商、最后一部分是直播(嗯沒錯(cuò)直播)。萬萬沒有想到這個(gè)網(wǎng)站真是骨骼驚奇,從建立起開始天天流量激增。這可高興壞了小白(已經(jīng)開始盤算上市敲鐘了),高興之余小白發(fā)現(xiàn)原來基于lnmp(linux+nginx+mysql+php Web2.0的經(jīng)典配置)的網(wǎng)站越來越卡,于是勤奮的小白開始他的網(wǎng)站優(yōu)化之路。工作之余,小白寫下了這篇用來記錄一路心路歷程。(本故事純屬虛構(gòu),如有雷同算我抄襲你。我也是不是文中的小白,我倒想是他,但是我的私人網(wǎng)站日dau不過10...)。
1. 搭建LNMP網(wǎng)站
小白打開了阿里云猶豫再三選中了最低的配置。就算是最低的配置(1Mb帶寬, 512MB內(nèi)存 1核CPU, 20GB硬盤)一年也要500多大洋,創(chuàng)業(yè)么不出點(diǎn)血能叫創(chuàng)業(yè)?哦 對了,還是需要從萬網(wǎng)上面挑選了一個(gè)域名吧。經(jīng)過一番配置終于把域名 www.54-250.com解析到了對應(yīng)的服務(wù)器IP了(后面還有漫長的備案手續(xù),暫時(shí)不表啦)。
那么商城系統(tǒng)用什么? 自己開發(fā)?這輩子都不可能自己開發(fā)!
搗鼓一番終于小白終于把PHP-Shop(一個(gè)虛構(gòu)的商城系統(tǒng))安裝到了服務(wù)器上面了。打開chrome輸入域名加載,華麗的商城頁面加載了出來。趕緊進(jìn)到后臺(tái)添加了幾個(gè)商品,就這樣 小白商城就這樣開了起來。沉靜在創(chuàng)業(yè)剛剛開始的興奮勁中,小白已經(jīng)開始思索上市的事情了。
Tips: Nginx的
gzip和sendfile開關(guān)最好是開啟的這樣會(huì)使得性能更高。
gzip和sendfile用來做什么的 gzip很簡單,就是壓縮了HTML和資源的體積,減少了網(wǎng)絡(luò)的傳輸?shù)臄?shù)據(jù)量性能當(dāng)然會(huì)好了。那么sendfile是用來干什么的?這是linux zero-copy的一個(gè)特性,傳統(tǒng)網(wǎng)絡(luò)程序如果要發(fā)送一個(gè)文件(這里指的 css JavaScript這些靜態(tài)資源),需要先把文件內(nèi)容讀取到內(nèi)存中(詳細(xì)過程:從硬盤拷貝到內(nèi)核數(shù)據(jù)空間,再從內(nèi)核數(shù)據(jù)空間拷貝到用戶態(tài)),然后再把數(shù)據(jù)發(fā)送給網(wǎng)絡(luò)的對端(內(nèi)存的數(shù)據(jù)拷貝到內(nèi)核數(shù)據(jù)空間,然后發(fā)送給網(wǎng)卡)。這個(gè)過程中存在多次用戶空間數(shù)據(jù)和內(nèi)核數(shù)據(jù)空間的數(shù)據(jù)拷貝(仔細(xì)想想這個(gè)是不是多余的,畢竟數(shù)據(jù)只是來回拷貝 沒有變化)。linux就是針對這個(gè)情況做了特殊優(yōu)化,nginx的sendfile就是利用了這個(gè)特性。
2. CDN
小白商城 運(yùn)營有一段時(shí)間了,日活躍用戶也越來越多,大部分都是從搜索引擎過來的。隨著活躍用戶越來越多小白發(fā)現(xiàn)網(wǎng)站打開越來越慢,從原來只要3秒現(xiàn)在需要20多秒了。 阿里云也發(fā)來數(shù)條告警短信:云服務(wù)器的IO已經(jīng)到峰值。小白隨手打開了chrome的inspect并刷新了頁面,很快發(fā)現(xiàn)原來網(wǎng)站的圖片太多了。圖片加載占據(jù)了90%的時(shí)間,而且加載速度還慢。
“是時(shí)候上CDN了!” 小白暗道。
CDN的全稱是Content Delivery Network, 內(nèi)容分發(fā)網(wǎng)絡(luò)主要用來通過中心平臺(tái)的負(fù)載均衡、內(nèi)容分發(fā)、調(diào)度等功能模塊,使用戶就近獲取所需內(nèi)容,降低網(wǎng)絡(luò)擁塞,提高用戶訪問響應(yīng)速度和命中率(這是百度百科里面的話)。用大白話說就是瀏覽器對于網(wǎng)站上面的靜態(tài)資源(圖片、CSS、JS)的訪問可以通過DNS的CNAME記錄,把原來訪問資源的url映射到CDN的域名上面去。然后瀏覽器會(huì)去最近的CDN服務(wù)器(區(qū)域上面挨著近的)獲取數(shù)據(jù)(如果沒有數(shù)據(jù),CDN會(huì)向他的上級(jí)獲取數(shù)據(jù),如果上級(jí)還沒有數(shù)據(jù)就會(huì)向源內(nèi)容獲取數(shù)據(jù),俗稱“回源”)。CDN會(huì)在一定時(shí)間里面Cache這個(gè)數(shù)據(jù),當(dāng)?shù)诙卧L問的時(shí)候就可以直接從Cache返回了,速度就上來了。

通過設(shè)置了子域名
img.54-250.com 和 res.54-250.com 2個(gè)域名的CNAME記錄并把所有的image css javascript的url遷移到這2個(gè)子域名下。刷新下頁面網(wǎng)站加載速度又快了起來,小白露出邪惡的微笑。
3. 數(shù)據(jù)庫主從
小白商城自從上次上了CDN后沒多久后用戶又激增了,日DAU到3w了(全是錢啊)。但是頁面又開始卡頓了,小白第一時(shí)間查詢了CDN的系統(tǒng),發(fā)現(xiàn)問題并不是出現(xiàn)在CDN上面。手動(dòng)點(diǎn)擊刷新瀏覽器上面的刷新按鈕后有幾次竟然出現(xiàn)了Mysql Connection Error。小白這下明白, 這是數(shù)據(jù)庫到了訪問的上限了。為了緩解問題首先先去阿里云上面提升了配置(4Mb帶寬, 4GB內(nèi)存,500G SSD硬盤),升級(jí)后訪問速度又再次快了起來。但是小白擔(dān)憂了起來,萬一數(shù)據(jù)庫損壞不能恢復(fù)了那我的心血不就付諸東流了。越想越擔(dān)心還是把數(shù)據(jù)單獨(dú)抽離出來做個(gè)主從熱備份吧。
Mysql主從:mysql集群特性,通過簡單的mysql的配置就可以讓多臺(tái)mysql數(shù)據(jù)庫服務(wù)器組合 master-slave架構(gòu)。在master-slave架構(gòu)下,只能對master服務(wù)器進(jìn)行寫操作。master數(shù)據(jù)庫服務(wù)器會(huì)把數(shù)據(jù)變動(dòng)寫入binlog中,并發(fā)送給slave機(jī)器(slave機(jī)器還可以有自己的slave機(jī)器)同步數(shù)據(jù)(事實(shí)上從分布式架構(gòu)上面來說這種設(shè)計(jì)不能保證數(shù)據(jù)絕對的一致性)。但是master和slave可以同時(shí)抗讀(可能有人會(huì)覺得,如果slave當(dāng)下數(shù)據(jù)有可能和master不完全一樣咋辦?是存在這個(gè)問題,要適當(dāng)規(guī)避)。
Myqsl主主:mysql集群的另一種搭建方式,多臺(tái)服務(wù)器都是master機(jī)器,互相同步binlog。在這種情況下所有的機(jī)器都可以寫入,但是要做寫入隔離(試想一下,A、B兩臺(tái)服務(wù)器互為 master-master架構(gòu)。同時(shí) 給A服務(wù)器 set id = 1, 給B服務(wù)器 set id = 2,稍后A把id = 1的信息發(fā)送給了B, B把id = 2的信息發(fā)送給了A。那么問題就來了到底id是多少?如圖所示)所以對于同一個(gè)數(shù)據(jù)的設(shè)置必須hash到其中一臺(tái)機(jī)器,保證數(shù)據(jù)寫入的有序性。所有的服務(wù)器都是用來抗讀,問題和主從架構(gòu)下類似。

小白經(jīng)過一番思索后決定使用,多主多從的架構(gòu):

通過搭建雙主服務(wù)器,master后有拖著2個(gè)slave服務(wù)器。通過對
PHP-Shop的數(shù)據(jù)庫的操作邏輯加以了修改后,對寫操作做了Hash操作(寫隔離),對讀取可以隨機(jī)訪問了任何一臺(tái)服務(wù)器, 把原來服務(wù)器的數(shù)據(jù)同步過來后這套架構(gòu)就正式上線了。經(jīng)過這樣一輪大刀闊斧的修改后,網(wǎng)站的速度又快了起來。再也沒有出現(xiàn)過Mysql Connection Error了。
5. 局域網(wǎng)隔離
這段時(shí)間小白商城一直快速發(fā)展著(連小白都覺得某明奇妙)已經(jīng)快到日dau 5w了。這天小白突然收到服務(wù)器流量反常激增的短信。跑到阿里云后臺(tái)一瞧,發(fā)現(xiàn)居然是一臺(tái)數(shù)據(jù)庫服務(wù)器收到大量的莫名其妙的IP發(fā)來的數(shù)據(jù)包。小白立刻明白了這是被DDOS攻擊了(互聯(lián)網(wǎng)最沒有技術(shù)含量的攻擊,分CC和SYNC 2種,都是通過發(fā)送大量數(shù)據(jù)包來消耗服務(wù)器資源或者帶寬資源)。還好數(shù)據(jù)庫的服務(wù)器之前在配置的時(shí)候設(shè)置了iptable白名單,但是這臺(tái)服務(wù)器的帶寬還是被吃滿了。幸好這次的攻擊事件沒有帶來什么本質(zhì)的損失,但是小白還是心有余悸。于是開始對后臺(tái)架構(gòu)開始了新一輪的改造計(jì)劃。
實(shí)施如下:

通過組件局域網(wǎng),對外網(wǎng)的接入是一個(gè)網(wǎng)關(guān)。網(wǎng)關(guān)把數(shù)據(jù)接入到局域網(wǎng)里面,傳遞給了邏輯服務(wù)器,邏輯服務(wù)器和數(shù)據(jù)庫集群都運(yùn)行在局域網(wǎng)內(nèi)。
網(wǎng)關(guān):也是一臺(tái)服務(wù)器,只是這臺(tái)服務(wù)器比較特殊,它有2個(gè)網(wǎng)卡。其中一個(gè)網(wǎng)卡是外網(wǎng)網(wǎng)卡,接受公網(wǎng)的數(shù)據(jù)請求。另一個(gè)是內(nèi)網(wǎng)網(wǎng)卡,它接入了內(nèi)網(wǎng)的交換機(jī)可以和內(nèi)網(wǎng)的服務(wù)器進(jìn)行數(shù)據(jù)通訊。
局域網(wǎng)防火墻:局域網(wǎng)的交換機(jī)都是帶有防火墻。所謂防火的策略總結(jié)成一句話,如果防火墻沒有之前沒有和外網(wǎng)的地址通訊過,那么當(dāng)這個(gè)地址發(fā)送來數(shù)據(jù),防火墻就會(huì)丟掉(話說就算不丟掉,按照路由器和交換機(jī)的路由策略也不知道發(fā)給誰...)。有了防火墻等于有了一個(gè)隔離,使得內(nèi)網(wǎng)的數(shù)據(jù)必須走網(wǎng)關(guān)才能和公網(wǎng)通訊。這樣內(nèi)網(wǎng)的服務(wù)器就算有漏洞(數(shù)據(jù)庫弱口令等等)也不會(huì)輕易被外網(wǎng)黑客利用。對外只暴露了網(wǎng)關(guān),網(wǎng)關(guān)上面基本上只部署數(shù)據(jù)中轉(zhuǎn)服務(wù),并不部署數(shù)據(jù)庫之類的軟件。所以也保障了數(shù)據(jù)在內(nèi)網(wǎng)的安全性(由于防火墻的這個(gè)特性,所以在做p2p直連的時(shí)候需要做防火墻滲透,暫時(shí)不表)。
小白購買了阿里云的VPC(阿里云虛擬私有網(wǎng)絡(luò),類似于局域網(wǎng)),折騰了數(shù)天。那么在網(wǎng)關(guān)服務(wù)器上面到底應(yīng)該部署什么軟件比較好?
【not end】接下文 一步一步構(gòu)建高性能Web服務(wù)網(wǎng)站(2)
版權(quán)所有,如有轉(zhuǎn)載請聯(lián)系我本人http://www.breakerror.com/?p=218