(五)網(wǎng)絡編程之流量接入層設計:基于性能怪獸從零構(gòu)建日均億級吞吐量的網(wǎng)關(guān)架構(gòu)逝段!

引言

? ?在前篇關(guān)于《Nginx》的文章中曾經(jīng)提到:單節(jié)點的Nginx在經(jīng)過調(diào)優(yōu)后,可承載5W左右的并發(fā)量桑腮,同時為確保Nginx的高可用捌朴,在文中也結(jié)合了Keepalived對其實現(xiàn)了程序宕機重啟洽损、主機下線從機頂替等功能庞溜。

但就算實現(xiàn)了高可用的Nginx依舊存在一個致命問題:如果項目的QPS超出5W,那么很有可能會導致Nginx被流量打到宕機碑定,然后根據(jù)配置的高可用規(guī)則流码,Keepalived會對Nginx重啟,但重啟后的Nginx依舊無法承載業(yè)務帶來的并發(fā)壓力延刘,結(jié)果同樣會宕機.....

經(jīng)過如上分析后漫试,明顯可看出,如果Nginx面對這種超高并發(fā)的情況碘赖,就會一直處于「在重啟驾荣、去重啟的路上」這個過程不斷徘徊,因此在此背景下崖疤,我們需要設計出一套能承載更大流量級別的接入層架構(gòu)。

不過相對來說典勇,至少90%以上的項目用不上這套接入層架構(gòu)劫哼,因為大部分項目上線后,能夠擁有的用戶數(shù)是很有限的割笙,壓根無法產(chǎn)生太高的并發(fā)量权烧,所以往往一個Nginx足以支撐系統(tǒng)的訪問壓力眯亦。

不過雖說大家不一定用的上,但不懂兩個字我們絕不能說出口般码,尤其是面試過程中妻率,往往頻繁問到的:你是如何處理高并發(fā)的? 跟本文有很大的聯(lián)系板祝,之后被問到時宫静,千萬先別回答什么緩存、削峰填谷券时、熔斷限流孤里、分庫分表.....等這類的,首先需要先把接入層說清楚橘洞,因為如果接入層都扛不住訪問壓力捌袜,流量都無法進到系統(tǒng),后續(xù)這一系列處理手段自然沒有意義炸枣。

一虏等、億級吞吐第一戰(zhàn)-DNS輪詢解析

? ?對于單節(jié)點的Nginx而言,雖然利用Keepalived實現(xiàn)了高可用适肠,但它更類似于一種主從關(guān)系霍衫,從機在主機正常的情況下,并不能為主機分擔訪問壓力迂猴,也就代表著作為主節(jié)點的機器慕淡,需要憑“一己之力”承載整個系統(tǒng)的所有流量。那么當系統(tǒng)流量超出承載極限后沸毁,很容易導致Nginx宕機峰髓,所以也需要對Nginx進行橫向拓展,那又該如何實現(xiàn)呢息尺?最簡單的方式:DNS輪詢解析方案携兵。
? ?DNS輪詢解析技術(shù)算一種較老的方案了,但在如今的大舞臺上依舊能夠看見它的身影搂誉,它源自于DNS的域名多記錄解析徐紧,在《HTTP/HTTPS》文章中曾聊到過,DNS域名系統(tǒng)本質(zhì)上是一個大型的分布式K-V數(shù)據(jù)庫炭懊,以域名作為Key并级,以物理服務器的公網(wǎng)IP作為Value,而大多數(shù)域名注冊商都支持為同一個域名配置多個對應的IP侮腹,如下:

DNS多IP配置

如上圖所示嘲碧,為一個域名配置多個映射的IP后,DNS服務器在解析域名請求時父阻,就會依據(jù)配置的IP順序愈涩,將請求逐一分配到不同的IP上望抽,也就是《上文》所提及到的輪詢調(diào)度方式。

借助DNS的輪詢解析支持履婉,對Nginx可以輕松實現(xiàn)橫向拓展煤篙,也就是同一個域名配置的多臺物理機,分別都部署一個Nginx節(jié)點毁腿,每臺Nginx節(jié)點的配置信息都一樣辑奈。

好比目前每瞬12W的并發(fā)量,配置域名時狸棍,映射3臺真實Nginx服務器身害,最終經(jīng)過DNS輪詢解析后,12W的并發(fā)請求被均攤到每臺Nginx草戈,每個節(jié)點分別承載4W的并發(fā)請求塌鸯,通過這種方式就能夠完美的解決之前的:單節(jié)點Nginx無法承載超高并發(fā)量而宕機的問題,如下:

Nginx水平集群

同時DNS域名解析唐片,也依舊可以配置調(diào)度算法丙猬,如Rate權(quán)重分配、最少連接數(shù)分配费韭、甚至可以按照客戶端網(wǎng)絡的運營商茧球、客戶端所在地區(qū)等方式進行解析分配,但僅一小部分的DNS服務器支持星持。

淺談DNS域名輪詢解析的優(yōu)劣

這種方式帶來的優(yōu)勢極為明顯:

無需增加額外的成本即可實現(xiàn)多節(jié)點水平集群抢埋,利于系統(tǒng)拓展。

但也存在非常大的劣勢:

  • ①與其他的負載均衡方案不同督暂,其他的負載方案一般都會自帶健康監(jiān)測機制揪垄,但DNS則無法感知,也就是當下游的某服務器宕機逻翁,DNS服務器會依舊向其分發(fā)請求饥努。
  • ②無法根據(jù)服務器的硬件配置,合理的分配客戶端請求八回,大部分DNS服務器只支持最簡單的輪詢調(diào)度酷愧。

雖然DNS輪詢解析方案存在很大的劣勢,但這兩個劣勢對比其帶來的收益可以忽略不計缠诅,因為現(xiàn)在云計算技術(shù)的發(fā)展溶浴,多臺節(jié)點保持相同的配置已不再是難事。同時管引,由于Nginx本身就會利用KeepalivedVIP機制實現(xiàn)高可用士败,所以就算某個節(jié)點宕機,從機也可頂替上線接管流量汉匙,中間只會有很短暫的切換時間拱烁。

而且如果DNS將客戶端請求分發(fā)到某個宕機節(jié)點時,客戶端看到的結(jié)果便是空白頁噩翠、超時無響應或請求錯誤的信息戏自,通常情況下,依據(jù)用戶的習性伤锚,都會再次重試擅笔,那么客戶端再次發(fā)出的請求會被輪詢解析到其他節(jié)點,而從機在這個時間間隔內(nèi)也能夠成功上線接管服務屯援。

二猛们、億級吞吐第二戰(zhàn)-CDN內(nèi)容分發(fā)

? ?CDN(Content Delivery Network)內(nèi)容分發(fā)網(wǎng)絡是一種構(gòu)建在現(xiàn)有網(wǎng)絡基礎上的智能虛擬網(wǎng)絡榛搔,依靠部署在全球各地的節(jié)點琳骡,通過負載均衡、內(nèi)容分發(fā)妙痹、機器調(diào)度等功能吉懊,使用戶的請求能夠被分發(fā)到離自身最近的節(jié)點處理庐橙,就近獲取所需的資源,最終達到提升用戶訪問速度以及降低服務器訪問壓力等目的借嗽。

? ?CDN出現(xiàn)的本質(zhì)是為了解決不同地區(qū)用戶訪問速度不一致問題态鳖,在之前的《TCP/IP》文中曾提到過,網(wǎng)絡上的數(shù)據(jù)傳輸本質(zhì)上最終都會依賴于物理層的傳輸介質(zhì)恶导,那么當用戶和目標服務器的“實際地理距離”越長浆竭,訪問的速度自然會越慢,而CDN的核心就在于:各地區(qū)都會部署子節(jié)點惨寿,當用戶訪問時邦泄,會將其請求分發(fā)到距離最近的節(jié)點處理,就好比生活中的例子:

某個想吃北京烤鴨的人身在美國缤沦,最初僅北京有相應的店鋪虎韵,因此想吃的時候必須得跑到北京去買,那么這一去一回的過程自然會需要很長時間缸废,而CDN的思想就是在各地都開分店包蓝,好比美國也有北京烤鴨的分店,當某個用戶想吃時企量,不再需要跑到北京去買测萎,而是可以直接選擇就近的店鋪進行購買,這樣速度自然會更快届巩。

2.1硅瞧、CDN分發(fā)的內(nèi)容

? ?通常一個平臺的資源都會分為靜態(tài)與動態(tài)兩種類型,而CDN本質(zhì)上是一種類似于緩存的技術(shù)恕汇,緩存必然會存在延遲性腕唧,對于會經(jīng)常發(fā)生變化的動態(tài)資源或辖,使用CDN意義并不大,因為CDN無法確保數(shù)據(jù)的實時性枣接。
? ?由于靜態(tài)資源很少發(fā)生變更颂暇,所以CDN一般會用于靜態(tài)資源的分發(fā),如果你要使用CDN服務但惶,國內(nèi)有大量的CDN提供商提供這類服務耳鸯,當購買CDN服務后,將靜態(tài)資源傳給CDN服務膀曾,那么這些靜態(tài)資源將自動的被分發(fā)到提供商全球各地的CDN節(jié)點县爬。

2.2、CDN實現(xiàn)原理

? ?在系統(tǒng)接入CDN服務并將靜態(tài)資源傳遞給CDN后添谊,那么當用戶再訪問系統(tǒng)時财喳,對應的一些請求就會被分發(fā)到距離用戶最近的CDN節(jié)點處理,但這究竟是如何實現(xiàn)的呢斩狱?接下來簡單聊一聊纲缓。

