2018-06-08

一藐俺、微服務(wù)介紹

1. 什么是微服務(wù)

在介紹微服務(wù)時,首先得先理解什么是微服務(wù)泥彤,顧名思義欲芹,微服務(wù)得從兩個方面去理解,什么是"微"吟吝、什么是"服務(wù)"菱父, 微 狹義來講就是體積小、著名的"2 pizza 團隊"很好的詮釋了這一解釋(2 pizza 團隊最早是亞馬遜 CEO Bezos提出來的剑逃,意思是說單個服務(wù)的設(shè)計浙宜,所有參與人從設(shè)計、開發(fā)蛹磺、測試粟瞬、運維所有人加起來 只需要2個披薩就夠了 )。 而所謂服務(wù)萤捆,一定要區(qū)別于系統(tǒng)裙品,服務(wù)一個或者一組相對較小且獨立的功能單元,是用戶可以感知最小功能集俗或。

2. 微服務(wù)由來

微服務(wù)最早由Martin Fowler與James Lewis于2014年共同提出市怎,微服務(wù)架構(gòu)風格是一種使用一套小服務(wù)來開發(fā)單個應(yīng)用的方式途徑,每個服務(wù)運行在自己的進程中辛慰,并使用輕量級機制通信区匠,通常是HTTP API,這些服務(wù)基于業(yè)務(wù)能力構(gòu)建昆雀,并能夠通過自動化部署機制來獨立部署辱志,這些服務(wù)使用不同的編程語言實現(xiàn),以及不同數(shù)據(jù)存儲技術(shù)狞膘,并保持最低限度的集中式管理揩懒。

3. 為什么需要微服務(wù)?

在傳統(tǒng)的IT行業(yè)軟件大多都是各種獨立系統(tǒng)的堆砌挽封,這些系統(tǒng)的問題總結(jié)來說就是擴展性差已球,可靠性不高,維護成本高辅愿。到后面引入了SOA服務(wù)化智亮,但是,由于 SOA 早期均使用了總線模式点待,這種總線模式是與某種技術(shù)棧強綁定的阔蛉,比如:J2EE。這導(dǎo)致很多企業(yè)的遺留系統(tǒng)很難對接癞埠,切換時間太長状原,成本太高聋呢,新系統(tǒng)穩(wěn)定性的收斂也需要一些時間。最終 SOA 看起來很美颠区,但卻成為了企業(yè)級奢侈品削锰,中小公司都望而生畏。

3.1 最期的單體架構(gòu)帶來的問題

單體架構(gòu)在規(guī)模比較小的情況下工作情況良好毕莱,但是隨著系統(tǒng)規(guī)模的擴大器贩,它暴露出來的問題也越來越多,主要有以下幾點:

1.復(fù)雜性逐漸變高

  • 比如有的項目有幾十萬行代碼朋截,各個模塊之間區(qū)別比較模糊藕甩,邏輯比較混亂恃慧,代碼越多復(fù)雜性越高淑履,越難解決遇到的問題棱诱。

2.技術(shù)債務(wù)逐漸上升

  • 公司的人員流動是再正常不過的事情,有的員工在離職之前饲宿,疏于代碼質(zhì)量的自我管束厦酬,導(dǎo)致留下來很多坑,由于單體項目代碼量龐大的驚人瘫想,留下的坑很難被發(fā)覺仗阅,這就給新來的員工帶來很大的煩惱,人員流動越大所留下的坑越多国夜,也就是所謂的技術(shù)債務(wù)越來越多减噪。

3.部署速度逐漸變慢

  • 這個就很好理解了,單體架構(gòu)模塊非常多车吹,代碼量非常龐大筹裕,導(dǎo)致部署項目所花費的時間越來越多,曾經(jīng)有的項目啟動就要一二十分鐘窄驹,這是多么恐怖的事情啊朝卒,啟動幾次項目一天的時間就過去了,留給開發(fā)者開發(fā)的時間就非常少了乐埠。

4.阻礙技術(shù)創(chuàng)新

  • 比如以前的某個項目使用struts2寫的抗斤,由于各個模塊之間有著千絲萬縷的聯(lián)系,代碼量大丈咐,邏輯不夠清楚瑞眼,如果現(xiàn)在想用spring mvc來重構(gòu)這個項目將是非常困難的,付出的成本將非常大棵逊,所以更多的時候公司不得不硬著頭皮繼續(xù)使用老的struts架構(gòu)伤疙,這就阻礙了技術(shù)的創(chuàng)新。

5.無法按需伸縮

  • 比如說電影模塊是CPU密集型的模塊辆影,而訂單模塊是IO密集型的模塊徒像,假如我們要提升訂單模塊的性能花吟,比如加大內(nèi)存、增加硬盤厨姚,但是由于所有的模塊都在一個架構(gòu)下,因此我們在擴展訂單模塊的性能時不得不考慮其它模塊的因素键菱,因為我們不能因為擴展某個模塊的性能而損害其它模塊的性能谬墙,從而無法按需進行伸縮。

3.2 微服務(wù)與單體架構(gòu)區(qū)別

  1. 單體架構(gòu)所有的模塊全都耦合在一塊经备,代碼量大拭抬,維護困難,微服務(wù)每個模塊就相當于一個單獨的項目侵蒙,代碼量明顯減少造虎,遇到問題也相對來說比較好解決。

  2. 單體架構(gòu)所有的模塊都共用一個數(shù)據(jù)庫纷闺,存儲方式比較單一算凿,微服務(wù)每個模塊都可以使用不同的存儲方式(比如有的用redis,有的用mysql等)犁功,數(shù)據(jù)庫也是單個模塊對應(yīng)自己的數(shù)據(jù)庫氓轰。

  3. 單體架構(gòu)所有的模塊開發(fā)所使用的技術(shù)一樣,微服務(wù)每個模塊都可以使用不同的開發(fā)技術(shù)浸卦,開發(fā)模式更靈活署鸡。

image

3.3 微服務(wù)與SOA區(qū)別

微服務(wù),從本質(zhì)意義上看限嫌,還是 SOA 架構(gòu)靴庆。但內(nèi)涵有所不同,微服務(wù)并不綁定某種特殊的技術(shù)怒医,在一個微服務(wù)的系統(tǒng)中炉抒,可以有 Java 編寫的服務(wù),也可以有 Python編寫的服務(wù)稚叹,他們是靠Restful架構(gòu)風格統(tǒng)一成一個系統(tǒng)的端礼。所以微服務(wù)本身與具體技術(shù)實現(xiàn)無關(guān),擴展性強入录。

