1. 程式人生 > >網際網路公司分散式叢集架構圖入門解析(簡單通俗易懂,超詳細)

網際網路公司分散式叢集架構圖入門解析(簡單通俗易懂,超詳細)

一、小型公司網路架構

狗子是某大學計算機專業本科應屆畢業生,由於自己的技術不錯,再加上網際網路產業的巨大利潤的驅使,狗子決定走上創業這條路,於是,狗子聯合了同學二黑,雞子,狗蛋等人花費了幾個月的時間寫出了一套網站,是關於足球資訊的pc端網站加上手機APP客戶端。現在產品測試成功了,準備釋出了,狗子想到了兩個問題:

1.網站需要伺服器

狗子之前所有的程式碼測試都是在本地伺服器或者區域網上進行的,現在需要把產品釋出到外網上,讓所有的人都能訪問,因此再用自己的電腦當伺服器顯然很不現實,於是,狗子去買了一臺伺服器,在上面裝了jdk,tomcat,mysql等必備環境,把網站搭了起來,又經過了很多測試,執行毫無問題了,通過網站的ip可以訪問並且實現功能了,而且app的後臺也在伺服器上測試成功了,目前公司的架構如圖所示:
在這裡插入圖片描述


那麼問題又來了:

2.網站需要域名

顯然,如果讓各地的使用者需要記住你伺服器的ip地址才能訪問你的網站的話,那是會被使用者拿刀追著砍的。因此,狗子需要一個便於記住的域名,以後在瀏覽器輸入這個域名就能夠訪問這個網站,所以,狗子拿著申請下來的各種資質,找到了域名販賣商,一般是騰訊阿里巴巴這種代理販賣商,花了一筆錢,從它們的手上購買了域名,徹底實現了網站通過域名就能訪問的功能。這裡需要講解一下通過域名訪問的原理:

域名訪問原理

通過ip訪問相當於使用者直接訪問輸入的ip所指向的伺服器,而通過域名訪問,是使用者輸入域名之後,請求先被髮送到域名管理者所控制的DNS伺服器中,DNS伺服器中有一個數據庫,資料庫中存有這個域名所對相應的ip地址,DNS伺服器當了一箇中間人,將請求轉發到這個ip地址對應的伺服器,就實現了通過域名訪問,因此,通過域名訪問本質上還是通過ip訪問。那麼,狗子公司的架構圖就應該是下面這樣:
在這裡插入圖片描述

解決了這兩個問題,狗子的產品順利的釋出了,經過一兩個月的運營,慢慢地發掘了一小批使用者,實現了小幅盈利,狗子開始沾沾自喜了,原來,掙錢就這麼容易啊。然而很快,現實給了初出茅廬的狗子當頭一棒:一個連黑客都算不上的惡意使用者,通過自己寫的一個小小的程式,居然把狗子的伺服器搞崩了,這是怎麼一回事呢?

伺服器防火牆概念

讀者可能也瞭解一些,使用者通過網站向伺服器傳送請求,伺服器處理請求再對使用者進行響應對伺服器的記憶體是有開銷的,但是,讀者可能不清楚的是,這種開銷有多麼大。每當一個使用者向伺服器傳送請求,伺服器都要啟動一個執行緒去處理這個請求並且響應給使用者。這之中耗費的伺服器記憶體差不多是1mb以上級別的,更別說是再加上其中的伺服器處理資料進行的各種操作了。也就是說,使用者傳送一個東西,伺服器會損失1mb以上的記憶體,多發幾個,伺服器就該受不了了。

攻擊狗子伺服器的人就是寫了一個簡簡單單的小程式,重複多次地向伺服器傳送請求,伺服器在短時間之內沒有這麼多記憶體去處理這麼多請求,自然就宕機了,就崩了。

搞懂了這些,狗子自然就想出了應對策略,於是,他給自己的伺服器開啟了防火牆,通過配置防火牆,實現了禁止同一個使用者在短時間內重複多次頻繁傳送請求,他的伺服器也可以安心地工作了。

當然,有的讀者可能會問了,那麼,防火牆禁止了單一使用者短時間內多次重複傳送請求,那麼如果我是一個黑客,通過種木馬等黑客手段控制了數以千計甚至更多的其他使用者的電腦,讓這些不同的電腦去短時間內攻擊伺服器,可不可以攻擊成功呢?答案是確實可以,這些被控制的電腦就是DDOS攻擊中的肉雞,這裡有些跑題了,在本文不再贅述。注意,配置這種攔截單一ip防火牆只是基本操作,甚至買來的伺服器會自帶。之所以狗子的伺服器沒有是因為只有他足夠的“初出茅廬”,才能給讀者解釋清楚:)。