一般用戶發(fā)送請求都是通過域名去進行訪問的,域名最終會被解析成一個IP喊废,那么如何解析出一個距離用戶最近的服務器IP祝高,這是普通的DNS服務器做不到的,因此CDN為了實現(xiàn)這點污筷,需要特殊的DNS服務器去解析域名請求工闺,該DNS服務器需要解決兩個問題:
①需要得知用戶目前的所在位置。
CDN所有節(jié)點中瓣蛀,哪個節(jié)點離用戶最近陆蟆。

對于上述兩個問題,第一個問題可以直接從用戶的請求中提取客戶端IP惋增,然后根據(jù)IP去判斷叠殷,可以將IP解析為上海電信、北京移動等诈皿,從而能夠確定用戶的大概位置林束。

第一個問題容易找到答案,但實現(xiàn)CDN請求分發(fā)的難點在于第二個問題:如何確定距離用戶最近的CDN節(jié)點稽亏。這時就需要用到DNS解析中的CNAME機制了壶冒,DNS域名解析主要會分為兩種:

  • ①將一個域名解析為一個具體的IP,這種方式被稱為A記錄機制截歉。
  • ②將一個域名解析為另一個域名胖腾,這種方式就被稱為CNAME機制。

CDN中,這個CNAME會被配置為CDN專用DNS服務器的域名地址咸作。

某個用戶通過域名static.xxx.com請求靜態(tài)資源時锨阿,這個域名會映射著一個CNAME,例如cdn.xxx.com记罚,當普通的DNS服務器收到用戶的static.xxx.com域名請求后群井,經(jīng)過解析得到一個CNAME,該CNAME對應的則是CDN專用的DNS服務器毫胜,那么會將域名解析工作轉(zhuǎn)交給該DNS服務器處理,CDN專用DNS服務器對cdn.xxx.com域名解析诬辈,根據(jù)服務器上記錄著的所有CDN節(jié)點信息酵使,選出距離用戶最近的CDN服務器地址并返回給用戶,最后用戶就可通過該地址訪問距離自己最近的CDN節(jié)點焙糟。

上述這個過程也被稱為智能DNS解析技術(shù)口渔。

2.3、CDN帶來的優(yōu)勢

? ?大致聊了CDN分發(fā)原理后穿撮,再來思考思考CDN的引入能夠給系統(tǒng)帶來哪些好處呢缺脉?

  • ①加快用戶的訪問速度,帶來更好的用戶體驗感悦穿。
  • ②分擔系統(tǒng)50%以上的訪問流量攻礼,降低系統(tǒng)的負載壓力。
  • ③節(jié)省系統(tǒng)源站的帶寬消耗栗柒,降低網(wǎng)絡帶寬的成本礁扮。
  • ④進一步提升系統(tǒng)安全性,大部分攻擊請求會被CDN節(jié)點阻擋瞬沦。

? ?從上看來太伊,系統(tǒng)接入CDN服務后帶來的收益很大,就算原本的系統(tǒng)訪問速度很慢逛钻,在接入CDN后也能夠快速加載僚焦,對于用戶而言體驗感會進一步提升,并且最關(guān)鍵的是:對于網(wǎng)站整體而言曙痘,幾乎90%以上的靜態(tài)請求會由CDN去響應芳悲,系統(tǒng)源站能夠減輕很大的訪問壓力,從而能夠確保系統(tǒng)本身擁有更大的“動態(tài)請求”吞吐能力边坤。

三芭概、億級吞吐第三戰(zhàn)-LVS負載均衡

? ?在之前提到過,我們可以通過DNS的輪詢解析機制對Nginx實現(xiàn)水平拓展惩嘉,從而使得接入層能夠承擔更高的并發(fā)訪問罢洲,但DNS由于其機制的不健全,所以一般并不會采用它去實現(xiàn)Nginx的集群,畢竟動態(tài)伸縮也不方便惹苗,更改配置后需要3~4小時才能生效殿较。
? ?如果要對Nginx實現(xiàn)集群,一般都會采用LVS去實現(xiàn)桩蓉,也包括淘寶淋纲、騰訊等大部分企業(yè),都使用了LVS技術(shù)院究,那什么是LVS呢洽瞬?

LVS-LOGO

LVSLinux Virtual Server的簡稱,意為Linux虛擬服務器业汰,本項目在19985月由章文嵩博士成立伙窃,在Linux2.6版本中被正式加入系統(tǒng)內(nèi)核,關(guān)于更多可參考:《LVS-百度百科》样漆。

? ?LVS一般被用作于負載調(diào)度器为障,它與Nginx的功能類似,但不同點在于:LVS工作在OSI七層網(wǎng)絡模型中的第四層-網(wǎng)絡層放祟,而Nginx則是工作在第七層-應用層鳍怨,同時LVS并非是以進程的方式運行在操作系統(tǒng)上的,而是直接位于Linux內(nèi)核中工作跪妥,因此LVS的性能一般是Nginx的十倍以上鞋喇。

其實在很多大型互聯(lián)網(wǎng)企業(yè)中,都能看見LVS的身影眉撵,例如淘寶的接入層設計确徙、阿里云中的SLB-CLB四層負載均衡服務等都是基于LVS實現(xiàn)的。

LVS相較于其他軟件負載均衡技術(shù)(Nginx执桌、HaProxy)的特點:

  • ①工作在網(wǎng)絡層鄙皇,位于系統(tǒng)內(nèi)核,擁有更高的性能仰挣、可用性伴逸。
  • ②能夠?qū)⒃S多低性能的服務器組合在一起形成一個高性能的超級服務器群。
  • ③擁有四種工作模式以及十二種調(diào)度算法膘壶,適用于各類不同的業(yè)務場景错蝴。
  • ④擁有健全的節(jié)點健康監(jiān)測機制,并且擁有很強的拓展性颓芭,支持動態(tài)伸縮顷锰。

同時在LVS中存在大量專業(yè)術(shù)語,如下:

  • Director:負載均衡器亡问,指LVS本身官紫。
  • Balancer:請求分發(fā)器肛宋,也指LVS本身。
  • Real Server(RS):后端負責請求處理的服務器束世。
  • Client IP(CIP):客戶端的IP地址酝陈。
  • Virtural IP(VIP):虛擬IP地址。
  • Director IP(DIP)LVS所在的服務器IP地址毁涉。
  • Real Server IP(RIP):后端服務器的IP地址沉帮。

LVS基本工作原理

LVS基本原理
  • ①客戶端通過訪問VIP發(fā)送請求報文,調(diào)度器收到后會將其發(fā)往內(nèi)核空間贫堰。
  • ②內(nèi)核中的PREROUTING鏈會先收到請求穆壕,確認是發(fā)往自己的請求后會轉(zhuǎn)給INPUT鏈。
  • ip_vs是工作在INPUT鏈上的其屏,IPVS會將用戶請求和VIP列表進行匹配喇勋,匹配成功后會修改請求報文中的目的地址及端口,然后將新的報文發(fā)給POSTROUTING鏈漫玄。
  • POSTROUTING鏈收到報文后,發(fā)現(xiàn)更改后的報文中目標地址正好是自己配置的后端服務器RS地址压彭,那此時就會通過選路睦优,最終將數(shù)據(jù)報文發(fā)送給后端服務器。

OK~壮不,對于LVS有了一點基本認識之后汗盘,接著來看看LVS中四種工作模式以及十二種調(diào)度算法。

3.1询一、LVS四種工作模式

? ?在LVS中隐孽,為了適應不同的應用場景,因此也專門研發(fā)了多種不同的工作模式健蕊,每種工作模式都有各自的應用場景菱阵,LVS中共計存在四種工作模式:
NAT、DR缩功、TUN晴及、FULL-NAT,其中最為常用的是DR直接路由模式嫡锌,接下來詳細剖析看看虑稼。

3.1.1、網(wǎng)絡地址轉(zhuǎn)換模式(NAT)

? ?NAT模式與帶有防火墻的私有網(wǎng)絡結(jié)構(gòu)類似势木,LVS作為所有后端服務器節(jié)點的網(wǎng)關(guān)層蛛倦,客戶端請求與后端服務器的響應都會經(jīng)過LVSLVS在整個接入層中作為客戶端的訪問入口啦桌,作為服務端的返回出口溯壶,后端服務器位于內(nèi)網(wǎng)環(huán)境,使用私有IP地址,與LVS位于同一物理網(wǎng)段茸塞,如下:

NAT模式

  • ①客戶端CIP請求VIP躲庄,VIPDIP,也就是LVS本身钾虐。
  • LVS將客戶端請求報文中的目標地址改為后端一臺具體的RIP地址噪窘。
  • RS將請求處理完成后,會將響應結(jié)果組裝成應答報文返回給LVS效扫。
  • LVS收到后端的響應數(shù)據(jù)后倔监,會將響應報文中的目標地址改為自身的VIP

NAT模式中菌仁,由于請求/應答的雙向流量都需要經(jīng)過LVS浩习,因此對于LVS的性能、帶寬開銷比較大济丘,同時需要注意:如果采用NAT模式谱秽,那么DIP、RIP必須要在同一個物理網(wǎng)絡中摹迷。

3.1.2疟赊、直接路由模式(DR)

? ?DR模式中,是采用半開放式網(wǎng)絡結(jié)構(gòu)實現(xiàn)的峡碉,后端的各節(jié)點與LVS位于同一個物理網(wǎng)絡近哟,LVS在其中作為客戶端的訪問入口,但服務端返回響應時則不需要經(jīng)過LVS鲫寄,而是直接把數(shù)據(jù)響應給客戶端吉执,如下:

DR模式

  • ①客戶端CIP請求VIP,請求報文中CIP為源地址地来,VIP為目標地址戳玫。
  • ②請求會先到LVS上,LVS會將報文中的目標MAC地址改變?yōu)槟撑_RSMAC地址未斑。
  • RS收到請求后發(fā)現(xiàn)是自己的MAC地址量九,并且也是自己的IP地址,則會處理請求颂碧。
  • RS處理完成請求后荠列,會根據(jù)請求報文中的源地址,直接將應答報文返回給CIP载城。

DR模式中肌似,很明顯的可以看出,客戶端請求的流量會通過LVS作為入口诉瓦,但服務端的應答流量卻不用通過LVS作為出口川队。因為在DR模式中力细,LVS與后端的RS都會綁定同一個VIP,然后LVS會通過修改目標MAC地址的方式實現(xiàn)請求分發(fā)固额,當RS收到請求后眠蚂,發(fā)現(xiàn)目標MAC、IP地址都是自己后斗躏,就會開始處理請求逝慧。

在這個過程中,由于客戶端請求的是VIP地址啄糙,而LVS笛臣、RS都綁定相同的VIP,所以LVS改掉目標MAC地址隧饼,轉(zhuǎn)發(fā)請求后沈堡,在RS角度來看是無法感知的,畢竟自己的IP就是請求報文中的VIP燕雁,所以RS會認為該請求就是客戶端直接請求自己的诞丽。

RS將客戶端的請求處理完成之后,會根據(jù)請求報文中的源IP地址拐格,作為應答報文的目標IP地址僧免,直接將響應結(jié)果返回給客戶端,無需經(jīng)過LVS再次包裝禁荒,這樣能夠很好的解決之前NAT模式中存在的不足猬膨。

3.1.3角撞、IP隧道模式(TUN)

? ?TUN模式是采用開放式網(wǎng)絡結(jié)構(gòu)呛伴,服務端的各節(jié)點可以不與LVS位于同一網(wǎng)絡,也就是后端服務器可以分散在互聯(lián)網(wǎng)中的不同網(wǎng)絡中谒所,但每個后端節(jié)點必須要有獨立的公網(wǎng)IP热康,因為LVS需要通過專用的IP隧道與后端節(jié)點相互通信。其中LVS主要作為客戶端的訪問入口劣领,服務器響應結(jié)果時姐军,直接通過各自的Internet連接返回給客戶端,不需要經(jīng)過LVS尖淘,如下:

TUN模式

  • ①客戶端發(fā)送請求報文到LVS服務器奕锌,報文源IPCIP,目標IPVIP村生。
  • LVS收到請求報文后惊暴,不會再修改報文內(nèi)容,而是在報文前面再添加一個IP報文頭趁桃。
    • 新增的IP報文中源地址為CIP辽话,目標地址為一臺具體的RIP肄鸽。
  • RS收到新封裝的報文后,會解封數(shù)據(jù)報油啤,然后處理客戶端請求典徘。
  • ④處理完成后會根據(jù)請求報文中的源IP:CIP,將應答報文直接返回給客戶端益咬。

從上述過程中會發(fā)現(xiàn)逮诲,TUN模式似乎與之前的DR模式有些類似纫溃,但與DR模式不同的是:TUN模式是基于IP隧道技術(shù)實現(xiàn)的飞蛹,并且整個LVS集群中的所有節(jié)點,都可以不在一個物理網(wǎng)絡中溯街,也就是LVS评腺、RS可以是分散在各地的服務器帘瞭,但需要額外注意:VIP、DIP蒿讥、RIP必須全部要為公網(wǎng)IP蝶念,不然無法使用IP隧道機制。

3.1.4芋绸、雙向網(wǎng)絡地址轉(zhuǎn)換模式(FULL-NAT)

? ?FULL-NAT模式在之前的版本中是不存在的媒殉,這個模式是章文嵩博士去了阿里之后,專門針對于阿里的業(yè)務研發(fā)的一種新模式摔敛,它是NAT模式的升級版本廷蓉,在NAT模式中只做兩次IP轉(zhuǎn)換,而FULL-NAT模式會做四次马昙,如下:

FULL-NAT模式

  • ①客戶端會先發(fā)送請求報文到LVS桃犬,報文中源IPCIP,目標IPVIP行楞。
  • LVS收到客戶端的報文后攒暇,會將源地址改為自身的DIP,并將目標IP改為RIP子房。
  • RS接收到請求后會進行處理形用,處理完成之后會將應答報文返回給LVS服務器。
  • LVS會將應答報文中的源IP改為VIP证杭,目標IPCIP田度,從而將數(shù)據(jù)響應給客戶端。

FULL-NAT模式中解愤,一共會做四次IP的轉(zhuǎn)換镇饺,那為何要這樣實現(xiàn)呢?因為之前的NAT模式中琢歇,DIP兰怠、VIP梦鉴、RIP都必須要位于同一個VLAN物理網(wǎng)絡中,那么此時就會導致RS集群的主機數(shù)量受到限制揭保。

FULL-NAT模式中肥橙,LVS收到客戶端請求后,會將報文中的源地址改為自身的DIP秸侣,并將目標IP改為RIP存筏,這樣對于RS而言,DIP就成了客戶端味榛,因此可以實現(xiàn)跨VLAN椭坚、跨機房、跨網(wǎng)絡進行請求分發(fā)搏色。

RS處理完對應的請求后善茎,會將數(shù)據(jù)返回到LVSLVS又會將應答報文中的源IP改為VIP频轿,目標IPCIP垂涯,從而由LVS作為響應者返回數(shù)據(jù)。

當然航邢,FULL-NAT模式雖然能夠?qū)崿F(xiàn)跨網(wǎng)絡分發(fā)耕赘,但由于其中進行了多次IP轉(zhuǎn)換,因此對比普通的NAT模式而言膳殷,分發(fā)的效率要降低10%左右操骡。

3.1.5、四種工作模式對比

對比項 NAT DR TUN FULL-NAT
分發(fā)性能 NO.03 NO.01 NO.2 NO.4
網(wǎng)絡結(jié)構(gòu) 封閉式網(wǎng)絡 半開放式網(wǎng)絡 開放式網(wǎng)絡 半開放式網(wǎng)絡
數(shù)據(jù)響應 LVS RS RS LVS
轉(zhuǎn)發(fā)實現(xiàn) 改目標IP 改目標MAC 新增IP數(shù)據(jù)報 重構(gòu)IP數(shù)據(jù)報
使用限制 局域網(wǎng)絡 綁定同一VIP 需支持Tunneling RS與LVS要能通信
模式特點 內(nèi)外網(wǎng)隔離 性能最佳 遠距離分發(fā) 可跨網(wǎng)絡分發(fā)

LVS的四種工作模式中赚窃,DR是性能最好的册招,也是正常情況下使用最為頻繁的工作模式,同時也是LVS默認的工作模式考榨。

3.2跨细、LVS十二種調(diào)度算法