4. 微服務(wù)本質(zhì)

  1. 微服務(wù)蛤奥,關(guān)鍵其實不僅僅是微服務(wù)本身,而是系統(tǒng)要提供一套基礎(chǔ)的架構(gòu)僚稿,這種架構(gòu)使得微服務(wù)可以獨立的部署凡桥、運行、升級蚀同,不僅如此缅刽,這個系統(tǒng)架構(gòu)還讓微服務(wù)與微服務(wù)之間在結(jié)構(gòu)上“松耦合”啊掏,而在功能上則表現(xiàn)為一個統(tǒng)一的整體。這種所謂的“統(tǒng)一的整體”表現(xiàn)出來的是統(tǒng)一風格的界面衰猛,統(tǒng)一的權(quán)限管理迟蜜,統(tǒng)一的安全策略,統(tǒng)一的上線過程啡省,統(tǒng)一的日志和審計方法娜睛,統(tǒng)一的調(diào)度方式,統(tǒng)一的訪問入口等等卦睹。

  2. 微服務(wù)的目的是有效的拆分應(yīng)用畦戒,實現(xiàn)敏捷開發(fā)和部署 。

  3. 微服務(wù)提倡的理念團隊間應(yīng)該是 inter-operate, not integrate 结序。inter-operate是定義好系統(tǒng)的邊界和接口障斋,在一個團隊內(nèi)全棧,讓團隊自治徐鹤,原因就是因為如果團隊按照這樣的方式組建垃环,將溝通的成本維持在系統(tǒng)內(nèi)部,每個子系統(tǒng)就會更加內(nèi)聚返敬,彼此的依賴耦合能變?nèi)跚绻缦到y(tǒng)的溝通成本也就能降低。

5. 什么樣的項目適合微服務(wù)

微服務(wù)可以按照業(yè)務(wù)功能本身的獨立性來劃分救赐,如果系統(tǒng)提供的業(yè)務(wù)是非常底層的涧团,如:操作系統(tǒng)內(nèi)核、存儲系統(tǒng)经磅、網(wǎng)絡(luò)系統(tǒng)泌绣、數(shù)據(jù)庫系統(tǒng)等等,這類系統(tǒng)都偏底層预厌,功能和功能之間有著緊密的配合關(guān)系阿迈,如果強制拆分為較小的服務(wù)單元,會讓集成工作量急劇上升轧叽,并且這種人為的切割無法帶來業(yè)務(wù)上的真正的隔離苗沧,所以無法做到獨立部署和運行,也就不適合做成微服務(wù)了炭晒。

能不能做成微服務(wù)待逞,取決于四個要素:

  • 小:微服務(wù)體積小网严,2 pizza 團隊识樱。

  • 獨:能夠獨立的部署和運行。

  • 輕:使用輕量級的通信機制和架構(gòu)。

  • 松:為服務(wù)之間是松耦合的怜庸。

6. 微服務(wù)折分與設(shè)計

  1. 從單體式結(jié)構(gòu)轉(zhuǎn)向微服務(wù)架構(gòu)中會持續(xù)碰到服務(wù)邊界劃分的問題:比如当犯,我們有user 服務(wù)來提供用戶的基礎(chǔ)信息,那么用戶的頭像和圖片等是應(yīng)該單獨劃分為一個新的service更好還是應(yīng)該合并到user服務(wù)里呢割疾?如果服務(wù)的粒度劃分的過粗嚎卫,那就回到了單體式的老路;如果過細宏榕,那服務(wù)間調(diào)用的開銷就變得不可忽視了拓诸,管理難度也會指數(shù)級增加。目前為止還沒有一個可以稱之為服務(wù)邊界劃分的標準担扑,只能根據(jù)不同的業(yè)務(wù)系統(tǒng)加以調(diào)節(jié)

  2. 拆分的大原則是當一塊業(yè)務(wù)不依賴或極少依賴其它服務(wù),有獨立的業(yè)務(wù)語義趣钱,為超過2個的其他服務(wù)或客戶端提供數(shù)據(jù)涌献,那么它就應(yīng)該被拆分成一個獨立的服務(wù)模塊。

6.1 微服務(wù)設(shè)計原則

單一職責原則

  • 意思是每個微服務(wù)只需要實現(xiàn)自己的業(yè)務(wù)邏輯就可以了首有,比如訂單管理模塊燕垃,它只需要處理訂單的業(yè)務(wù)邏輯就可以了,其它的不必考慮井联。

服務(wù)自治原則

  • 意思是每個微服務(wù)從開發(fā)卜壕、測試、運維等都是獨立的烙常,包括存儲的數(shù)據(jù)庫也都是獨立的轴捎,自己就有一套完整的流程,我們完全可以把它當成一個項目來對待蚕脏。不必依賴于其它模塊侦副。

輕量級通信原則

  • 首先是通信的語言非常的輕量,第二驼鞭,該通信方式需要是跨語言秦驯、跨平臺的,之所以要跨平臺挣棕、跨語言就是為了讓每個微服務(wù)都有足夠的獨立性译隘,可以不受技術(shù)的鉗制。

接口明確原則

  • 由于微服務(wù)之間可能存在著調(diào)用關(guān)系洛心,為了盡量避免以后由于某個微服務(wù)的接口變化而導(dǎo)致其它微服務(wù)都做調(diào)整固耘,在設(shè)計之初就要考慮到所有情況,讓接口盡量做的更通用词身,更靈活玻驻,從而盡量避免其它模塊也做調(diào)整。

7. 微服務(wù)優(yōu)勢與缺點

7.1 特性

  1. 每個微服務(wù)可獨立運行在自己的進程里;

  2. 一系列獨立運行的微服務(wù)共同構(gòu)建起了整個系統(tǒng)璧瞬;

  3. 每個服務(wù)為獨立的業(yè)務(wù)開發(fā)户辫,一個微服務(wù)一般完成某個特定的功能,比如:訂單管理嗤锉,用戶管理等渔欢;

  4. 微服務(wù)之間通過一些輕量級的通信機制進行通信,例如通過REST API或者RPC的方式進行調(diào)用瘟忱。

