狗子是某大學(xué)計(jì)算機(jī)專業(yè)本科應(yīng)屆畢業(yè)生,由于自己的技術(shù)不錯(cuò),再加上互聯(lián)網(wǎng)產(chǎn)業(yè)的巨大利潤(rùn)的驅(qū)使,狗子決定走上創(chuàng)業(yè)這條路,于是,狗子聯(lián)合了同學(xué)二黑,雞子,狗蛋等人花費(fèi)了幾個(gè)月的時(shí)間寫出了一套網(wǎng)站,是關(guān)于足球資訊的pc端網(wǎng)站加上手機(jī)APP客戶端?,F(xiàn)在產(chǎn)品測(cè)試成功了,準(zhǔn)備發(fā)布了,狗子想到了兩個(gè)問(wèn)題:
1.網(wǎng)站需要服務(wù)器
狗子之前所有的代碼測(cè)試都是在本地服務(wù)器或者局域網(wǎng)上進(jìn)行的,現(xiàn)在需要把產(chǎn)品發(fā)布到外網(wǎng)上,讓所有的人都能訪問(wèn),因此再用自己的電腦當(dāng)服務(wù)器顯然很不現(xiàn)實(shí),于是,狗子去買了一臺(tái)服務(wù)器,在上面裝了jdk,tomcat,mysql等必備環(huán)境,把網(wǎng)站搭了起來(lái),又經(jīng)過(guò)了很多測(cè)試,運(yùn)行毫無(wú)問(wèn)題了,通過(guò)網(wǎng)站的ip可以訪問(wèn)并且實(shí)現(xiàn)功能了,而且app的后臺(tái)也在服務(wù)器上測(cè)試成功了,目前公司的架構(gòu)如圖所示:
那么問(wèn)題又來(lái)了:
2.網(wǎng)站需要的域名
顯然,如果讓各地的用戶需要記住你服務(wù)器的ip地址才能訪問(wèn)你的網(wǎng)站的話,那是會(huì)被用戶拿刀追著砍的。因此,狗子需要一個(gè)便于記住的域名,以后在瀏覽器輸入這個(gè)域名就能夠訪問(wèn)這個(gè)網(wǎng)站,所以,狗子拿著申請(qǐng)下來(lái)的各種資質(zhì),找到了域名販賣商,一般是騰訊阿里巴巴這種代理販賣商,花了一筆錢,從它們的手上購(gòu)買了域名,徹底實(shí)現(xiàn)了網(wǎng)站通過(guò)域名就能訪問(wèn)的功能。這里需要講解一下通過(guò)域名訪問(wèn)的原理:
域名訪問(wèn)原理
通過(guò)ip訪問(wèn)相當(dāng)于用戶直接訪問(wèn)輸入的ip所指向的服務(wù)器,而通過(guò)域名訪問(wèn),是用戶輸入域名之后,請(qǐng)求先被發(fā)送到域名管理者所控制的DNS服務(wù)器中,DNS服務(wù)器中有一個(gè)數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)中存有這個(gè)域名所對(duì)相應(yīng)的ip地址,DNS服務(wù)器當(dāng)了一個(gè)中間人,將請(qǐng)求轉(zhuǎn)發(fā)到這個(gè)ip地址對(duì)應(yīng)的服務(wù)器,就實(shí)現(xiàn)了通過(guò)域名訪問(wèn),因此,通過(guò)域名訪問(wèn)本質(zhì)上還是通過(guò)ip訪問(wèn)。那么,狗子公司的架構(gòu)圖就應(yīng)該是下面這樣:
解決了這兩個(gè)問(wèn)題,狗子的產(chǎn)品順利的發(fā)布了,經(jīng)過(guò)一兩個(gè)月的運(yùn)營(yíng),慢慢地發(fā)掘了一小批用戶,實(shí)現(xiàn)了小幅盈利,狗子開(kāi)始沾沾自喜了,原來(lái),掙錢就這么容易啊。然而很快,現(xiàn)實(shí)給了初出茅廬的狗子當(dāng)頭一棒:一個(gè)連黑客都算不上的惡意用戶,通過(guò)自己寫的一個(gè)小小的程序,居然把狗子的服務(wù)器搞崩了,這是怎么一回事呢?
服務(wù)器防火墻的概念
讀者可能也了解一些,用戶通過(guò)網(wǎng)站向服務(wù)器發(fā)送請(qǐng)求,服務(wù)器處理請(qǐng)求再對(duì)用戶進(jìn)行響應(yīng)對(duì)服務(wù)器的內(nèi)存是有開(kāi)銷的,但是,讀者可能不清楚的是,這種開(kāi)銷有多么大。每當(dāng)一個(gè)用戶向服務(wù)器發(fā)送請(qǐng)求,服務(wù)器都要啟動(dòng)一個(gè)線程去處理這個(gè)請(qǐng)求并且響應(yīng)給用戶。這之中耗費(fèi)的服務(wù)器內(nèi)存差不多是1mb以上級(jí)別的,更別說(shuō)是再加上其中的服務(wù)器處理數(shù)據(jù)進(jìn)行的各種操作了。也就是說(shuō),用戶發(fā)送一個(gè)東西,服務(wù)器會(huì)損失1mb以上的內(nèi)存,多發(fā)幾個(gè),服務(wù)器就該受不了了。
攻擊狗子服務(wù)器的人就是寫了一個(gè)簡(jiǎn)簡(jiǎn)單單的小程序,重復(fù)多次地向服務(wù)器發(fā)送請(qǐng)求,服務(wù)器在短時(shí)間之內(nèi)沒(méi)有這么多內(nèi)存去處理這么多請(qǐng)求,自然就宕機(jī)了,就崩了。
搞懂了這些,狗子自然就想出了應(yīng)對(duì)策略,于是,他給自己的服務(wù)器開(kāi)啟了防火墻,通過(guò)配置防火墻,實(shí)現(xiàn)了禁止同一個(gè)用戶在短時(shí)間內(nèi)重復(fù)多次頻繁發(fā)送請(qǐng)求,他的服務(wù)器也可以安心地工作了。
當(dāng)然,有的讀者可能會(huì)問(wèn)了,那么,防火墻禁止了單一用戶短時(shí)間內(nèi)多次重復(fù)發(fā)送請(qǐng)求,那么如果我是一個(gè)黑客,通過(guò)種木馬等黑客手段控制了數(shù)以千計(jì)甚至更多的其他用戶的電腦,讓這些不同的電腦去短時(shí)間內(nèi)攻擊服務(wù)器,可不可以攻擊成功呢?答案是確實(shí)可以,這些被控制的電腦就是DDOS攻擊中的肉雞,這里有些跑題了,在本文不再贅述。注意,配置這種攔截單一ip防火墻只是基本操作,甚至買來(lái)的服務(wù)器會(huì)自帶。之所以狗子的服務(wù)器沒(méi)有是因?yàn)橹挥兴銐虻摹俺醭雒]”,才能給讀者解釋清楚:)。
那么,我們現(xiàn)在的架構(gòu)圖就應(yīng)該是這樣:
狗子的公司越辦越大,越來(lái)越多的用戶開(kāi)始使用他的軟件看各種足球咨詢,而且,用于用戶的基數(shù)變大了,每天增長(zhǎng)的用戶數(shù)量都在變多,以前可能是每天有十個(gè)新用戶,那么現(xiàn)在就是每天有了一百個(gè)新用戶。在一個(gè)晚上的服務(wù)器宕機(jī)事故出現(xiàn)之后,狗子終于意識(shí)到,自己的單臺(tái)服務(wù)器應(yīng)對(duì)日益龐大的用戶群已經(jīng)開(kāi)始體力不支了。于是,他用了之前積攢下來(lái)的收益,又購(gòu)入了三臺(tái)服務(wù)器,并且用其中一臺(tái)服務(wù)器單獨(dú)運(yùn)行數(shù)據(jù)庫(kù),作為數(shù)據(jù)庫(kù)服務(wù)器。
那么現(xiàn)在問(wèn)題來(lái)了,這四臺(tái)服務(wù)器怎么一起使用,同時(shí)服務(wù)于一個(gè)網(wǎng)站的運(yùn)營(yíng)呢?
解決方案有兩個(gè):
1.三個(gè)服務(wù)器同時(shí)運(yùn)行相同的代碼,在代碼頁(yè)設(shè)置三個(gè)用戶入口,如果用戶進(jìn)入一個(gè)入口發(fā)現(xiàn)進(jìn)不去,就選擇另一個(gè)入口,每個(gè)入口對(duì)應(yīng)一臺(tái)服務(wù)器
這樣做的好處是簡(jiǎn)單方便,直接把代碼往另外兩個(gè)服務(wù)器一拷貝 然后更改一些其中的設(shè)置,再設(shè)置三個(gè)入口就行了。但是缺點(diǎn)也是很明顯的,顯然用戶的第一反應(yīng)都是點(diǎn)擊第一個(gè)入口,只有當(dāng)?shù)谝粋€(gè)入口進(jìn)不去的時(shí)候才會(huì)選擇另外兩個(gè)服務(wù)器,而且等到以后用戶數(shù)量越來(lái)越大,難道我們要設(shè)置幾十幾百個(gè)入口讓用戶一個(gè)一個(gè)去試嗎?這顯然又是一個(gè)被用戶追著拿刀砍的行為。(當(dāng)程序員可以體驗(yàn)死亡如風(fēng),常伴吾身的感覺(jué))所以,這個(gè)方法顯然不太現(xiàn)實(shí),不過(guò)這個(gè)方法也是有它的應(yīng)用場(chǎng)景的,比如說(shuō)在一些學(xué)校的官網(wǎng)的在校生入口,由于在校生是畢業(yè)一批又新來(lái)一批,所以用戶體量不會(huì)有太大的增長(zhǎng),因此才可以使用這個(gè)方法。這種方法的架構(gòu)圖是這樣的:
2.負(fù)載均衡
狗子咨詢了一些在中大型互聯(lián)網(wǎng)公司的學(xué)長(zhǎng),終于找到了一種解決這個(gè)問(wèn)題還不像第一種方法那樣容易有生命危險(xiǎn)的辦法,那就是nginx。
nginx是個(gè)什么東西呢?是用來(lái)做服務(wù)器負(fù)載均衡的,說(shuō)白了就是當(dāng)用戶發(fā)送請(qǐng)求的時(shí)候,先經(jīng)過(guò)nginx這個(gè)中間人,nginx會(huì)去感受哪個(gè)服務(wù)器比較閑,就會(huì)把請(qǐng)求發(fā)送到這個(gè)比較閑的服務(wù)器上去,這樣運(yùn)行多了,就可以做到每個(gè)服務(wù)器相對(duì)的負(fù)擔(dān)比較平衡,這就是負(fù)載均衡。nginx可以放在服務(wù)器本機(jī),也可以放在單獨(dú)的一個(gè)服務(wù)器中,nginx這個(gè)中間人會(huì)向各個(gè)服務(wù)器分發(fā)請(qǐng)求,并且nginx的性能十分高超,每秒百萬(wàn)級(jí)以下數(shù)量的請(qǐng)求都可以處理。你可能要問(wèn)了,如果狗子把nginx單獨(dú)放在一個(gè)服務(wù)器上,那么他的三臺(tái)服務(wù)器怎么對(duì)應(yīng)到同一個(gè)域名上呢?他是否需要給每個(gè)nginx分發(fā)的服務(wù)器也就是那三臺(tái)購(gòu)買三個(gè)域名呢?當(dāng)然不用,事實(shí)上,現(xiàn)在我們對(duì)外的公共ip已經(jīng)變成了安裝nginx的服務(wù)器的ip了,也就是說(shuō),我們只要把域名映射到這個(gè)nginx服務(wù)器就可以了,然后nginx中會(huì)有配置,我們只要在配置中寫下三個(gè)服務(wù)器的ip,nginx以后就能把請(qǐng)求分發(fā)過(guò)去了。那么,我們現(xiàn)在的架構(gòu)圖就變成了下圖這樣:
狗子還想對(duì)服務(wù)器做做優(yōu)化,像是session這種東西,只是簡(jiǎn)簡(jiǎn)單單的一個(gè)session請(qǐng)求,卻要耗費(fèi)服務(wù)器那么多的性能,有沒(méi)有一種方法,能夠?qū)@方面做一些改進(jìn)呢?
當(dāng)然有,解決方案就是redis。
redis的作用
redis是一種數(shù)據(jù)庫(kù),我們比較熟知的數(shù)據(jù)庫(kù)有mysql,sqlServer,oracle等,那么這個(gè)redis又是個(gè)什么玩意?
redis和上述幾種數(shù)據(jù)庫(kù)不同,它是緩存數(shù)據(jù)庫(kù),也就是說(shuō),redis是致力于短時(shí)存儲(chǔ)的,redis并不是從硬盤中拿取和處理數(shù)據(jù),它對(duì)數(shù)據(jù)的處理都是在內(nèi)存中,由于內(nèi)存的數(shù)據(jù)處理速度不知道比磁盤高到哪里去了,所以redis的性能也是碾壓mysql,sqlServer,oracle這種數(shù)據(jù)庫(kù)的,這無(wú)關(guān)于軟件優(yōu)劣,純粹是因?yàn)橛布用娴囊蛩?。不過(guò)redis因?yàn)槭窃趦?nèi)存中,因此只要機(jī)器一關(guān)閉,內(nèi)存中redis存儲(chǔ)的東西就會(huì)消失了,不過(guò)redis也可以將數(shù)據(jù)持久化存儲(chǔ)到mysql這些數(shù)據(jù)庫(kù)中,但是一涉及到對(duì)硬盤的操作,redis的性能就下來(lái)了。因此,我們的redis常常是用來(lái)存儲(chǔ)像是用戶的登錄狀態(tài)這種短時(shí)需要的數(shù)據(jù),而去把用戶登錄注冊(cè)的時(shí)間備份到硬盤上的數(shù)據(jù)庫(kù)。那么,我們現(xiàn)在的架構(gòu)圖就變成了如下這樣:
又過(guò)了一段時(shí)間,隨著用戶體量越來(lái)越大,數(shù)量級(jí)達(dá)到了上萬(wàn)上十萬(wàn)的時(shí)候,狗子發(fā)現(xiàn)一直以來(lái),自己都忽略了一個(gè)問(wèn)題,盡管自己增加了服務(wù)器,加了負(fù)載均衡,還啟用了redis緩存數(shù)據(jù)庫(kù),為了使用戶訪問(wèn)的速度增加還有讓服務(wù)器的負(fù)載不那么大,但是,網(wǎng)站處理數(shù)據(jù)的方式本質(zhì)上是對(duì)數(shù)據(jù)庫(kù)進(jìn)行增刪改查,而現(xiàn)在我們的數(shù)據(jù)庫(kù)服務(wù)器只有一臺(tái),數(shù)據(jù)庫(kù)處理數(shù)據(jù)本身就是一項(xiàng)復(fù)雜耗費(fèi)內(nèi)存的工作,現(xiàn)在的一臺(tái)數(shù)據(jù)庫(kù)服務(wù)器更是杯水車薪,因此,在中小型公司的網(wǎng)站架構(gòu)中,最先撐不住的往往是數(shù)據(jù)庫(kù)服務(wù)器。
當(dāng)然,狗子又有了解決辦法。他又購(gòu)入了兩臺(tái)服務(wù)器當(dāng)作數(shù)據(jù)庫(kù)服務(wù)器,然后把數(shù)據(jù)庫(kù)進(jìn)行了分庫(kù)分表的操作,分別把數(shù)據(jù)存在三臺(tái)數(shù)據(jù)庫(kù)服務(wù)器上。當(dāng)然狗子覺(jué)得這還不夠,因此,他又使用了一種技術(shù),將數(shù)據(jù)庫(kù)進(jìn)行了讀寫分離。
讀寫分離理解起來(lái)很簡(jiǎn)單,和它的字面意思一樣,就是把從數(shù)據(jù)庫(kù)中寫入數(shù)據(jù)和從數(shù)據(jù)庫(kù)中拿取數(shù)據(jù)進(jìn)行分離,以此來(lái)達(dá)到減少數(shù)據(jù)庫(kù)服務(wù)器負(fù)擔(dān)的作用。用來(lái)讀取數(shù)據(jù)的服務(wù)器和用來(lái)寫入數(shù)據(jù)的服務(wù)器會(huì)在用戶進(jìn)行操作之后延遲一段時(shí)間進(jìn)行數(shù)據(jù)同步,一般來(lái)說(shuō)延遲時(shí)間不會(huì)太長(zhǎng),很可能用戶都不會(huì)覺(jué)察到。那么,我們現(xiàn)在的架構(gòu)圖就變成了下圖這樣:
可以看到,我們的圖上新出現(xiàn)了“集群”這個(gè)詞,不錯(cuò),互聯(lián)網(wǎng)經(jīng)常提及的xxx集群終于在我們眼前解開(kāi)了神秘面紗,也就是多臺(tái)服務(wù)器同時(shí)協(xié)同處理事務(wù),就可以稱作一個(gè)服務(wù)器集群。
時(shí)光飛逝,轉(zhuǎn)眼間五年的時(shí)間過(guò)去了,狗子已經(jīng)從一個(gè)中小型互聯(lián)網(wǎng)公司的小老板搖身一變成了一個(gè)上市公司總裁,和馬云馬化騰等it行業(yè)巨佬互動(dòng)成了他的日常,他的一句話可以動(dòng)搖it界,他的網(wǎng)站也擁有了上億的用戶。。。。。
到了這種程度,狗子的公司網(wǎng)絡(luò)架構(gòu)已經(jīng)變成了下圖這樣:
(內(nèi)容比較多,看不清記得放大哦)
能支持上億人訪問(wèn)的服務(wù)器肯定不止這么幾個(gè),只是象征性地畫了幾個(gè)。同時(shí),我們把redis服務(wù)器與mysql服務(wù)器進(jìn)行了連線,是因?yàn)槲覀兦懊嬲f(shuō)過(guò)redis可以將數(shù)據(jù)存入持久性數(shù)據(jù)庫(kù),這里我們可以用來(lái)記錄登錄時(shí)間之類的信息。同時(shí),圖中的mysql服務(wù)器是重疊在一起的,不要以為僅僅只有兩臺(tái)服務(wù)器。
隨著公司變?yōu)榫揞^,狗子的經(jīng)驗(yàn)不斷累積,他發(fā)現(xiàn)自己的公司雖然體量很大,開(kāi)發(fā)的產(chǎn)品越來(lái)越多,功能越來(lái)越全面,但是總是有那么一部分的功能是重復(fù)的。假如在一個(gè)新的頁(yè)面或者產(chǎn)品中,剛開(kāi)始開(kāi)發(fā)時(shí)有那么10%是和以前開(kāi)發(fā)過(guò)的頁(yè)面或者產(chǎn)品的功能是重復(fù)的,那么,等到這個(gè)新東西的功能開(kāi)發(fā)接近完善的時(shí)候,就可能會(huì)有70%的功能和從前開(kāi)發(fā)的一樣。仔細(xì)想想這是一件很可怕的事情,狗子居然畫了70%的開(kāi)發(fā)時(shí)間和開(kāi)發(fā)成本在做以前早就做過(guò)的事情。
這狗子就不能忍了,于是他想到了一個(gè)好辦法,既然面向?qū)ο缶幊陶Z(yǔ)言中有封裝的這種概念,把代碼的重復(fù)部分封裝起來(lái)便于重復(fù)使用,那么產(chǎn)品和產(chǎn)品之間為何不能封裝相同的東西便于使用呢?
于是,他開(kāi)始實(shí)現(xiàn)微服務(wù)的概念,解釋起來(lái)可能一上來(lái)比較難于接受,我們先來(lái)看,剛剛我們的架構(gòu)圖中的產(chǎn)品實(shí)際上可以看成一整個(gè)系統(tǒng),假設(shè)這個(gè)系統(tǒng)叫做系統(tǒng)A。那么,我們現(xiàn)在開(kāi)發(fā)出來(lái)了其它的各種產(chǎn)品或者各種頁(yè)面,也可以看作是新的系統(tǒng)B和系統(tǒng)C?,F(xiàn)在,系統(tǒng)ABC之間有很多重復(fù)的部分,于是,我們想到了將這些重復(fù)的部分放到一起,供三個(gè)系統(tǒng)同時(shí)調(diào)用。那么實(shí)際上,這個(gè)重復(fù)的部分就是被封裝起來(lái)的微服務(wù),微服務(wù)是一種模塊化開(kāi)發(fā),把產(chǎn)品的功能提煉成多個(gè)模塊,在開(kāi)發(fā)時(shí)把模塊拼接起來(lái),就可以省去大量的工作。為了實(shí)現(xiàn)一個(gè)模塊,模塊中也需要帶有服務(wù)器集群等東西。聽(tīng)了這些,我們下面的架構(gòu)圖看起來(lái)應(yīng)該沒(méi)有那么難懂了:
這些與技術(shù)無(wú)關(guān),而是一種開(kāi)發(fā)理念,一種思想,有了這種思想,才能在成千上萬(wàn)的用戶需求之間找到共通,提升開(kāi)發(fā)效率,節(jié)省成本。
狗子有了這種思想,并實(shí)現(xiàn)了他,終于打敗了所有競(jìng)爭(zhēng)對(duì)手,迎娶白富美,走上了人生巔峰。
。
。
。
。
。
。
。
。
后來(lái),他夢(mèng)醒了。。。
對(duì)于很多初級(jí)Java工程師而言,想要提升技能,往往是自己摸索成長(zhǎng),不成體系的學(xué)習(xí)效果低效漫長(zhǎng)且無(wú)助。
下文整理的這些架構(gòu)技術(shù)希望對(duì)Java開(kāi)發(fā)的朋友們有所參考以及少走彎路,本文的重點(diǎn)是你有沒(méi)有收獲與成長(zhǎng),其余的都不重要,希望讀者們能謹(jǐn)記這一點(diǎn)。同時(shí)我經(jīng)過(guò)多年的收藏目前也算收集到了一套完整的學(xué)習(xí)資料,希望對(duì)想成為架構(gòu)師的朋友有一定的參考和幫助。
下面是資料部分截圖,誠(chéng)意滿滿:特別適合有3-5年開(kāi)發(fā)經(jīng)驗(yàn)的Java程序員們學(xué)習(xí)。
領(lǐng)取方式:轉(zhuǎn)發(fā)文章,一定記得轉(zhuǎn)發(fā)文章,然后加入合作Java架構(gòu)交流Qqun:908676731,管理員處免費(fèi)領(lǐng)取所有資料。
而針對(duì)以上面試技術(shù)點(diǎn),我在這里也做一些技術(shù)知識(shí)面試專題資料分享,希望能更好的幫助到大家。
領(lǐng)取方式:轉(zhuǎn)發(fā)文章,一定記得轉(zhuǎn)發(fā)文章,然后加入合作Java進(jìn)階之路Qqun:908676731,管理員處免費(fèi)領(lǐng)取所有資料。
聯(lián)系客服