? ?與其他的負載調(diào)度技術(shù)相同鹦倚,在LVS中也提供了多種調(diào)度算法河质,主要也分為兩大類:靜態(tài)調(diào)度以及動態(tài)調(diào)度算法,兩類算法共計十二種震叙,如下:

  • 靜態(tài)調(diào)度算法:
    • 輪詢算法(RR
    • 加權(quán)輪詢算法(WRR
    • 源地址哈希算法(SH
    • 目標地址哈希算法(DH
  • 動態(tài)調(diào)度算法:
    • 最小連接數(shù)算法(LC
    • 加權(quán)最小連接數(shù)算法(WLC
    • 最短延遲算法(SED
    • 最少隊列算法(NQ
    • 局部最少連接數(shù)算法(LBLC
    • 帶復制的局部最少連接數(shù)算法(LBLCR
    • 加權(quán)故障轉(zhuǎn)移算法(FO
    • 加權(quán)活動連接數(shù)算法(OVF

其中動態(tài)算法對比靜態(tài)算法而言會更為智能化掀鹅,但分發(fā)效率也會更低,接下來簡單看看LVS中提供的每種調(diào)度算法媒楼。

不會對每種算法進行原理剖析乐尊,大致分析其過程和思想,如想要了解調(diào)度算法具體實現(xiàn)的小伙伴可參考上篇:《網(wǎng)絡編程之請求分發(fā)篇》划址。

3.2.1扔嵌、輪詢算法(RR)

? ?輪詢算法在LVS中也被稱為輪叫限府、輪調(diào)算法,但本質(zhì)上意思都是相同的痢缎,對于配置的多個服務端節(jié)點胁勺,依次分發(fā)請求處理。

在這種算法中独旷,分發(fā)請求時講究雨露均沾署穗,會對配置的所有節(jié)點無差別的依次調(diào)度。

具體實現(xiàn)可參考《請求分發(fā)篇-輪詢算法實現(xiàn)》嵌洼。

3.2.2案疲、加權(quán)輪詢算法(WRR)

? ?這種算法屬于輪詢算法的升級版本,主要是為了照顧到集群中硬件配置不同的節(jié)點麻养,根據(jù)服務器自身的硬件基礎褐啡,為不同服務器配置不同的權(quán)重值,性能越好的服務器配置越高的權(quán)重值鳖昌,LVS在分發(fā)請求時春贸,會根據(jù)配置的權(quán)重值,分發(fā)對應比例的請求數(shù)到每臺服務器遗遵。

這種算法相較于基本的輪詢調(diào)度而言萍恕,更加智能化一些,因為能夠根據(jù)節(jié)點的性能去配置對應權(quán)重车要,能夠在最大程度上將每臺服務器的性能發(fā)揮到極致允粤。

具體實現(xiàn)可參考《請求分發(fā)篇-平滑加權(quán)輪詢算法實現(xiàn)》

3.2.3翼岁、源地址哈希算法(SH)

? ?之前的兩種調(diào)度算法类垫,都無法解決session不一致問題:

session不一致問題:好比最簡單的登錄功能,客戶端發(fā)送請求登錄成功琅坡,然后將其登錄的狀態(tài)保存在session中悉患,結(jié)果客戶端的第二次請求被分發(fā)到了另外一臺機器,由于第二臺服務器session中沒有相關(guān)的登錄信息榆俺,因此會要求客戶端重新登錄售躁。

而源地址哈希算法中,LVS會根據(jù)請求報文中的源IP地址進行哈希計算茴晋,然后最終計算出一臺服務器的IP陪捷,并將該請求分發(fā)到對應的節(jié)點處理,同時由于分發(fā)請求是基于哈希算法實現(xiàn)的诺擅,那么之后每當相同的客戶端請求時市袖,由于源IP地址是相同的,所以同一客戶端的請求都會被分發(fā)到同一臺服務器處理烁涌。

3.2.4苍碟、目標地址哈希算法(DH)

? ?與源地址哈希算法相同酒觅,目標地址哈希算法也是一種基于哈希算法實現(xiàn)的,但該算法中是基于目標地址作為哈希條件去進行計算微峰,從而計算出一臺的具體服務器地址阐滩,最后將對應的請求轉(zhuǎn)發(fā)到對應節(jié)點處理。

需要額外注意的是:這里的目標地址并非指請求報文中的目標IP地址县忌,因為本質(zhì)上客戶端都是通過請求相同的VIP來訪問LVS的掂榔,所以請求報文中的目標IP地址都是相同的,要是基于目標IP地址去計算症杏,那么會將所有請求都分發(fā)到一個節(jié)點上装获。

既然不是通過請求報文中的目標IP地址進行計算,那這里所謂的“目標地址”究竟是什么呢厉颤?要搞清楚這個點之前穴豫,首先得理解DH算法的應用場景,一般DH算法都是應用在緩存場景中的逼友,所以這里的“目標地址”其實是緩存的目標Key值精肃,舉例:

請求①:put name '竹子'
請求②:get name

在上述案例中,請求①是寫入操作帜乞,其Keyname司抱,DH算法會以該值作為哈希計算的條件,從而算出一臺服務器地址黎烈,并將其該Key值的緩存項寫入到該節(jié)點中习柠。請求②則是一個讀取操作,由于讀取的目標為name照棋,與之前寫入操作的Key相同资溃,那么DH算法計算之后,最終得到的服務器地址也是相同的烈炭,就會將這個讀取請求分發(fā)到之前寫入緩存的節(jié)點溶锭,確保能夠命中數(shù)據(jù)。

對于兩種哈希算法的具體實現(xiàn)可參考《請求分發(fā)篇-一致性哈希算法實現(xiàn)》符隙。

3.2.5趴捅、最小連接數(shù)算法(LC)

? ?最小連接數(shù)算法,也可以被稱為最小活躍數(shù)算法膏执、最空閑節(jié)點算法等驻售,該算法屬于動態(tài)算法的一種露久,相較于之前的四種靜態(tài)算法更米,該算法更為智能化,在這種算法中可以根據(jù)所有節(jié)點的負載情況毫痕,進行“相對合理”的請求分發(fā)征峦,永遠都會選取最為空閑的那臺服務器來處理請求迟几。

如果存在多個連接數(shù)都為最小的節(jié)點,則是類似于輪詢的方式去依次調(diào)度栏笆。

這種算法中类腮,能夠根據(jù)線上各服務器的實際運行情況分發(fā)請求,能夠?qū)⒓褐小白鍪伦钌俚墓?jié)點揪出來”處理請求蛉加,從而做到“杜絕任何服務器出現(xiàn)摸魚情況”蚜枢。

3.2.6、加權(quán)最小連接數(shù)算法(WLC)

? ?LC针饥、WLC算法的關(guān)系就類似于之前的輪詢和加權(quán)輪詢算法厂抽,加權(quán)最小連接數(shù)算法是最小連接數(shù)算法的升級版本,也就是說可以為每個節(jié)點配置權(quán)重丁眼,當尋找連接數(shù)最小的節(jié)點時筷凤,如果集群中存在多個連接數(shù)都為最小的節(jié)點,那最終就會根據(jù)配置的權(quán)重值苞七,來決定當前請求具體交由誰處理藐守。

Dubbo的負載均衡-最小活躍數(shù)算法的實現(xiàn)中,實現(xiàn)的就是加權(quán)最小活躍數(shù)版本蹂风。

對于最小連接數(shù)算法的具體實現(xiàn)感興趣的小伙伴可參考《請求分發(fā)篇-最小活躍數(shù)算法實現(xiàn)》卢厂。

3.2.7、最短預期延遲算法(SED)

? ?最短預期延遲算法是基于WLC算法實現(xiàn)的惠啄,WLC算法中足淆,如果權(quán)重值和連接數(shù)都相同,那么會隨機調(diào)度一個節(jié)點處理請求礁阁,這顯然還并沒有那么那么“智能”巧号,因此SED算法的出現(xiàn)就是為了解決該問題。

WLC算法中衡量連接數(shù)標準是綜合考慮所有連接數(shù)的姥闭,而SED算法中則只考慮活動連接數(shù)丹鸿,也就是說SED算法只會選擇活動連接數(shù)最小的節(jié)點,這樣能夠確保選擇的節(jié)點將會是整個集群中棚品,預期延遲最短的RS靠欢,因為活動連接數(shù)最小,所以也就代表著該節(jié)點實際負載最低铜跑,那么響應速度也就最快门怪。

3.2.8、最少隊列算法(NQ)

? ?最少隊列算法也被稱為永不排隊算法锅纺,這種算法又是基于SED算法實現(xiàn)的掷空,NQ算法在SED算法的基礎上,實現(xiàn)了一個活躍連接數(shù)為0的判斷,當有節(jié)點的活躍連接數(shù)為0時坦弟,那么無需經(jīng)過SED運算护锤,而是將請求直接分發(fā)過去,在沒有節(jié)點活躍數(shù)為0的情況下酿傍,正常使用SED算法分發(fā)請求烙懦,

LC、WLC赤炒、SED氯析、NQ四種算法,本質(zhì)上都是遞進的關(guān)系莺褒,后面的每種算法都基于之前的算法不足魄鸦,然后優(yōu)化后并推出的,最終的目的則是:讓請求分發(fā)時更為智能癣朗,選擇出的節(jié)點永遠都是性能最好的拾因。

不過在上篇文章中,我們也提到了另外一種更為智能的最優(yōu)響應算法旷余,該算法在開始前绢记,會對服務列表中的各節(jié)點發(fā)出一個探測請求,然后根據(jù)各節(jié)點的響應時間來決定由哪臺服務器處理客戶端請求正卧,該算法能更好根據(jù)節(jié)點列表中每臺機器的當前運行狀態(tài)分發(fā)請求蠢熄,具體實現(xiàn)可參考《請求分發(fā)篇-最優(yōu)響應算法實現(xiàn)》

3.2.9炉旷、局部最少連接數(shù)算法(LBLC)

? ?局部最少連接數(shù)算法其實比較雞肋签孔,屬于DH算法的動態(tài)版本,相對來說使用的也較少窘行,在該算法中會基于請求的目標地址進行分發(fā)饥追,首先根據(jù)其目標地址找出該目標地址最近使用的服務器,如若對應的服務器目前可用并沒有超載罐盔,就直接將該請求分發(fā)到這臺服務器處理但绕。如若找出的服務器不可用或請求負載過高,則根據(jù)LC算法找出集群中連接數(shù)最小的節(jié)點惶看,并將該請求分發(fā)過去捏顺。

3.2.10、帶復制的局部最少連接數(shù)算法(LBLCR)

? ?LBLCR算法也就是基于LBLC算法的升級版本纬黎,與LBLC算法的不同點在于:該算法會維護一個目的地址與一組服務器的映射表幅骄,而LBLC算法中只會維護目的地址與一個服務器的映射關(guān)系。

LBLCR算法中本今,會根據(jù)請求的目標地址先找到映射的一組服務器拆座,然后根據(jù)最少連接數(shù)算法從該組服務器中主巍,選出一臺節(jié)點處理請求,如若選擇的節(jié)點不可用或負載過高懂拾,則會去RS集群中再根據(jù)LC算法選擇一個節(jié)點煤禽,然后加入映射的服務器組中铐达,并將請求分發(fā)到該服務器岖赋。

同時,如果映射的服務器組很長一段時間內(nèi)都沒被修改過瓮孙,那會自動將“最忙”的服務器移除唐断。

DH、LBLC杭抠、LBLCR算法一般都是用于Cache集群環(huán)境中脸甘,但目前用的也比較少,因為一般的緩存中間件都有成熟的集群方案偏灿,除非需要自研緩存集群時丹诀,才會用到LVS這些算法作為緩存分發(fā)策略。

3.2.11翁垂、加權(quán)故障轉(zhuǎn)移算法(FO)

? ?加權(quán)故障轉(zhuǎn)移算法中铆遭,首先會遍歷所有的RS節(jié)點列表,然后從中找到負載較低且權(quán)重值最高的服務器沿猜,并將請求分發(fā)到該服務器上處理枚荣。

對于負載過高的服務器,LVS會對其設置一個IP_VS_DEST_F_OVERLOAD標識啼肩,這里說的“找到負載較低的服務器”橄妆,即代表著找到未設置IP_VS_DEST_F_OVERLOAD標識的節(jié)點。

3.2.12祈坠、加權(quán)活動連接數(shù)算法(OVF)

? ?加權(quán)活動連接數(shù)算法是基于服務器的活動連接數(shù)與權(quán)重值實現(xiàn)的害碾,在該算法中會首先找到權(quán)重值最高的可用節(jié)點,可用節(jié)點要滿足以下條件:

  • ①未設置IP_VS_DEST_F_OVERLOAD標識赦拘,即負載較低蛮原。
  • ②服務器當前的活動連接數(shù)小于其權(quán)重值。
  • ③服務器的權(quán)重值不能為0另绩。

找到權(quán)重值最高的可用節(jié)點后儒陨,會將請求分發(fā)到權(quán)重值最高的服務器,直至其活動連接數(shù)超過權(quán)重值為止笋籽。

FO蹦漠、OVF算法都是后面新增加的算法,只在內(nèi)核版本4.15及其以上的版本中才存在车海,如若你內(nèi)核的版本低于4.15笛园,那么需要額外打補丁后才能使用隘击。

3.2.13、分發(fā)調(diào)度算法小結(jié)

? ?經(jīng)過上述分析后研铆,不難得知的是:LVS前前后后共計提供了十二種調(diào)度算法埋同,其中靜態(tài)算法四種,動態(tài)算法八種棵红,越到后面的算法凶赁,其實現(xiàn)過程就越為復雜,但其分發(fā)請求也越為智能逆甜。所有算法中用的比較頻繁的是RR虱肄、WRR、SH交煞、LC咏窿、WLC五種。

? ?不過還是之前那句話素征,越智能的算法往往代表著開銷越大集嵌,在超高并發(fā)的情況下,將所有節(jié)點的硬件配置統(tǒng)一標準御毅,采用越普通根欧、越簡單的算法才是最佳的選擇。

3.3亚享、LVS的安裝與管理

LVS因本身是被加入到Linux內(nèi)核的咽块,所以無需額外再安裝,在內(nèi)核中名為ip_vs欺税。

①首先檢測一下內(nèi)核中是否有LVS模塊:

[root@localhost]# lsmod | grep -i ip_vs
ip_vs           141432  0 
nf_conntrack    133053  1 ip_vs
libcrc32c       12644  4 xfs,sctp,ip_vs,nf_conntrack

②如果沒有上面的內(nèi)容侈沪,需要加載一下:

[root@localhost]# modprobe ip_vs

ip_vs模塊加載到內(nèi)核后拥诡,即可安裝ipvsadm工具了稍浆,ipvsadmLVS官方提供的管理工具仅淑,因為LVS本身就成為了內(nèi)核的一部分帘腹,所以我們使用LVS本質(zhì)上是通過工具對內(nèi)核的ip_vs模塊進行調(diào)用。

3.3.1盐固、安裝ipvsadm管理工具

①首先需要安裝一下ipvsadm工具看疗,在線安裝方式:

[root@localhost]# yum install -y ipvsadm

離線方式安裝方式:

  • 一唆阿、先創(chuàng)建存放離線包的目錄并進入
  • 二燥筷、通過wget命令從官網(wǎng)拉取源碼包
  • 三箩祥、解壓拉取下來的源碼包并編譯
  • 四、如若編譯報錯則需要安裝相關(guān)的依賴包
[root@localhost]# mkdir /soft/tools && mkdir /soft/tools/ipvsadm
[root@localhost]# cd /soft/tools/ipvsadm
[root@localhost]# wget https://kernel.org/pub/linux/utils/kernel/ipvsadm/ipvsadm-1.31.tar.gz
[root@localhost]# tar -xzvf ipvsadm-1.31.tar.gz
[root@localhost]# cd ipvsadm-1.31
[root@localhost]# make && make install
# 編譯報錯請執(zhí)行下述命令安裝依賴包
yum install -y popt-static kernel-devel make gcc openssl-devel lftplibnl* popt* openssl-devel lftplibnl* popt* libnl* libpopt* gcc*

②創(chuàng)建一個內(nèi)核的軟鏈接肆氓,提供給ipvsadm工具操作內(nèi)核中的ip_vs模塊:

[root@localhost]# ln -s /usr/src/kernels/3.10.0-862.el7.x86_64/ /usr/src/linux

如果你不清楚內(nèi)核的版本袍祖,可以通過uname -r查看,創(chuàng)建對應內(nèi)核版本的軟鏈接谢揪。


③檢查ipvsadm是否安裝成功:

[root@localhost]# ipvsadm
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
.......

在任意位置輸入ipvsadm命令蕉陋,如果出現(xiàn)如上提示代表安裝成功捐凭。


ipvsadm安裝成功后,主體文件位置:

  • 離線安裝的情況下凳鬓,所有主體文件都會在解壓后的目錄中茁肠。
  • 通過yum命令在線安裝的情況下,各主體文件的所在位置:
    • 主程序:/usr/sbin/ipvsadm
    • 規(guī)則保存工具:/usr/sbin/ipvsadm-save
    • 規(guī)則重載工具:/usr/sbin/ipvsadm-restore
    • 配置文件:/etc/sysconfig/ipvsadm-config
    • ipvs調(diào)度規(guī)則文件:/etc/sysconfig/ipvsadm

3.3.2缩举、ipvsadm指令大全

? ?ipvsadmLVS工作在用戶空間的管理工具垦梆,可以通過它管理工作在內(nèi)核空間的ip_vsipvsadm的所有操作指令大體可分為三類:

  • 對于虛擬服務器VIP的增蚁孔、刪奶赔、改指令惋嚎。
  • 對于真實服務器RS的增杠氢、刪、改指令另伍。
  • 對于LVS自身的操作與查看指令鼻百。

用法如下:

ipvsadm [option] [value] ....

ipvsadm的參數(shù)選項有很多,如下:

  • -h(--help):查看命令的幫助信息摆尝,列出ipvsadm的所有指令與參數(shù)温艇。
  • -A(--add service):在VIP服務器列表中添加一條新的虛擬服務器記錄。
  • -a(--add server):在RS服務器列表中添加一條新的真實服務器記錄堕汞。
  • -t(--tcp-service):代表對外提供TCP服務勺爱。
  • -u(--udp-service):代表對外提供UDP服務。
  • -r(--real-server):表示真實服務器的IP地址讯检。
  • -s(--scheduler):代表目前服務器列表使用何種調(diào)度算法琐鲁。
  • -w(--weight):為每個RS節(jié)點配置權(quán)重值。
  • -m(--masquerading):指定LVS的工作模式為NAT模式人灼。
  • -g(--gatewaying):指定LVS的工作模式為DR模式围段。
  • -i(--ipip):指定LVS的工作模式為TUN模式。
  • -6(--IPv6):指定LVS支持IPv6類型的IP訪問投放。
  • -E(--edit-service):編輯VIP列表中的一條虛擬服務器記錄奈泪。
  • -D(--delete-service):刪除VIP列表中一條虛擬服務器記錄。
  • -C(--clear):清空VIP列表中的所有虛擬服務器記錄灸芳。
  • -R(--restore):恢復VIP列表已配置的規(guī)則涝桅。
  • -S(--save):將VIP列表中配置好的規(guī)則保存到指定文件中。
  • -d(--delete-server):刪除一個VIP中的某條真實服務器記錄烙样。
  • -L|-l(--list):顯示VIP服務器列表冯遂。
  • -n(--numberic):以數(shù)字形式輸出IP地址與端口。
  • -stats:輸出LVS自身的流量統(tǒng)計信息误阻。
  • -rete:輸出LVS流量的出入速率信息债蜜。
  • -Z(--zero):清空LVS統(tǒng)計的所有信息晴埂。
  • .......

3.3.3、LVS-DR模式實操

①準備工作寻定,準備三臺Linux儒洛,所有的服務器都需要關(guān)閉防火墻以及selinux

  • 192.168.12.129:作為director狼速,部署LVS琅锻。
  • 192.168.12.130:作為真實服務器RS1,部署后端服務向胡。
  • 192.168.12.131:作為真實服務器RS2恼蓬,部署后端服務。

②在LVS所在的Linux網(wǎng)卡上綁定VIP(需要根據(jù)機器的網(wǎng)卡類型綁定):

[root@localhost]# ip addr add dev ens33 192.168.12.111/32

上述中僵芹,我的網(wǎng)卡為ens33处硬,并綁定VIP:192.168.12.111/32


③為了方便操作拇派,我們把一些操作指令編寫成一個lvs-dr.sh腳本荷辕,如下:

[root@localhost]# vi /soft/scripts/lvs/lvs-dr.sh

#!/bin/sh
# 指定安裝后的ipvsadm主程序位置
adm=/soft/tools/ipvsadm/ipvsadm-1.31/ipvsadm
# 先清除LVS之前配置好的所有規(guī)則
$adm -C
# 在VIP列表中添加一條虛擬服務器記錄,調(diào)度算法會輪詢
$adm -A -t 192.168.12.111:80 -s rr
# 在前面添加的VIP記錄上新增兩條真實服務器記錄件豌,工作模式為DR
$adm -a -t 192.168.12.111:80 -r 192.168.12.130 -g
$adm -a -t 192.168.12.111:80 -r 192.168.12.131 -g
# 將配置好的規(guī)則保存在文件中
$adm -S > /etc/sysconfig/ipvsadm
# 開啟路由轉(zhuǎn)發(fā)功能
echo 1 > /proc/sys/net/ipv4/ip_forward

④編寫的腳本文件需要更改編碼格式疮方,并賦予執(zhí)行權(quán)限,否則可能執(zhí)行失敿胪:

[root@localhost]# vi /soft/scripts/lvs/lvs-dr.sh

:set fileformat=unix # 在vi命令里面執(zhí)行骡显,修改編碼格式
:set ff # 查看修改后的編碼格式

[root@localhost]# chmod +x /soft/scripts/lvs/lvs-dr.sh

⑤執(zhí)行lvs_dr.sh腳本并查看配置后的結(jié)果:

[root@localhost]# ./soft/scripts/lvs/lvs-dr.sh
[root@localhost]# ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.12.111:80 rr
  -> 192.168.12.130:80            Route   1      0          0         
  -> 192.168.12.131:80            Route   1      0          0

從上面的結(jié)果中可以看出,我們添加了一條192.168.12.111:80VIP記錄曾掂,采用的調(diào)度算法為RR輪詢算法惫谤,并且在該VIP記錄下還添加了兩條真實服務器RIP記錄。不過由于目前還未開始測試遭殉,因此后面LVS的統(tǒng)計信息都為0石挂。


⑥配置第一臺RS真實服務器:192.168.12.130,首先可以在上面安裝Nginx

可以通過yum install -y nginx在線安裝险污。
也可以參考之前文章《Nginx-環(huán)境搭建》中的離線安裝方式痹愚。


⑦為RS真實服務器綁定VIPDR模式中的LVS、RS必須要求綁定同一個VIP)蛔糯,但需要注意的是:RS節(jié)點的VIP一定要綁在lo口上拯腮,不要綁在ens33、eth0等這類網(wǎng)卡上:

[root@localhost]# ip addr add dev lo 192.168.12.111/32

⑧將RS節(jié)點上需執(zhí)行的一些命令編寫成lvs-dr-rs.sh腳本:

[root@localhost]# vi /soft/scripts/lvs/lvs-dr_rs.sh

#!/bin/sh
# 改寫一下Nginx的默認的index.html首頁內(nèi)容
echo "I is Real Server 001" > /soft/nginx/html/index.html
# 忽略ARP廣播蚁飒,保持ARP靜默动壤,確保請求VIP時,能夠首先落入到LVS上
echo 1 >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo 1 >/proc/sys/net/ipv4/conf/all/arp_ignore
# 開啟精確匹配IP回包機制淮逻,確保RS處理完請求后能夠直接響應數(shù)據(jù)給客戶端
echo 2 >/proc/sys/net/ipv4/conf/lo/arp_announce
echo 2 >/proc/sys/net/ipv4/conf/all/arp_announce
# 啟動nginx(由于沒做反向代理琼懊,也未更改配置文件阁簸,直接啟動即可)
/soft/nginx/sbin/nginx

然后重復上述過程,配置第二臺RS節(jié)點哼丈,也可以直接克隆一次启妹,但第二個RS節(jié)點上,稍微將上述腳本第一條指令中的I is Real Server 001改為I is Real Server 002醉旦,這樣做的好處在于:待會兒測試的時候方便觀察效果饶米。


⑨為兩個RS節(jié)點的腳本文件開放執(zhí)行權(quán)限并執(zhí)行:

[root@localhost]# vi /soft/scripts/lvs/lvs-dr-rs.sh

:set fileformat=unix # 在vi命令里面執(zhí)行,修改編碼格式
:set ff # 查看修改后的編碼格式

[root@localhost]# chmod +x /soft/scripts/lvs/lvs-dr-rs.sh
[root@localhost]# ./soft/scripts/lvs/lvs-dr-rs.sh

⑩用一臺新的機器充當客戶端车胡,測試LVS-DR模式的分發(fā)效果檬输,可以在Windows瀏覽器訪問VIP測試,也可直接通過curl命令測試:

[root@localhost]# curl http://192.168.12.111
I is Real Server 001
[root@localhost]# curl http://192.168.12.111
I is Real Server 002
[root@localhost]# curl http://192.168.12.111
I is Real Server 001
[root@localhost]# curl http://192.168.12.111
I is Real Server 002
[root@localhost]# curl http://192.168.12.111
I is Real Server 001
.......

觀察如上結(jié)果匈棘,很明顯可看出LVS在根據(jù)我們配置好的RR輪詢算法進行請求分發(fā)丧慈。


? ?整個LVS-DR模式實驗測試到此便告一段落了,但實際過程中一般很少用ipvsadm去操作LVS羹饰,因為這種方式步驟比較繁雜伊滋,并且沒有健康檢查機制碳却,也就是說當某個RS節(jié)點宕機后队秩,LVS依舊會為其分發(fā)請求。
? ?正是由于不方便管理以及沒有健康檢查機制昼浦,因此實際情況下都是采用Keepalived去管理LVS的馍资,其實Keepalived最開始就是為LVS專門研發(fā)的,用于快捷管理关噪、確保高可用以及健康檢查的工具鸟蟹。

3.4、結(jié)合Keepalived管理LVS

? ?Keepalived《Nginx-高可用》篇章中初次提到了它使兔,我們使用它對Nginx實現(xiàn)了最基本的宕機重啟以及VIP漂移的高可用機制建钥,因此對于Keepalived基本概念與環(huán)境構(gòu)建過程,在本文中則不再重復贅述虐沥,可直接參考之前的內(nèi)容熊经,在這里重點講一下如何通過Keepalived管理LVS

通過Keepalived管理LVS其實還是配置之前的keepalived.conf文件欲险。
環(huán)境:四臺Linux镐依,其中兩臺作為RS,一臺作為LVS主天试,另一臺作為LVS從槐壳。

首先根據(jù)之前說過的Keepalived安裝步驟,先在LVS主喜每、從兩臺機器上安裝Keepalived务唐,然后開始配置keepalived.conf文件雳攘。


LVS主節(jié)點上的keepalived.conf文件:

# -------全局配置---------
global_defs {
    # 自帶的郵件提醒服務,建議用獨立的監(jiān)控或第三方SMTP枫笛,也可選擇配置郵件發(fā)送来农。
    notification_email {
        root@localhost
    }
    notification_email_from root@localhost
    smtp_server localhost
    smtp_connect_timeout 30
    # 高可用集群主機身份標識(集群中主機身份標識名稱不能重復,建議配置成本機IP)
    router_id 192.168.12.129 
}

# -------Keepalived自身實例配置---------
# 定義虛擬路由崇堰,VI_1為虛擬路由的標示符(可自定義名稱)
vrrp_instance VI_1 {
    # 當前節(jié)點的身份標識:用來決定主從(MASTER為主機沃于,BACKUP為從機)
    state MASTER
    # 綁定虛擬IP的網(wǎng)絡接口,根據(jù)自己的機器的網(wǎng)卡配置
    interface ens33 
    # 虛擬路由的ID號海诲,主從兩個節(jié)點設置必須一樣
    virtual_router_id 121
    # 填寫本機IP
    mcast_src_ip 192.168.12.129
    # 節(jié)點權(quán)重優(yōu)先級繁莹,主節(jié)點要比從節(jié)點優(yōu)先級高
    priority 100
    # 優(yōu)先級高的設置nopreempt,解決異程蒯#恢復后再次搶占造成的腦裂問題
    nopreempt
    # 組播信息發(fā)送間隔咨演,兩個節(jié)點設置必須一樣,默認1s(類似于心跳檢測)
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    
    virtual_ipaddress {
        # 虛擬IP(VIP)蚯斯,也可擴展薄风,可配置多個。
        192.168.12.111/32
    }
}

# -------LVS集群配置---------
# 配置一個虛擬服務器(VIP)拍嵌,可配置多個組成VIP集群
virtual_server 192.168.12.129 80 {
    # 對每個RS健康檢查的時間間隔
    delay_loop 6
    # 當前VIP所采用的分發(fā)調(diào)度算法:RR輪詢
    lb_algo rr
    # 當前LVS采用的工作模式:DR直接路由
    lb_kind DR
    # 同一個客戶端的請求在多少秒內(nèi)都發(fā)往同一臺RS服務器
    persistence_timeout 50
    # 當前LVS所采用的通信協(xié)議
    protocol TCP
    # 定義備用節(jié)點遭赂,當所有RS都故障時,用sorry_server來響應客戶端
    sorry_server 127.0.0.1 80
    
    # 配置第一臺RS真實服務器的信息
    real_server 192.168.12.130 80 {
        # 設定權(quán)重值横辆,默認為1
        weight 1
        # 配置TCP信息
        TCP_CHECK {
            # 連接的端口號
            connect_port 80    
            # 連接超時時間
            connect_timeout 3
            # 請求失敗后的重試次數(shù)
            nb_get_retry 3
            # 重試的超時時間
            delay_before_retry 3
        }
    }

    # 配置第二臺RS真實服務器的信息
    real_server 192.168.12.131 80 {
        # 設定權(quán)重值撇他,默認為1
        weight 1
        # 配置TCP信息
        TCP_CHECK {
            # 連接的端口號
            connect_port 80    
            # 連接超時時間
            connect_timeout 3
            # 請求失敗后的重試次數(shù)
            nb_get_retry 3
            # 重試的超時時間
            delay_before_retry 3
        }
    }
}

觀察上述配置文件,其實與之前的并未有太大區(qū)別狈蚤,僅僅只是多增加了一個virtual_server模塊困肩,而后在內(nèi)配置了LVS的規(guī)則,以及兩個真實服務器節(jié)點real_server脆侮。當然锌畸,LVS作為整個系統(tǒng)請求分發(fā)的“咽喉要塞”,自然也要確保其高可用的特性靖避,因此可再為其配置一臺從機潭枣,確保當前機器發(fā)生意外不能正常工作時,依舊能夠確保整個系統(tǒng)的可用性筋蓖。


LVS從節(jié)點上的keepalived.conf文件:

# -------Keepalived全局配置---------
global_defs {
    # 自帶的郵件提醒服務卸耘,建議用獨立的監(jiān)控或第三方SMTP,也可選擇配置郵件發(fā)送粘咖。
    notification_email {
        root@localhost
    }
    notification_email_from root@localhost
    smtp_server localhost
    smtp_connect_timeout 30
    # 高可用集群主機身份標識(集群中主機身份標識名稱不能重復蚣抗,建議配置成本機IP)
    router_id 192.168.12.132 
}

# -------Keepalived自身實例配置---------
# 定義虛擬路由,VI_1為虛擬路由的標示符(可自定義名稱)
vrrp_instance VI_1 {
    # 當前節(jié)點的身份標識:用來決定主從(MASTER為主機,BACKUP為從機)
    state BACKUP
    # 綁定虛擬IP的網(wǎng)絡接口翰铡,根據(jù)自己的機器的網(wǎng)卡配置
    interface ens33 
    # 虛擬路由的ID號钝域,主從兩個節(jié)點設置必須一樣
    virtual_router_id 121
    # 填寫本機IP
    mcast_src_ip 192.168.12.132
    # 節(jié)點權(quán)重優(yōu)先級,主節(jié)點要比從節(jié)點優(yōu)先級高
    priority 90
    # 優(yōu)先級高的設置nopreempt锭魔,解決異忱ぃ恢復后再次搶占造成的腦裂問題
    nopreempt
    # 組播信息發(fā)送間隔,兩個節(jié)點設置必須一樣迷捧,默認1s(類似于心跳檢測)
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }

    virtual_ipaddress {
        # 虛擬IP(VIP)织咧,也可擴展,可配置多個漠秋。
        192.168.12.111/32
    }
}

# -------LVS集群配置---------
# 配置一個虛擬服務器(VIP)笙蒙,可配置多個組成VIP集群
virtual_server 192.168.12.129 80 {
    # 對每個RS健康檢查的時間間隔
    delay_loop 6
    # 當前VIP所采用的分發(fā)調(diào)度算法:RR輪詢
    lb_algo rr
    # 當前LVS采用的工作模式:DR直接路由
    lb_kind DR
    # 同一個客戶端的請求在多少秒內(nèi)都發(fā)往同一臺RS服務器
    persistence_timeout 50
    # 當前LVS所采用的通信協(xié)議
    protocol TCP
    # 定義備用節(jié)點,當所有RS都故障時庆锦,用sorry_server來響應客戶端
    sorry_server 127.0.0.1 80
    
    # 配置第一臺RS真實服務器的信息
    real_server 192.168.12.130 80 {
        # 設定權(quán)重值捅位,默認為1
        weight 1
        # 配置TCP信息
        TCP_CHECK {
            # 連接的端口號
            connect_port 80    
            # 連接超時時間
            connect_timeout 3
            # 請求失敗后的重試次數(shù)
            nb_get_retry 3
            # 重試的超時時間
            delay_before_retry 3
        }
    }

    # 配置第二臺RS真實服務器的信息
    real_server 192.168.12.131 80 {
        # 設定權(quán)重值,默認為1
        weight 1
        # 配置TCP信息
        TCP_CHECK {
            # 連接的端口號
            connect_port 80    
            # 連接超時時間
            connect_timeout 3
            # 請求失敗后的重試次數(shù)
            nb_get_retry 3
            # 重試的超時時間
            delay_before_retry 3
        }
    }
}

兩個RS節(jié)點還是按照之前的方式配置搂抒,然后分別啟動LVS主艇搀、從機器上的keepalived服務以及RS節(jié)點上的Nginx服務,接著來測試結(jié)果看看:

[root@localhost]# curl http://192.168.12.111
I is Real Server 001
[root@localhost]# curl http://192.168.12.111
I is Real Server 002
[root@localhost]# curl http://192.168.12.111
I is Real Server 001
[root@localhost]# curl http://192.168.12.111
I is Real Server 002
.......

測試結(jié)果與之前通過ipvsadm工具管理的LVS相同求晶,而通過keepalived之后焰雕,所有配置可以統(tǒng)一化管理,同時還能對每個VIP下的真實服務器節(jié)點進行健康檢測誉帅,并且還能對LVS實現(xiàn)高可用淀散,因此實際生產(chǎn)環(huán)境中,當項目使用LVS時蚜锨,一般都會采用keepalived管理。

當然慢蜓,對于LVS的高可用特性亚再、RS節(jié)點的健康檢測機制,大家可以自行停掉對應的機器晨抡,然后測試觀察結(jié)果(也包括其他的工作模式也可以自行測試氛悬,但一般最常用的就是DR模式)。

四耘柱、億級吞吐第四戰(zhàn)-Nginx與Gateway網(wǎng)關(guān)高可用

? ?前面過程中簡單的對LVS-DR模式進行了簡單實驗如捅,其中我們通過Nginx作為WEB服務,但實際系統(tǒng)中调煎,Nginx是提供反向代理的作用镜遣,它并不處理客戶端的請求,最終的業(yè)務處理還是交由后端的Tomcat處理士袄。

4.1悲关、Nginx高可用設計

? ?前面實驗中基于LVSNginx實現(xiàn)了水平集群拓展谎僻,因此讓整個系統(tǒng)擁有了更高的并發(fā)處理能力,而對于每個Nginx節(jié)點寓辱,也可以對其實現(xiàn)高可用艘绍,具體過程可參考:《全解Nginx篇-Keepalived實現(xiàn)Nginx高可用》

Nginx熱備

相較而言秫筏,如果僅是為了容災诱鞠,都為每臺Nginx配置一臺備機,那么硬件成本會直線增高这敬,因此通過KeepalivedNginx實現(xiàn)宕機重啟就夠了般甲,無需再為其實現(xiàn)VIP漂移,畢竟帶來的收益遠小于硬件成本鹅颊,但如若系統(tǒng)要保障更高程度上的高可用敷存,那么可以再為每個Nginx節(jié)點配置從機。

如若要保證更高的可用性堪伍,那依舊可以為每個Nginx節(jié)點配置從節(jié)點容災锚烦。

4.1.1、為Nginx配置從機后的接入層架構(gòu)

配置從機

由于每個Nginx都配置了從機帝雇,因此每個Nginx節(jié)點都具備容災能力涮俄,因此可以讓每臺Nginx負責不同WEB服務器的請求分發(fā),這樣做的好處在于:能夠一定程度上提升些許性能尸闸。

4.1.2彻亲、不為Nginx配置從機的接入層架構(gòu)

不配從機

但如若不為Nginx配置從機,那每個Nginx節(jié)點的不具備很強的容災能力吮廉,再通過上述的那種方式配置反向代理苞尝,就會存在問題,因為如果一個節(jié)點宕機宦芦,會導致該節(jié)點所代理的Web-server節(jié)點都不可用宙址。

因此如果不給Nginx配置從機,那么可以將每個Nginx的反向代理调卑,都配置成所有Web-sever的列表抡砂,這樣就算一臺Nginx節(jié)點宕機,也不會影響系統(tǒng)的正常運轉(zhuǎn)恬涧。

4.2注益、Gateway網(wǎng)關(guān)高可用集群

? ?前面Nginx負責代理的是普通Web-server,但大型網(wǎng)站必然會做業(yè)務切割溯捆,對于分布式/微服務架構(gòu)而言丑搔,一般會劃分出多個子服務,但服務太多不方便相互之間調(diào)用,并且也不方便對外提供低匙,因此在微服務中都會存在一個服務網(wǎng)關(guān)旷痕,由網(wǎng)關(guān)統(tǒng)一對外提供接口,目前微服務架構(gòu)中主流的網(wǎng)關(guān)技術(shù)是Gateway(在早期的SOA架構(gòu)中是服務總線)顽冶。
? ?因此對于分布式/微服務系統(tǒng)而言欺抗,Nginx代理的實則為網(wǎng)關(guān)節(jié)點,由于網(wǎng)關(guān)作為整個后端系統(tǒng)的流量入口强重,因此必須要保證其高可用绞呈,也就是說會對其做集群部署,也就是在多臺服務器上部署網(wǎng)關(guān)(結(jié)構(gòu)完全相同)间景,然后Nginx的配置中佃声,將upstream配置成每個Gateway節(jié)點的IP+Port即可,最終整個接入層的架構(gòu)如下:

接入層架構(gòu)

在這套架構(gòu)中倘要,CDN至少能夠為系統(tǒng)分擔一半的流量圾亏,而LVS作為接入層的“首個守關(guān)將”,它的并發(fā)性是極強的封拧,幾乎是Nginx的十倍以上志鹃,那假設此時LVS每秒的并發(fā)吞吐量為20W,為整個系統(tǒng)單日接入上億泽西、十憶曹铃、百億流量都行。

五捧杉、千臺實例構(gòu)建日均百億流量架構(gòu)

? ?這小節(jié)主要是為了拓展一下陕见,類似于yy階段,說簡單一點就是讓諸位在吹牛逼的時候多點談資味抖,不過在講述之前评甜,首先需要搞懂幾個平臺常用的數(shù)據(jù)指標:

  • PV:平臺頁面被瀏覽/點擊的總次數(shù),每次訪問或刷新都會計入一次PV非竿。
  • UV:一天內(nèi)訪問平臺的總用戶數(shù)(以客戶端cookie作為計算依據(jù))蜕着。
  • IP:一天內(nèi)訪問平臺的獨立IP總數(shù)(以客戶端IP地址作為計算依據(jù))。
  • QPS:平臺一秒內(nèi)接收到的請求總數(shù)红柱。
  • TPS:平臺一秒內(nèi)接收到的事務總數(shù)。
  • RPS:平臺每秒能夠處理的請求總數(shù)(吞吐量)蓖乘。
  • RT:執(zhí)行一個請求從訪問到響應的總體時間锤悄。
  • 最大并發(fā)數(shù):平臺能夠在同一時刻同時處理的最大請求數(shù)。
  • 單日流量:一天內(nèi)平臺收到的請求總數(shù)嘉抒。

QPS零聚、TPS的區(qū)別:TPS中的事務是指客戶端請求、服務端處理、服務端響應 這個過程隶症,一個事務是指客戶端訪問一次頁面政模,但QPS是每次對服務器發(fā)起請求都會計入一次,而訪問一個頁面往往會產(chǎn)生多個請求蚂会,因此一個TPS中往往會包含多個QPS淋样。

OK~,對于上述的些許指標有了簡單了解后胁住,接著來聊聊百億架構(gòu)的事情趁猴,在思考該問題之前,首先需要計算出一個關(guān)鍵指標:峰值QPS彪见,因為峰值QPS代表著系統(tǒng)將面臨的最高并發(fā)儡司,峰值QPS計算公式如下:

峰值QPS = (單日流量 * 80%) / (60 * 60 * 24 * 20%)
由于每天80%的訪問集中在20%的時間里,這20%時間叫做峰值時間余指,因此只需要用單日流量去計算出這20%中的QPS捕犬,那么就能的到單日峰值QPS

在有些地方并非用單日流量作為計算條件酵镜,而是單日的PV總值碉碉,但在咱們這里就用現(xiàn)有的百億單日流量 作為計算的基礎條件,如下:

(10000000000*0.8)/(60*60*24*0.2)≈462963

通過如上公式計算笋婿,可以得知大概的峰值QPS46.3W左右誉裆。的到峰值QPS后,就可以根據(jù)該值計算出每個層面的服務節(jié)點大概數(shù)量了缸濒,但首先要根據(jù)峰值QPS計算出每個節(jié)點的單機QPS上限足丢,以及峰值QPS情況下會造成的最大并發(fā)數(shù):

①根據(jù)峰值QPS計算出系統(tǒng)流量的最大并發(fā)數(shù):
計算公式:QPS / (一秒 / 平均響應時間)
假設此時系統(tǒng)中每個請求的平均響應時間為500ms,那么根據(jù)公式計算出系統(tǒng)在同一時間會出現(xiàn)流量的最大并發(fā)數(shù):462963/(1/0.5)=231481.5庇配。

②計算出每個層面單機QPS處理的上限值:
計算公式:節(jié)點最大并發(fā)數(shù) * (一秒 / 請求處理時間)
假設一個節(jié)點處理每個請求的平均時間為200ms斩跌,最大并發(fā)數(shù)為800,那么該節(jié)點的單機QPS上限為4000捞慌。

得到了流量的最大并發(fā)數(shù)以及單機QPS上限后耀鸦,那么就可以根據(jù)這兩個值去計算每個層面需要的節(jié)點數(shù)量了,可以通過最大并發(fā)數(shù)計算啸澡,也可以通過單機的QPS上限計算:

  • 通過最大并發(fā)數(shù)計算:節(jié)點數(shù)量 = 流量最大并發(fā)數(shù) / 節(jié)點最大并發(fā)數(shù)袖订。
  • 通過單機QPS上限計算:節(jié)點數(shù)量 = 峰值QPS / 單機QPS上限。

通過第二種方式計算出來的節(jié)點數(shù)量是最準確的嗅虏,畢竟每個層面處理請求的時間并不同洛姑,比如MySQL處理一個請求需要200ms,而Redis可能只需10ms甚至更低皮服,因但為了簡單楞艾,咱們就通過第一種方式去計算每個層面的節(jié)點數(shù)量(畢竟只是模擬):

  • 接入層:
    • LVS一主一備(LVS-DR的最大連接數(shù)上限大概在30-50W
      • 但為了容錯需要再搭建一個容災集群参咙,因此LVS共計四臺。
    • Nginx(單節(jié)點并發(fā)連接數(shù)5W左右硫眯,線上做反向代理實際3W左右)
      • 231481.5/30000≈8巧骚,Nginx大概需要8臺嗤攻。
    • Gateway網(wǎng)關(guān)由于不做具體的業(yè)務處理为鳄,默認最大連接數(shù)在1W左右
      • 231481.5/10000≈24孟害,Gateway網(wǎng)關(guān)大概需要24臺左右。
  • 系統(tǒng)服務層:
    • SpringBoot內(nèi)嵌的Tomcat:默認最大連接數(shù)也是1W谆刨,但由于要處理業(yè)務請求塘娶,因此線上能達到2000左右已算極致
    • 231481.5/2000≈116Tomcat大概需要116臺左右痊夭。
    • 還要考慮到微服務的生態(tài)圈刁岸,服務不可能單獨部署,注冊中心她我、服務保護虹曙、系統(tǒng)監(jiān)控、定時調(diào)度番舆、授權(quán)中心酝碳、CI/CD自動化等.....
    • 因此系統(tǒng)服務層的完整構(gòu)建,至少需要大概180+臺左右的實例恨狈。
  • 中間件層:
    • 緩存中間件Redis疏哗,線上單機性能大概在5W左右的最大連接數(shù)。
      • 231481.5/50000≈5禾怠,但由于緩存的特殊性返奉,至少需部署20臺以上。
    • 分庫分表中間件:8臺左右吗氏。
    • ELK分布式日志收集10臺左右芽偏。
    • Kafka、RabbitMQ消息中間件共計30臺左右弦讽。
    • ElasticSearch搜索中間件共計30臺左右污尉。
    • ..........
  • 存儲層:
    • Mongodb大概需要30臺左右。
    • MySQLTomcat的數(shù)量大致對應往产,100臺左右(有些庫需要水平集群)被碗。
    • 大數(shù)據(jù)CDH全家桶50臺以上。
    • FastDFS分布式文件存儲共計20臺左右仿村。
  • .......

? ?其中除開Redis外蛮放,其他實例都可采用“一物理機四實例”的方式部署,但想要構(gòu)建出整個完整的架構(gòu)奠宜,估摸著需要幾千臺上萬實例包颁,幾千臺物理機器。當然压真, 上述的節(jié)點數(shù)量并不作為生產(chǎn)環(huán)境下的的推薦娩嚼,但計算方式是相同的,實際情況下可先計算出峰值QPS滴肿,然后再根據(jù)峰值QPS去與每個層面上的單機QPS上限做計算岳悟,從而得到準確的節(jié)點數(shù)量。

? ?但實際情況下泼差,還需要參考物理服務器的內(nèi)存贵少、CPU、磁盤的配置堆缘,還需要依據(jù)項目的業(yè)務類型滔灶、開發(fā)人員的技術(shù)水平去綜合性考慮具體要使用多少個節(jié)點,因為性能好的超級服務器再加一定程度上的性能調(diào)優(yōu)吼肥,能夠極大程度上去節(jié)省服務器成本录平。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市缀皱,隨后出現(xiàn)的幾起案子斗这,更是在濱河造成了極大的恐慌,老刑警劉巖啤斗,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件表箭,死亡現(xiàn)場離奇詭異,居然都是意外死亡钮莲,警方通過查閱死者的電腦和手機免钻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來臂痕,“玉大人伯襟,你說我怎么就攤上這事∥胀” “怎么了姆怪?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長澡绩。 經(jīng)常有香客問我稽揭,道長,這世上最難降的妖魔是什么肥卡? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任溪掀,我火速辦了婚禮,結(jié)果婚禮上步鉴,老公的妹妹穿的比我還像新娘揪胃。我一直安慰自己璃哟,他們只是感情好,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布喊递。 她就那樣靜靜地躺著随闪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪骚勘。 梳的紋絲不亂的頭發(fā)上铐伴,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天,我揣著相機與錄音俏讹,去河邊找鬼当宴。 笑死,一個胖子當著我的面吹牛泽疆,可吹牛的內(nèi)容都是我干的户矢。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼于微,長吁一口氣:“原來是場噩夢啊……” “哼逗嫡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起株依,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤驱证,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后恋腕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抹锄,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年荠藤,在試婚紗的時候發(fā)現(xiàn)自己被綠了伙单。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡哈肖,死狀恐怖吻育,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情淤井,我是刑警寧澤布疼,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站币狠,受9級特大地震影響游两,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜漩绵,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一贱案、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧止吐,春花似錦宝踪、人聲如沸侨糟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽粟害。三九已至,卻和暖如春颤芬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背套鹅。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工站蝠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人卓鹿。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓菱魔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親吟孙。 傳聞我的和親對象是個殘疾皇子澜倦,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容