7.2 特點

易于開發(fā)和維護

  • 由于微服務(wù)單個模塊就相當于一個項目奥额,開發(fā)這個模塊我們就只需關(guān)心這個模塊的邏輯即可,代碼量和邏輯復(fù)雜度都會降低访诱,從而易于開發(fā)和維護垫挨。

啟動較快

  • 這是相對單個微服務(wù)來講的,相比于啟動單體架構(gòu)的整個項目触菜,啟動某個模塊的服務(wù)速度明顯是要快很多的九榔。

局部修改容易部署

  • 在開發(fā)中發(fā)現(xiàn)了一個問題,如果是單體架構(gòu)的話涡相,我們就需要重新發(fā)布并啟動整個項目哲泊,非常耗時間,但是微服務(wù)則不同催蝗,哪個模塊出現(xiàn)了bug我們只需要解決那個模塊的bug就可以了切威,解決完bug之后,我們只需要重啟這個模塊的服務(wù)即可丙号,部署相對簡單先朦,不必重啟整個項目從而大大節(jié)約時間。

技術(shù)棧不受限

  • 比如訂單微服務(wù)和電影微服務(wù)原來都是用java寫的犬缨,現(xiàn)在我們想把電影微服務(wù)改成nodeJs技術(shù)烙无,這是完全可以的,而且由于所關(guān)注的只是電影的邏輯而已遍尺,因此技術(shù)更換的成本也就會少很多截酷。

按需伸縮

  • 我們上面說了單體架構(gòu)在想擴展某個模塊的性能時不得不考慮到其它模塊的性能會不會受影響,對于我們微服務(wù)來講乾戏,完全不是問題迂苛,電影模塊通過什么方式來提升性能不必考慮其它模塊的情況。

7.3 缺點

運維要求較高

  • 對于單體架構(gòu)來講鼓择,我們只需要維護好這一個項目就可以了三幻,但是對于微服務(wù)架構(gòu)來講,由于項目是由多個微服務(wù)構(gòu)成的呐能,每個模塊出現(xiàn)問題都會造成整個項目運行出現(xiàn)異常念搬,想要知道是哪個模塊造成的問題往往是不容易的抑堡,因為我們無法一步一步通過debug的方式來跟蹤,這就對運維人員提出了很高的要求朗徊。

分布式的復(fù)雜性

  • 對于單體架構(gòu)來講首妖,我們可以不使用分布式,但是對于微服務(wù)架構(gòu)來說爷恳,分布式幾乎是必會用的技術(shù)有缆,由于分布式本身的復(fù)雜性,導(dǎo)致微服務(wù)架構(gòu)也變得復(fù)雜起來温亲。

接口調(diào)整成本高

  • 比如棚壁,用戶微服務(wù)是要被訂單微服務(wù)和電影微服務(wù)所調(diào)用的,一旦用戶微服務(wù)的接口發(fā)生大的變動栈虚,那么所有依賴它的微服務(wù)都要做相應(yīng)的調(diào)整袖外,由于微服務(wù)可能非常多,那么調(diào)整接口所造成的成本將會明顯提高魂务。

重復(fù)勞動

  • 對于單體架構(gòu)來講曼验,如果某段業(yè)務(wù)被多個模塊所共同使用,我們便可以抽象成一個工具類头镊,被所有模塊直接調(diào)用蚣驼,但是微服務(wù)卻無法這樣做魄幕,因為這個微服務(wù)的工具類是不能被其它微服務(wù)所直接調(diào)用的相艇,從而我們便不得不在每個微服務(wù)上都建這么一個工具類,從而導(dǎo)致代碼的重復(fù)纯陨。

8. 微服務(wù)開發(fā)框架

目前微服務(wù)的開發(fā)框架坛芽,最常用的有以下四個:

  1. Spring Cloud:http://projects.spring.io/spring-cloud(現(xiàn)在非常流行的微服務(wù)架構(gòu))

  2. Dubbo:http://dubbo.io

  3. Dropwizard:http://www.dropwizard.io (關(guān)注單個微服務(wù)的開發(fā))

  4. Consul、etcd&etc.(微服務(wù)的模塊)

9. Sprint cloud 和 Sprint boot區(qū)別

Spring Boot:

旨在簡化創(chuàng)建產(chǎn)品級的Spring應(yīng)用和服務(wù)翼抠,簡化了配置文件咙轩,使用嵌入式web服務(wù)器,含有諸多開箱即用微服務(wù)功能阴颖,可以和spring cloud聯(lián)合部署活喊。

Spring Cloud:

微服務(wù)工具包,為開發(fā)者提供了在分布式系統(tǒng)的配置管理量愧、服務(wù)發(fā)現(xiàn)钾菊、斷路器、智能路由偎肃、微代理煞烫、控制總線等開發(fā)工具包。

二累颂、微服務(wù)實踐先知

1. 客戶端如何訪問這些服務(wù)滞详?(API Gateway)

傳統(tǒng)的開發(fā)方式,所有的服務(wù)都是本地的,UI可以直接調(diào)用料饥,現(xiàn)在按功能拆分成獨立的服務(wù)蒲犬,跑在獨立的一般都在獨立的虛擬機上的 Java進程了∠』穑客戶端UI如何訪問他的暖哨?后臺有N個服務(wù),前臺就需要記住管理N個服務(wù)凰狞,一個服務(wù)下線/更新/升級篇裁,前臺就要重新部署,這明顯不服務(wù)我們 拆分的理念赡若,特別當前臺是移動應(yīng)用的時候达布,通常業(yè)務(wù)變化的節(jié)奏更快。另外逾冬,N個小服務(wù)的調(diào)用也是一個不小的網(wǎng)絡(luò)開銷黍聂。還有一般微服務(wù)在系統(tǒng)內(nèi)部,通常是無狀態(tài)的身腻,用戶登錄信息和權(quán)限管理最好有一個統(tǒng)一的地方維護管理(OAuth)产还。