那麼,我們現在的架構圖就應該是這樣:
在這裡插入圖片描述

二、中型公司網路架構

狗子的公司越辦越大,越來越多的使用者開始使用他的軟體看各種足球諮詢,而且,用於使用者的基數變大了,每天增長的使用者數量都在變多,以前可能是每天有十個新使用者,那麼現在就是每天有了一百個新使用者。在一個晚上的伺服器宕機事故出現之後,狗子終於意識到,自己的單臺伺服器應對日益龐大的使用者群已經開始體力不支了。於是,他用了之前積攢下來的收益,又購入了三臺伺服器,並且用其中一臺伺服器單獨執行資料庫,作為資料庫伺服器。

那麼現在問題來了,這四臺伺服器怎麼一起使用,同時服務於一個網站的運營呢?

解決方案有兩個:

1.三個伺服器同時執行相同的程式碼,在內碼表設定三個使用者入口,如果使用者進入一個入口發現進不去,就選擇另一個入口,每個入口對應一臺伺服器

這樣做的好處是簡單方便,直接把程式碼往另外兩個伺服器一拷貝 然後更改一些其中的設定,再設定三個入口就行了。但是缺點也是很明顯的,顯然使用者的第一反應都是點選第一個入口,只有當第一個入口進不去的時候才會選擇另外兩個伺服器,而且等到以後使用者數量越來越大,難道我們要設定幾十幾百個入口讓使用者一個一個去試嗎?這顯然又是一個被使用者追著拿刀砍的行為。(當程式設計師可以體驗死亡如風,常伴吾身的感覺)所以,這個方法顯然不太現實,不過這個方法也是有它的應用場景的,比如說在一些學校的官網的在校生入口,由於在校生是畢業一批又新來一批,所以使用者體量不會有太大的增長,因此才可以使用這個方法。這種方法的架構圖是這樣的:
在這裡插入圖片描述

2.負載均衡

狗子諮詢了一些在中大型網際網路公司的學長,終於找到了一種解決這個問題還不像第一種方法那樣容易有生命危險的辦法,那就是nginx。

nginx是個什麼東西呢?是用來做伺服器負載均衡的,說白了就是當用戶傳送請求的時候,先經過nginx這個中間人,nginx會去感受哪個伺服器比較閒,就會把請求傳送到這個比較閒的伺服器上去,這樣執行多了,就可以做到每個伺服器相對的負擔比較平衡,這就是負載均衡。nginx可以放在伺服器本機,也可以放在單獨的一個伺服器中,nginx這個中間人會向各個伺服器分發請求,並且nginx的效能十分高超,每秒百萬級以下數量的請求都可以處理。你可能要問了,如果狗子把nginx單獨放在一個伺服器上,那麼他的三臺伺服器怎麼對應到同一個域名上呢?他是否需要給每個nginx分發的伺服器也就是那三臺購買三個域名呢?當然不用,事實上,現在我們對外的公共ip已經變成了安裝nginx的伺服器的ip了,也就是說,我們只要把域名對映到這個nginx伺服器就可以了,然後nginx中會有配置,我們只要在配置中寫下三個伺服器的ip,nginx以後就能把請求分發過去了。那麼,我們現在的架構圖就變成了下圖這樣:

在這裡插入圖片描述
狗子還想對伺服器做做優化,像是session這種東西,只是簡簡單單的一個session請求,卻要耗費伺服器那麼多的效能,有沒有一種方法,能夠對這方面做一些改進呢?

當然有,解決方案就是redis。

redis的作用

redis是一種資料庫,我們比較熟知的資料庫有mysql,sqlServer,oracle等,那麼這個redis又是個什麼玩意?
redis和上述幾種資料庫不同,它是快取資料庫,也就是說,redis是致力於短時儲存的,redis並不是從硬碟中拿取和處理資料,它對資料的處理都是在記憶體中,由於記憶體的資料處理速度不知道比磁碟高到哪裡去了,所以redis的效能也是碾壓mysql,sqlServer,oracle這種資料庫的,這無關於軟體優劣,純粹是因為硬體層面的因素。不過redis因為是在記憶體中,因此只要機器一關閉,記憶體中redis儲存的東西就會消失了,不過redis也可以將資料持久化儲存到mysql這些資料庫中,但是一涉及到對硬碟的操作,redis的效能就下來了。因此,我們的redis常常是用來儲存像是使用者的登入狀態這種短時需要的資料,而去把使用者登入註冊的時間備份到硬碟上的資料庫。那麼,我們現在的架構圖就變成了如下這樣:
在這裡插入圖片描述
又過了一段時間,隨著使用者體量越來越大,數量級達到了上萬上十萬的時候,狗子發現一直以來,自己都忽略了一個問題,儘管自己增加了伺服器,加了負載均衡,還啟用了redis快取資料庫,為了使使用者訪問的速度增加還有讓伺服器的負載不那麼大,但是,網站處理資料的方式本質上是對資料庫進行增刪改查,而現在我們的資料庫伺服器只有一臺,資料庫處理資料本身就是一項複雜耗費記憶體的工作,現在的一臺資料庫伺服器更是杯水車薪,因此,在中小型公司的網站架構中,最先撐不住的往往是資料庫伺服器。