所以,一般在后臺N個服務(wù)和UI之間一般會一個代理或者叫API Gateway嘀趟,他的作用包括

  • 提供統(tǒng)一服務(wù)入口脐区,讓微服務(wù)對前臺透明

  • 聚合后臺的服務(wù),節(jié)省流量她按,提升性能

  • 提供安全牛隅,過濾,流控等API管理功能

  • 我的理解其實這個API Gateway可以有很多廣義的實現(xiàn)辦法酌泰,可以是一個軟硬一體的盒子媒佣,也可以是一個簡單的MVC框架,甚至是一個Node.js的服務(wù)端陵刹。他們最重要的作用是為前臺(通常是移動應(yīng)用)提供后臺服務(wù)的聚合默伍,提供一個統(tǒng)一的服務(wù)出口,解除他們之間的耦合衰琐,不過API Gateway也有可能成為單點故障點或者性能的瓶頸也糊。

image

2. 服務(wù)之間如何通信?(服務(wù)調(diào)用)

因為所有的微服務(wù)都是獨立的Java進程跑在獨立的虛擬機上碘耳,所以服務(wù)間的通行就是IPC(inter process communication)显设,已經(jīng)有很多成熟的方案。現(xiàn)在基本最通用的有兩種方式辛辨。這幾種方式捕捂,展開來講都可以寫本書瑟枫,而且大家一般都比較熟悉細節(jié)了, 就不展開講了指攒。

  • REST(JAX-RS慷妙,Spring Boot)

  • RPC(Thrift, Dubbo)

  • 異步消息調(diào)用(Kafka, Notify)

image

一般同步調(diào)用比較簡單,一致性強允悦,但是容易出調(diào)用問題膝擂,性能體驗上也會差些,特別是調(diào)用層次多的時候隙弛。RESTful和RPC的比較也是一個很有意 思的話題架馋。一般REST基于HTTP,更容易實現(xiàn)全闷,更容易被接受叉寂,服務(wù)端實現(xiàn)技術(shù)也更靈活些,各個語言都能支持总珠,同時能跨客戶端屏鳍,對客戶端沒有特殊的要 求,只要封裝了HTTP的SDK就能調(diào)用局服,所以相對使用的廣一些钓瞭。RPC也有自己的優(yōu)點,傳輸協(xié)議更高效淫奔,安全更可控山涡,特別在一個公司內(nèi)部,如果有統(tǒng)一個的開發(fā)規(guī)范和統(tǒng)一的服務(wù)框架時搏讶,他的開發(fā)效率優(yōu)勢更明顯些佳鳖。就看各自的技術(shù)積累實際條件霍殴,自己的選擇了媒惕。

異步消息的方式在分布式系統(tǒng)中有特別廣泛的應(yīng)用,他既能減低調(diào)用服務(wù)之間的耦合来庭,又能成為調(diào)用之間的緩沖妒蔚,確保消息積壓不會沖垮被調(diào)用方,同時能 保證調(diào)用方的服務(wù)體驗月弛,繼續(xù)干自己該干的活肴盏,不至于被后臺性能拖慢。不過需要付出的代價是一致性的減弱帽衙,需要接受數(shù)據(jù)最終一致性菜皂;還有就是后臺服務(wù)一般要 實現(xiàn)冪等性,因為消息發(fā)送出于性能的考慮一般會有重復(fù)(保證消息的被收到且僅收到一次對性能是很大的考驗)厉萝;最后就是必須引入一個獨立的broker恍飘,如 果公司內(nèi)部沒有技術(shù)積累榨崩,對broker分布式管理也是一個很大的挑戰(zhàn)。

3. 這么多服務(wù)怎么查找章母?(服務(wù)發(fā)現(xiàn))

在微服務(wù)架構(gòu)中母蛛,一般每一個服務(wù)都是有多個拷貝,來做負載均衡乳怎。一個服務(wù)隨時可能下線彩郊,也可能應(yīng)對臨時訪問壓力增加新的服務(wù)節(jié)點。服務(wù)之間如何相互 感知蚪缀?服務(wù)如何管理秫逝?這就是服務(wù)發(fā)現(xiàn)的問題了。一般有兩類做法询枚,也各有優(yōu)缺點筷登。基本都是通過zookeeper等類似技術(shù)做服務(wù)注冊信息的分布式管理哩盲。當 服務(wù)上線時前方,服務(wù)提供者將自己的服務(wù)信息注冊到ZK(或類似框架),并通過心跳維持長鏈接廉油,實時更新鏈接信息惠险。服務(wù)調(diào)用者通過ZK尋址,根據(jù)可定制算法抒线,找到一個服務(wù)班巩,還可以將服務(wù)信息緩存在本地以提高性能。當服務(wù)下線時嘶炭,ZK會發(fā)通知給服務(wù)客戶端抱慌。

客戶端做:優(yōu)點是架構(gòu)簡單,擴展靈活眨猎,只對服務(wù)注冊器依賴抑进。缺點是客戶端要維護所有調(diào)用服務(wù)的地址,有技術(shù)難度睡陪,一般大公司都有成熟的內(nèi)部框架支持寺渗,比如Dubbo。

服務(wù)端做:優(yōu)點是簡單兰迫,所有服務(wù)對于前臺調(diào)用方透明信殊,一般在小公司在云服務(wù)上部署的應(yīng)用采用的比較多。

image

4. 服務(wù)掛了怎么辦汁果?

分布式最大的特性就是網(wǎng)絡(luò)是不可靠 的涡拘。通過微服務(wù)拆分能降低這個風險,不過如果沒有特別的保障据德,結(jié)局肯定是噩夢鳄乏。我們剛遇到一個線上故障就是一個很不起眼的SQL計數(shù)功能府蔗,在訪問量上升 時,導(dǎo)致數(shù)據(jù)庫load彪高汞窗,影響了所在應(yīng)用的性能姓赤,從而影響所有調(diào)用這個應(yīng)用服務(wù)的前臺應(yīng)用。所以當我們的系統(tǒng)是由一系列的服務(wù)調(diào)用鏈組成的時候仲吏,我們必須確保任一環(huán)節(jié)出問題都不至于影響整體鏈路不铆。相應(yīng)的手段有很多:

  • 重試機制

  • 限流

  • 熔斷機制

  • 負載均衡

  • 降級(本地緩存) 這些方法基本上都很明確通用,就不詳細說明了裹唆。比如Netflix的Hystrix:https://github.com/Netflix/Hystrix

image

5. 微服務(wù)需要考慮的問題

這里有一個圖非常好的總結(jié)微服務(wù)架構(gòu)需要考慮的問題誓斥,包括

  • API Gateway

  • 服務(wù)間調(diào)用

  • 服務(wù)發(fā)現(xiàn)

  • 服務(wù)容錯

  • 服務(wù)部署

  • 數(shù)據(jù)調(diào)用

三、微服務(wù)重要部件

1. 微服務(wù)基本能力

[圖片上傳失敗...(image-fe2e8a-1528422624724)]

2. 服務(wù)注冊中心

服務(wù)之間需要創(chuàng)建一種服務(wù)發(fā)現(xiàn)機制许帐,用于幫助服務(wù)之間互相感知彼此的存在劳坑。服務(wù)啟動時會將自身的服務(wù)信息注冊到注冊中心,并訂閱自己需要消費的服務(wù)成畦。

服務(wù)注冊中心是服務(wù)發(fā)現(xiàn)的核心距芬。它保存了各個可用服務(wù)實例的網(wǎng)絡(luò)地址(IPAddress和Port)。服務(wù)注冊中心必須要有高可用性和實時更新功能循帐。上面提到的 Netflix Eureka 就是一個服務(wù)注冊中心框仔。它提供了服務(wù)注冊和查詢服務(wù)信息的REST API。服務(wù)通過使用POST請求注冊自己的IPAddress和Port拄养。每30秒發(fā)送一個PUT請求刷新注冊信息离斩。通過DELETE請求注銷服務(wù)”衲洌客戶端通過GET請求獲取可用的服務(wù)實例信息跛梗。 Netflix的高可用(Netflix achieves high availability )是通過在Amazon EC2運行多個實例來實現(xiàn)的,每一個Eureka服務(wù)都有一個彈性IP Address。當Eureka服務(wù)啟動時棋弥,有DNS服務(wù)器動態(tài)的分配核偿。Eureka客戶端通過查詢 DNS來獲取Eureka的網(wǎng)絡(luò)地址(IP Address和Port)。一般情況下嘁锯,都是返回和客戶端在同一個可用區(qū)Eureka服務(wù)器地址宪祥。 其他能夠作為服務(wù)注冊中心的有:

  • etcd —– 高可用聂薪,分布式家乘,強一致性的,key-value藏澳,Kubernetes和Cloud Foundry都是使用了etcd仁锯。

  • consul —–一個用于discovering和configuring的工具。它提供了允許客戶端注冊和發(fā)現(xiàn)服務(wù)的API翔悠。Consul可以進行服務(wù)健康檢查业崖,以確定服務(wù)的可用性野芒。

  • zookeeper —— 在分布式應(yīng)用中被廣泛使用,高性能的協(xié)調(diào)服務(wù)双炕。 Apache Zookeeper 最初為Hadoop的一個子項目狞悲,但現(xiàn)在是一個頂級項目。

2.1 zookeeper服務(wù)注冊和發(fā)現(xiàn)

簡單來講妇斤,zookeeper可以充當一個服務(wù)注冊表(Service Registry)摇锋,讓多個服務(wù)提供者形成一個集群,讓服務(wù)消費者通過服務(wù)注冊表獲取具體的服務(wù)訪問地址(ip+端口)去訪問具體的服務(wù)提供者站超。如下圖所示:

image

具體來說荸恕,zookeeper就是個分布式文件系統(tǒng),每當一個服務(wù)提供者部署后都要將自己的服務(wù)注冊到zookeeper的某一路徑上: /{service}/{version}/{ip:port}, 比如我們的HelloWorldService部署到兩臺機器死相,那么zookeeper上就會創(chuàng)建兩條目錄:分別為/HelloWorldService/1.0.0/100.19.20.01:16888 /HelloWorldService/1.0.0/100.19.20.02:16888融求。

zookeeper提供了“心跳檢測”功能,它會定時向各個服務(wù)提供者發(fā)送一個請求(實際上建立的是一個 socket 長連接)算撮,如果長期沒有響應(yīng)生宛,服務(wù)中心就認為該服務(wù)提供者已經(jīng)“掛了”,并將其剔除肮柜,比如100.19.20.02這臺機器如果宕機了茅糜,那么zookeeper上的路徑就會只剩/HelloWorldService/1.0.0/100.19.20.01:16888。

服務(wù)消費者會去監(jiān)聽相應(yīng)路徑(/HelloWorldService/1.0.0),一旦路徑上的數(shù)據(jù)有任務(wù)變化(增加或減少),zookeeper都會通知服務(wù)消費方服務(wù)提供者地址列表已經(jīng)發(fā)生改變加勤,從而進行更新丁鹉。

更為重要的是zookeeper 與生俱來的容錯容災(zāi)能力(比如leader選舉),可以確保服務(wù)注冊表的高可用性昧狮。

3. 負載均衡

服務(wù)高可用的保證手段,為了保證高可用,每一個微服務(wù)都需要部署多個服務(wù)實例來提供服務(wù)酥馍。此時客戶端進行服務(wù)的負載均衡。

3.1 負載均衡的常見策略

3.1.1 隨機

把來自網(wǎng)絡(luò)的請求隨機分配給內(nèi)部中的多個服務(wù)器阅酪。

3.1.2 輪詢

每一個來自網(wǎng)絡(luò)中的請求旨袒,輪流分配給內(nèi)部的服務(wù)器,從1到N然后重新開始术辐。此種負載均衡算法適合服務(wù)器組內(nèi)部的服務(wù)器都具有相同的配置并且平均服務(wù)請求相對均衡的情況砚尽。

3.1.3 加權(quán)輪詢

根據(jù)服務(wù)器的不同處理能力,給每個服務(wù)器分配不同的權(quán)值辉词,使其能夠接受相應(yīng)權(quán)值數(shù)的服務(wù)請求必孤。例如:服務(wù)器A的權(quán)值被設(shè)計成1,B的權(quán)值是3瑞躺,C的權(quán)值是6敷搪,則服務(wù)器A兴想、B、C將分別接受到10%赡勘、30%嫂便、60%的服務(wù)請求。此種均衡算法能確保高性能的服務(wù)器得到更多的使用率闸与,避免低性能的服務(wù)器負載過重顽悼。

3.1.4 IP Hash

這種方式通過生成請求源IP的哈希值,并通過這個哈希值來找到正確的真實服務(wù)器几迄。這意味著對于同一主機來說他對應(yīng)的服務(wù)器總是相同蔚龙。使用這種方式,你不需要保存任何源IP映胁。但是需要注意木羹,這種方式可能導(dǎo)致服務(wù)器負載不平衡。