當然,狗子又有了解決辦法。他又購入了兩臺伺服器當作資料庫伺服器,然後把資料庫進行了分庫分表的操作,分別把資料存在三臺資料庫伺服器上。當然狗子覺得這還不夠,因此,他又使用了一種技術,將資料庫進行了讀寫分離。

讀寫分離理解起來很簡單,和它的字面意思一樣,就是把從資料庫中寫入資料和從資料庫中拿取資料進行分離,以此來達到減少資料庫伺服器負擔的作用。用來讀取資料的伺服器和用來寫入資料的伺服器會在使用者進行操作之後延遲一段時間進行資料同步,一般來說延遲時間不會太長,很可能使用者都不會覺察到。那麼,我們現在的架構圖就變成了下圖這樣:
在這裡插入圖片描述
可以看到,我們的圖上新出現了“叢集”這個詞,不錯,網際網路經常提及的xxx叢集終於在我們眼前解開了神祕面紗,也就是多臺伺服器同時協同處理事務,就可以稱作一個伺服器叢集。

三、大型公司網路架構

時光飛逝,轉眼間五年的時間過去了,狗子已經從一箇中小型網際網路公司的小老闆搖身一變成了一個上市公司總裁,和馬雲馬化騰等it行業巨佬互動成了他的日常,他的一句話可以動搖it界,他的網站也擁有了上億的使用者。。。。。

到了這種程度,狗子的公司網路架構已經變成了下圖這樣:
(內容比較多,看不清記得放大哦)
在這裡插入圖片描述
能支援上億人訪問的伺服器肯定不止這麼幾個,只是象徵性地畫了幾個。同時,我們把redis伺服器與mysql伺服器進行了連線,是因為我們前面說過redis可以將資料存入永續性資料庫,這裡我們可以用來記錄登入時間之類的資訊。同時,圖中的mysql伺服器是重疊在一起的,不要以為僅僅只有兩臺伺服器。

隨著公司變為巨頭,狗子的經驗不斷累積,他發現自己的公司雖然體量很大,開發的產品越來越多,功能越來越全面,但是總是有那麼一部分的功能是重複的。假如在一個新的頁面或者產品中,剛開始開發時有那麼10%是和以前開發過的頁面或者產品的功能是重複的,那麼,等到這個新東西的功能開發接近完善的時候,就可能會有70%的功能和從前開發的一樣。仔細想想這是一件很可怕的事情,狗子居然畫了70%的開發時間和開發成本在做以前早就做過的事情。

這狗子就不能忍了,於是他想到了一個好辦法,既然面向物件程式語言中有封裝的這種概念,把程式碼的重複部分封裝起來便於重複使用,那麼產品和產品之間為何不能封裝相同的東西便於使用呢?

於是,他開始實現微服務的概念,解釋起來可能一上來比較難於接受,我們先來看,剛剛我們的架構圖中的產品實際上可以看成一整個系統,假設這個系統叫做系統A。那麼,我們現在開發出來了其它的各種產品或者各種頁面,也可以看作是新的系統B和系統C。現在,系統ABC之間有很多重複的部分,於是,我們想到了將這些重複的部分放到一起,供三個系統同時呼叫。那麼實際上,這個重複的部分就是被封裝起來的微服務,微服務是一種模組化開發,把產品的功能提煉成多個模組,在開發時把模組拼接起來,就可以省去大量的工作。為了實現一個模組,模組中也需要帶有伺服器叢集等東西。聽了這些,我們下面的架構圖看起來應該沒有那麼難懂了:

在這裡插入圖片描述
這些與技術無關,而是一種開發理念,一種思想,有了這種思想,才能在成千上萬的使用者需求之間找到共通,提升開發效率,節省成本。

狗子有了這種思想,並實現了他,終於打敗了所有競爭對手,迎娶白富美,走上了人生巔峰。




















後來,他夢醒了。。。