3.1.5 最少連接數(shù)

客戶端的每一次請求服務(wù)在服務(wù)器停留的時間可能會有較大的差異解孙,隨著工作時間加長坑填,如果采用簡單的輪循或隨機均衡算法,每一臺服務(wù)器上的連接進程可能會產(chǎn)生極大的不同弛姜,并沒有達到真正的負載均衡脐瑰。最少連接數(shù)均衡算法對內(nèi)部中需負載的每一臺服務(wù)器都有一個數(shù)據(jù)記錄,記錄當前該服務(wù)器正在處理的連接數(shù)量廷臼,當有新的服務(wù)連接請求時苍在,將把當前請求分配給連接數(shù)最少的服務(wù)器,使均衡更加符合實際情況荠商,負載更加均衡寂恬。此種均衡算法適合長時處理的請求服務(wù),如FTP莱没。

4. 容錯

容錯初肉,這個詞的理解,直面意思就是可以容下錯誤饰躲,不讓錯誤再次擴張牙咏,讓這個錯誤產(chǎn)生的影響在一個固定的邊界之內(nèi),“千里之堤毀于蟻穴”我們用容錯的方式就是讓這種蟻穴不要變大嘹裂。那么我們常見的降級妄壶,限流,熔斷器焦蘑,超時重試等等都是容錯的方法盯拱。

在調(diào)用服務(wù)集群時,如果一個微服務(wù)調(diào)用異常例嘱,如超時狡逢,連接異常,網(wǎng)絡(luò)異常等拼卵,則根據(jù)容錯策略進行服務(wù)容錯奢浑。目前支持的服務(wù)容錯策略有快速失敗,失效切換腋腮。如果連續(xù)失敗多次則直接熔斷雀彼,不再發(fā)起調(diào)用。這樣可以避免一個服務(wù)異常拖垮所有依賴于他的服務(wù)即寡。

4.1 容錯策略

4.1.1 快速失敗

服務(wù)只發(fā)起一次待用徊哑,失敗立即報錯。通常用于非冪等下性的寫操作

4.1.2 失效切換

服務(wù)發(fā)起調(diào)用聪富,當出現(xiàn)失敗后莺丑,重試其他服務(wù)器。通常用于讀操作墩蔓,但重試會帶來更長時間的延遲梢莽。重試的次數(shù)通常是可以設(shè)置的

4.1.3 失敗安全

失敗安全, 當服務(wù)調(diào)用出現(xiàn)異常時奸披,直接忽略昏名。通常用于寫入日志等操作。

4.1.4 失敗自動恢復(fù)

當服務(wù)調(diào)用出現(xiàn)異常時阵面,記錄失敗請求轻局,定時重發(fā)。通常用于消息通知样刷。

4.1.5 forking Cluster

并行調(diào)用多個服務(wù)器嗽交,只要有一個成功,即返回颂斜。通常用于實時性較高的讀操作夫壁。可以通過forks=n來設(shè)置最大并行數(shù)沃疮。

4.1.6 廣播調(diào)用

廣播調(diào)用所有提供者盒让,逐個調(diào)用,任何一臺失敗則失敗司蔬。通常用于通知所有提供者更新緩存或日志等本地資源信息邑茄。

5. 熔斷

熔斷技術(shù)可以說是一種“智能化的容錯”,當調(diào)用滿足失敗次數(shù)俊啼,失敗比例就會觸發(fā)熔斷器打開肺缕,有程序自動切斷當前的RPC調(diào)用,來防止錯誤進一步擴大。實現(xiàn)一個熔斷器主要是考慮三種模式,關(guān)閉同木,打開浮梢,半開。各個狀態(tài)的轉(zhuǎn)換如下圖彤路。

image

我們在處理異常的時候秕硝,要根據(jù)具體的業(yè)務(wù)情況來決定處理方式,比如我們調(diào)用商品接口洲尊,對方只是臨時做了降級處理远豺,那么作為網(wǎng)關(guān)調(diào)用就要切到可替換的服務(wù)上來執(zhí)行或者獲取托底數(shù)據(jù),給用戶友好提示坞嘀。還有要區(qū)分異常的類型躯护,比如依賴的服務(wù)崩潰了,這個可能需要花費比較久的時間來解決丽涩。也可能是由于服務(wù)器負載臨時過高導(dǎo)致超時棺滞。作為熔斷器應(yīng)該能夠甄別這種異常類型,從而根據(jù)具體的錯誤類型調(diào)整熔斷策略内狸。增加手動設(shè)置检眯,在失敗的服務(wù)恢復(fù)時間不確定的情況下,管理員可以手動強制切換熔斷狀態(tài)昆淡。最后锰瘸,熔斷器的使用場景是調(diào)用可能失敗的遠程服務(wù)程序或者共享資源。如果是本地緩存本地私有資源昂灵,使用熔斷器則會增加系統(tǒng)的額外開銷避凝。還要注意,熔斷器不能作為應(yīng)用程序中業(yè)務(wù)邏輯的異常處理替代品眨补。

有一些異常比較頑固管削,突然發(fā)生,無法預(yù)測撑螺,而且很難恢復(fù)含思,并且還會導(dǎo)致級聯(lián)失敗(舉個例子甘晤,假設(shè)一個服務(wù)集群的負載非常高含潘,如果這時候集群的一部分掛掉了,還占了很大一部分資源线婚,整個集群都有可能遭殃)遏弱。如果我們這時還是不斷進行重試的話,結(jié)果大多都是失敗的塞弊。因此漱逸,此時我們的應(yīng)用需要立即進入失敗狀態(tài)(fast-fail)泪姨,并采取合適的方法進行恢復(fù)。

我們可以用狀態(tài)機來實現(xiàn)CircuitBreaker饰抒,它有以下三種狀態(tài):

  • 關(guān)閉( Closed ):默認情況下Circuit Breaker是關(guān)閉的肮砾,此時允許操作執(zhí)行。CircuitBreaker內(nèi)部記錄著最近失敗的次數(shù)循集,如果對應(yīng)的操作執(zhí)行失敗唇敞,次數(shù)就會續(xù)一次蔗草。如果在某個時間段內(nèi)咒彤,失敗次數(shù)(或者失敗比率)達到閾值,CircuitBreaker會轉(zhuǎn)換到開啟( Open )狀態(tài)咒精。在開啟狀態(tài)中镶柱,Circuit Breaker會啟用一個超時計時器,設(shè)這個計時器的目的是給集群相應(yīng)的時間來恢復(fù)故障模叙。當計時器時間到的時候歇拆,CircuitBreaker會轉(zhuǎn)換到半開啟( Half-Open )狀態(tài)。

  • 開啟( Open ):在此狀態(tài)下范咨,執(zhí)行對應(yīng)的操作將會立即失敗并且立即拋出異常故觅。

  • 半開啟( Half-Open ):在此狀態(tài)下,Circuit Breaker會允許執(zhí)行一定數(shù)量的操作渠啊。如果所有操作全部成功输吏,CircuitBreaker就會假定故障已經(jīng)恢復(fù),它就會轉(zhuǎn)換到關(guān)閉狀態(tài)替蛉,并且重置失敗次數(shù)贯溅。如果其中 任意一次 操作失敗了,Circuit Breaker就會認為故障仍然存在躲查,所以它會轉(zhuǎn)換到開啟狀態(tài)并再次開啟計時器(再給系統(tǒng)一些時間使其從失敗中恢復(fù))

6. 限流和降級

保證核心服務(wù)的穩(wěn)定性它浅。為了保證核心服務(wù)的穩(wěn)定性,隨著訪問量的不斷增加镣煮,需要為系統(tǒng)能夠處理的服務(wù)數(shù)量設(shè)置一個極限閥值姐霍,超過這個閥值的請求則直接拒絕。同時典唇,為了保證核心服務(wù)的可用镊折,可以對否些非核心服務(wù)進行降級,通過限制服務(wù)的最大訪問量進行限流蚓聘,通過管理控制臺對單個微服務(wù)進行人工降級

7. SLA

SLA:Service-LevelAgreement的縮寫腌乡,意思是服務(wù)等級協(xié)議。 是關(guān)于網(wǎng)絡(luò)服務(wù)供應(yīng)商和客戶間的一份合同夜牡,其中定義了服務(wù)類型与纽、服務(wù)質(zhì)量和客戶付款等術(shù)語侣签。 典型的SLA包括以下項目:

  • 分配給客戶的最小帶寬;

  • 客戶帶寬極限急迂;

  • 能同時服務(wù)的客戶數(shù)目影所;

  • 在可能影響用戶行為的網(wǎng)絡(luò)變化之前的通知安排;

  • 撥入訪問可用性僚碎;

  • 運用統(tǒng)計學猴娩;

  • 服務(wù)供應(yīng)商支持的最小網(wǎng)絡(luò)利用性能,如99.9%有效工作時間或每天最多為1分鐘的停機時間勺阐;

  • 各類客戶的流量優(yōu)先權(quán)卷中;

  • 客戶技術(shù)支持和服務(wù);

  • 懲罰規(guī)定渊抽,為服務(wù)供應(yīng)商不能滿足 SLA需求所指定蟆豫。

8. API網(wǎng)關(guān)

這里說的網(wǎng)關(guān)是指API網(wǎng)關(guān),直面意思是將所有API調(diào)用統(tǒng)一接入到API網(wǎng)關(guān)層懒闷,有網(wǎng)關(guān)層統(tǒng)一接入和輸出十减。一個網(wǎng)關(guān)的基本功能有:統(tǒng)一接入、安全防護愤估、協(xié)議適配帮辟、流量管控、長短鏈接支持玩焰、容錯能力由驹。有了網(wǎng)關(guān)之后,各個API服務(wù)提供團隊可以專注于自己的的業(yè)務(wù)邏輯處理震捣,而API網(wǎng)關(guān)更專注于安全荔棉、流量、路由等問題蒿赢。

9. 多級緩存

最簡單的緩存就是查一次數(shù)據(jù)庫然后將數(shù)據(jù)寫入緩存比如redis中并設(shè)置過期時間润樱。因為有過期失效因此我們要關(guān)注下緩存的穿透率,這個穿透率的計算公式羡棵,比如查詢方法queryOrder(調(diào)用次數(shù)1000/1s)里面嵌套查詢DB方法queryProductFromDb(調(diào)用次數(shù)300/s)壹若,那么redis的穿透率就是300/1000,在這種使用緩存的方式下,是要重視穿透率的皂冰,穿透率大了說明緩存的效果不好店展。還有一種使用緩存的方式就是將緩存持久化,也就是不設(shè)置過期時間秃流,這個就會面臨一個數(shù)據(jù)更新的問題赂蕴。一般有兩種辦法,一個是利用時間戳舶胀,查詢默認以redis為主概说,每次設(shè)置數(shù)據(jù)的時候放入一個時間戳碧注,每次讀取數(shù)據(jù)的時候用系統(tǒng)當前時間和上次設(shè)置的這個時間戳做對比,比如超過5分鐘糖赔,那么就再查一次數(shù)據(jù)庫萍丐。這樣可以保證redis里面永遠有數(shù)據(jù),一般是對DB的一種容錯方法放典。還有一個就是真正的讓redis做為DB使用逝变。就是圖里面畫的通過訂閱數(shù)據(jù)庫的binlog通過數(shù)據(jù)異構(gòu)系統(tǒng)將數(shù)據(jù)推送給緩存,同時將將緩存設(shè)置為多級奋构】怯埃可以通過使用jvmcache作為應(yīng)用內(nèi)的一級緩存,一般是體積小声怔,訪問頻率大的更適合這種jvmcache方式态贤,將一套redis作為二級remote緩存舱呻,另外最外層三級redis作為持久化緩存醋火。

10. 超時和重試

超時與重試機制也是容錯的一種方法,凡是發(fā)生RPC調(diào)用的地方箱吕,比如讀取redis芥驳,db,mq等茬高,因為網(wǎng)絡(luò)故障或者是所依賴的服務(wù)故障兆旬,長時間不能返回結(jié)果,就會導(dǎo)致線程增加怎栽,加大cpu負載丽猬,甚至導(dǎo)致雪崩。所以對每一個RPC調(diào)用都要設(shè)置超時時間熏瞄。對于強依賴RPC調(diào)用資源的情況脚祟,還要有重試機制,但是重試的次數(shù)建議1-2次强饮,另外如果有重試由桌,那么超時時間就要相應(yīng)的調(diào)小,比如重試1次邮丰,那么一共是發(fā)生2次調(diào)用行您。如果超時時間配置的是2s,那么客戶端就要等待4s才能返回剪廉。因此重試+超時的方式娃循,超時時間要調(diào)小。這里也再談一下一次PRC調(diào)用的時間都消耗在哪些環(huán)節(jié)斗蒋,一次正常的調(diào)用統(tǒng)計的耗時主要包括: ①調(diào)用端RPC框架執(zhí)行時間 + ②網(wǎng)絡(luò)發(fā)送時間 + ③服務(wù)端RPC框架執(zhí)行時間 + ④服務(wù)端業(yè)務(wù)代碼時間捌斧。調(diào)用方和服務(wù)方都有各自的性能監(jiān)控捧书,比如調(diào)用方tp99是500ms,服務(wù)方tp99是100ms骤星,找了網(wǎng)絡(luò)組的同事確認網(wǎng)絡(luò)沒有問題经瓷。那么時間都花在什么地方了呢,兩種原因洞难,客戶端調(diào)用方舆吮,還有一個原因是網(wǎng)絡(luò)發(fā)生TCP重傳。所以要注意這兩點队贱。

11. 線程池隔離

在抗量這個環(huán)節(jié)色冀,Servlet3異步的時候,有提到過線程隔離柱嫌。線程隔離的之間優(yōu)勢就是防止級聯(lián)故障锋恬,甚至是雪崩。當網(wǎng)關(guān)調(diào)用N多個接口服務(wù)的時候编丘,我們要對每個接口進行線程隔離与学。比如,我們有調(diào)用訂單嘉抓、商品索守、用戶。那么訂單的業(yè)務(wù)不能夠影響到商品和用戶的請求處理抑片。如果不做線程隔離卵佛,當訪問訂單服務(wù)出現(xiàn)網(wǎng)絡(luò)故障導(dǎo)致延時,線程積壓最終導(dǎo)致整個服務(wù)CPU負載滿敞斋。就是我們說的服務(wù)全部不可用了截汪,有多少機器都會被此刻的請求塞滿。那么有了線程隔離就會使得我們的網(wǎng)關(guān)能保證局部問題不會影響全局植捎。

12. 降級和限流

關(guān)于降級限流的方法業(yè)界都已經(jīng)有很成熟的方法了衙解,比如FAILBACK機制,限流的方法令牌桶鸥跟,漏桶丢郊,信號量等。這里談一下我們的一些經(jīng)驗医咨,降級一般都是由統(tǒng)一配置中心的降級開關(guān)來實現(xiàn)的枫匾,那么當有很多個接口來自同一個提供方,這個提供方的系統(tǒng)或這機器所在機房網(wǎng)絡(luò)出現(xiàn)了問題拟淮,我們就要有一個統(tǒng)一的降級開關(guān)干茉,不然就要一個接口一個接口的來降級。也就是要對業(yè)務(wù)類型有一個大閘刀很泊。還有就是 降級切記暴力降級角虫,什么是暴力降級的沾谓,比如把論壇功能降調(diào),結(jié)果用戶顯示一個大白板戳鹅,我們要實現(xiàn)緩存住一些數(shù)據(jù)均驶,也就是有托底數(shù)據(jù)。限流一般分為分布式限流和單機限流枫虏,如果實現(xiàn)分布式限流的話就要一個公共的后端存儲服務(wù)比如redis妇穴,在大nginx節(jié)點上利用lua讀取redis配置信息。我們現(xiàn)在的限流都是單機限流隶债,并沒有實施分布式限流腾它。

13. 網(wǎng)關(guān)監(jiān)控和統(tǒng)計

image

API網(wǎng)關(guān)是一個串行的調(diào)用,那么每一步發(fā)生的異常要記錄下來死讹,統(tǒng)一存儲到一個地方比如elasticserach中瞒滴,便于后續(xù)對調(diào)用異常的分析。鑒于公司docker申請都是統(tǒng)一分配赞警,而且分配之前docker上已經(jīng)存在3個agent了妓忍,不再允許增加。我們自己實現(xiàn)了一個agent程序仅颇,來負責采集服務(wù)器上面的日志輸出单默,然后發(fā)送到kafka集群,再消費到elasticserach中忘瓦,通過web查詢。現(xiàn)在做的追蹤功能還比較簡單引颈,這塊還需要繼續(xù)豐富耕皮。

來源:https://blog.csdn.net/wuxiaobingandbob/article/details/78642020?locationNum=1&fps=1

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蝙场,隨后出現(xiàn)的幾起案子凌停,更是在濱河造成了極大的恐慌,老刑警劉巖售滤,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件罚拟,死亡現(xiàn)場離奇詭異,居然都是意外死亡完箩,警方通過查閱死者的電腦和手機赐俗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弊知,“玉大人阻逮,你說我怎么就攤上這事≈韧” “怎么了叔扼?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵事哭,是天一觀的道長。 經(jīng)常有香客問我瓜富,道長鳍咱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任与柑,我火速辦了婚禮流炕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘仅胞。我一直安慰自己每辟,他們只是感情好,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布干旧。 她就那樣靜靜地躺著渠欺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪椎眯。 梳的紋絲不亂的頭發(fā)上挠将,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天,我揣著相機與錄音编整,去河邊找鬼舔稀。 笑死,一個胖子當著我的面吹牛掌测,可吹牛的內(nèi)容都是我干的内贮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼汞斧,長吁一口氣:“原來是場噩夢啊……” “哼夜郁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起粘勒,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤竞端,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后庙睡,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體事富,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年乘陪,在試婚紗的時候發(fā)現(xiàn)自己被綠了统台。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡暂刘,死狀恐怖饺谬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤募寨,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布族展,位于F島的核電站,受9級特大地震影響拔鹰,放射性物質(zhì)發(fā)生泄漏仪缸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一列肢、第九天 我趴在偏房一處隱蔽的房頂上張望恰画。 院中可真熱鬧,春花似錦瓷马、人聲如沸拴还。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽片林。三九已至,卻和暖如春怀骤,著一層夾襖步出監(jiān)牢的瞬間费封,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工蒋伦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留弓摘,地道東北人。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓痕届,卻偏偏與公主長得像韧献,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子爷抓,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353

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