API網(wǎng)關(guān)的設(shè)計(jì)思考

作為技術(shù),尤其是后端開發(fā),從一開始工作就一直會(huì)和nginx打交道纲刀。它已經(jīng)是現(xiàn)代互聯(lián)網(wǎng)企業(yè)的事實(shí)網(wǎng)關(guān)標(biāo)準(zhǔn)了。即使各個(gè)公司都自研了各種不同的網(wǎng)關(guān),但是大多數(shù)還是會(huì)在請(qǐng)求最前端部署一層nginx示绊。它的穩(wěn)定性锭部、可靠性以及性能方面的口碑都是非常非常好的。在我剛開始工作那時(shí)面褐,就特別崇拜nginx拌禾。在這個(gè)網(wǎng)絡(luò)的時(shí)代,nginx作為網(wǎng)關(guān)展哭,它涉及到了非常多有深度的后端技術(shù)湃窍。比如:

  • 網(wǎng)絡(luò)協(xié)議
  • 事件驅(qū)動(dòng)的異步編程
  • 高度可擴(kuò)展的架構(gòu)設(shè)計(jì)
  • 高可用設(shè)計(jì)(熱加載熱更新)
  • 恰當(dāng)?shù)臄?shù)據(jù)結(jié)構(gòu)設(shè)計(jì)
  • 極致的性能優(yōu)化

在我看來(lái),nginx就是一個(gè)技術(shù)的百科全書匪傍,除了存儲(chǔ)相關(guān)的內(nèi)容您市,大部分技術(shù)都可以在它里面找到運(yùn)用,而且都是標(biāo)桿級(jí)的役衡。因此我也萌生了一個(gè)想法茵休,就是要自己寫一個(gè)和nginx一樣好用的網(wǎng)關(guān)軟件。這不是出于重復(fù)造輪子的目的手蝎,而是為了學(xué)習(xí)榕莺。因?yàn)槲矣X(jué)得只有當(dāng)你有能力模仿,你才有能力去創(chuàng)新棵介。

通過(guò)這些年不斷地學(xué)習(xí)和使用钉鸯,我漸漸地發(fā)現(xiàn),實(shí)現(xiàn)一個(gè)nginx(完成核心功能邮辽、性能差距不太大)并不是一件難以想象的事情亏拉,雖然困難但是依然是可以做到的。由于nginx是一個(gè)模塊化設(shè)計(jì)的軟件逆巍,能夠非常容易地?cái)U(kuò)展及塘,隨著這些年的發(fā)展,功能是非常豐富的锐极。如果想要完整覆蓋nginx的功能笙僚,沒(méi)必要也沒(méi)可能。同時(shí)灵再,nginx經(jīng)過(guò)多年的發(fā)展肋层,除了核心技術(shù)(事件驅(qū)動(dòng))的優(yōu)越性以外,還進(jìn)行了很多細(xì)節(jié)的優(yōu)化翎迁,這些優(yōu)化也使得后來(lái)者很難達(dá)到相同甚至更高的性能栋猖。因此,我逐漸明白汪榔,與其說(shuō)要實(shí)現(xiàn)一個(gè)nginx蒲拉,不如說(shuō)是領(lǐng)悟nginx的精髓,實(shí)現(xiàn)一個(gè)和nginx一樣擴(kuò)展性高,性能好的web server雌团。

不過(guò)隨著互聯(lián)網(wǎng)的快速發(fā)展燃领,網(wǎng)關(guān)技術(shù)也處于一個(gè)變革的前夕。由于微服務(wù)的出現(xiàn)锦援,以前單體應(yīng)用中的功能模塊被拆分成多個(gè)微服務(wù)進(jìn)行獨(dú)立部署猛蔽,這使得nginx的下游頓時(shí)變得多了起來(lái)。微服務(wù)的動(dòng)態(tài)伸縮灵寺,使得服務(wù)發(fā)現(xiàn)變成了幾乎所有企業(yè)都需要的基礎(chǔ)設(shè)施曼库。而nginx設(shè)計(jì)之初并沒(méi)有考慮服務(wù)發(fā)現(xiàn),好在由于nginx支持配置熱更新略板,現(xiàn)在有很多方法可以在服務(wù)信息變化之后自動(dòng)改寫nginx.conf中upstream部分凉泄,從而達(dá)到支持服務(wù)發(fā)現(xiàn)的目的。但是這又引入了很多運(yùn)維的問(wèn)題蚯根。

另一方面后众,nginx主要是進(jìn)行http服務(wù)代理,而很多企業(yè)越來(lái)越意識(shí)到http1.x協(xié)議的不足颅拦。它明文蒂誉、無(wú)類型且性能差,雖然部分場(chǎng)景無(wú)法替代(瀏覽器)距帅,但是越來(lái)越多的公司已經(jīng)開始在內(nèi)部RPC轉(zhuǎn)向thrift dubbo protobuf這類基于TCP的強(qiáng)類型且高性能的傳輸協(xié)議了右锨。nginx設(shè)計(jì)之初并沒(méi)有考慮多協(xié)議轉(zhuǎn)換的問(wèn)題,雖然這些年官方也慢慢支持了grpc碌秸,nginx的fork版本 tengine支持了dubbo绍移,但是這讓我們意識(shí)到一個(gè)問(wèn)題:如何在架構(gòu)設(shè)計(jì)時(shí)就考慮到多協(xié)議的支持?只有當(dāng)web server能夠支持多協(xié)議轉(zhuǎn)換讥电,它才能夠承擔(dān)企業(yè)內(nèi)網(wǎng)流量轉(zhuǎn)發(fā)的職責(zé)蹂窖。

除了以上問(wèn)題,nginx如果要作為企業(yè)內(nèi)部流量轉(zhuǎn)發(fā)器恩敌,還面臨另一個(gè)問(wèn)題瞬测,那就是運(yùn)維和部署。nginx的常用場(chǎng)景的就是幾臺(tái)固定的機(jī)器纠炮,半自動(dòng)化地利用一些工具去更新nginx.conf并reload月趟。但是這也意味著,nginx是一個(gè)單點(diǎn)層恢口,一旦出問(wèn)題將使所有服務(wù)都不可用孝宗。在過(guò)去,除了讓nginx更穩(wěn)定以外沒(méi)什么別的辦法耕肩。但到了現(xiàn)在因妇,隨著k8s等技術(shù)的發(fā)展问潭,部署服務(wù)和服務(wù)的依賴變得非常容易,因此去中心化的代理層變得越來(lái)越受歡迎沙峻,比如說(shuō)像service mesh的sidecar。每個(gè)代理服務(wù)和業(yè)務(wù)服務(wù)部署到一個(gè)節(jié)點(diǎn)两芳,通過(guò)統(tǒng)一的控制面板來(lái)修改不同節(jié)點(diǎn)上sidecar的行為摔寨。這樣的好處是去中心化,即使有sidecar掛掉怖辆,也不影響整體可用性是复,同時(shí)每個(gè)sidecar并不需要承受太高的流量壓力,并且最關(guān)鍵的是節(jié)約資源竖螃,不需要額外為轉(zhuǎn)發(fā)層專門部署數(shù)量龐大的機(jī)器淑廊,一年下來(lái)這甚至能節(jié)約數(shù)百萬(wàn)。去中心化的這種sidecar模式特咆,它最核心的復(fù)雜性就在運(yùn)維和部署季惩,而這些復(fù)雜性已經(jīng)被k8s解決掉了。

sidecar除了作流量轉(zhuǎn)發(fā)以外腻格,還有個(gè)很重要的功能就是服務(wù)管控画拾,包括但不限于:

  • 限流
  • 降級(jí)
  • tracing
  • 加解密
  • 鑒權(quán)
  • 服務(wù)發(fā)現(xiàn)
  • 熔斷

這些功能在nginx里基本上都有,即使官方?jīng)]有支持菜职,也能找到社區(qū)的開源模塊或者利用openresty+lua來(lái)實(shí)現(xiàn)青抛。這里也側(cè)面體現(xiàn)出了nginx架構(gòu)設(shè)計(jì)的優(yōu)越性,能夠容易地?cái)U(kuò)展酬核,使得軟件的生命力長(zhǎng)盛不衰蜜另。由于以上服務(wù)管控的功能在現(xiàn)代任何一個(gè)互聯(lián)網(wǎng)公司都幾乎是必不可少的,因此在設(shè)計(jì)一個(gè)新的代理服務(wù)器時(shí)嫡意,一定要在設(shè)計(jì)階段就把這些功能考慮進(jìn)去举瑰。

總結(jié)一下:對(duì)于一個(gè)現(xiàn)代的流量代理服務(wù)器(這里我不再說(shuō)它是web server了,因?yàn)閣eb服務(wù)只是很少的一部分了)蔬螟,它需要滿足以下的一些特點(diǎn):

  • 高度模塊化可擴(kuò)展的設(shè)計(jì)
  • 利用異步實(shí)現(xiàn)高IO性能
  • 更適合存儲(chǔ)和結(jié)構(gòu)化的配置文件(不需要像nginx那樣human readable)
  • 能支持xDS協(xié)議
  • 無(wú)狀態(tài)適合分布式部署
  • 支持熱升級(jí)配置熱更新
  • 支持多協(xié)議轉(zhuǎn)換嘶居,提供方便的開發(fā)接口
  • 內(nèi)置服務(wù)管控
  • 豐富的metrics且能方便對(duì)接prometheus等平臺(tái)

當(dāng)然,這里面的每個(gè)點(diǎn)做起來(lái)其實(shí)都不簡(jiǎn)單促煮。比如模塊化和可擴(kuò)展性的設(shè)計(jì)邮屁,這個(gè)實(shí)際是每個(gè)系統(tǒng)都需要做的設(shè)計(jì),然而也是看起來(lái)很虛的菠齿。因?yàn)榻^大部分系統(tǒng)和軟件的生命周期都很短佑吝,短到甚至MVP版本上線后就砍掉了,因此大部分人雖然口頭上重視實(shí)際行動(dòng)上藐視绳匀,很少真正去思考怎么去設(shè)計(jì)芋忿。
模塊化和可擴(kuò)展性本質(zhì)上是類似的炸客,如果模塊拆分得比較恰當(dāng),每個(gè)模塊的功能很正交且明確戈钢,那么在擴(kuò)展時(shí)就能夠很容易地對(duì)它們進(jìn)行組合痹仙。增強(qiáng)和擴(kuò)展單個(gè)模塊,也可以讓所有其它相關(guān)功能受益殉了。模塊其實(shí)就是宏觀上的函數(shù)开仰。而可擴(kuò)展性,其實(shí)就是代碼中的抽象薪铜。我們的代碼核心流程應(yīng)該建立在一系列的抽象之上,比如寫日志隔箍,不應(yīng)該先入為主地認(rèn)為日志就是文件,而應(yīng)該抽象來(lái)看蜒滩,日志是把系統(tǒng)生成一些關(guān)鍵信息滨达,通過(guò)某種設(shè)備記錄下來(lái)弦悉。我們不應(yīng)該假定設(shè)備就是文件系統(tǒng),也可能是數(shù)據(jù)庫(kù)蟆炊,也可能是通過(guò)網(wǎng)絡(luò)傳輸?shù)搅硗獾臋C(jī)器…
因此,只有面向抽象來(lái)設(shè)計(jì)整個(gè)系統(tǒng)涩搓,才能做到真的可擴(kuò)展。除了抽象以外昧甘,核心流程里留出足夠多的hook,也是可擴(kuò)展性的關(guān)鍵充边。但是通過(guò)hook實(shí)現(xiàn)的擴(kuò)展,只能是一些旁路功能浇冰,但是這些也很重要贬媒,比如給http請(qǐng)求加一些額外的header,修改header中的某些值肘习,記錄一些metric信息等等…
因此际乘,光設(shè)計(jì)一項(xiàng)就需要花很多心思。如果系統(tǒng)設(shè)計(jì)得過(guò)于抽象也是不行的漂佩,因?yàn)槟菢泳蜎](méi)有意義了脖含。最極端抽象的系統(tǒng)就是一個(gè)空的main函數(shù)罪塔,它當(dāng)然足夠抽象,把系統(tǒng)抽象為一系列函數(shù)的組合养葵,基于這種抽象征堪,你當(dāng)然可以從main函數(shù)擴(kuò)展出任何你想要的功能。但是軟件總是為了實(shí)現(xiàn)特定需求的关拒,也就是說(shuō)它不需要像main函數(shù)那么強(qiáng)的擴(kuò)展性佃蚜。太抽象意味著直接可以被復(fù)用的能力太少,也意味著擴(kuò)展方需要花更多的精力去設(shè)計(jì)和開發(fā)夏醉。一個(gè)好的設(shè)計(jì)爽锥,一定是從先明確需求開始的涌韩,也就是上面我總結(jié)的那些需求點(diǎn)畔柔,從需求出發(fā),根據(jù)實(shí)際需要臣樱,哪些是未來(lái)可能變化的靶擦,哪些是不變的」秃粒總的來(lái)說(shuō)玄捕,依賴和功能的實(shí)現(xiàn)應(yīng)該抽象的,而處理流程應(yīng)該具象的棚放。

除了設(shè)計(jì)以外枚粘,性能也是一個(gè)及其重要的因素。apache由于性能太差飘蚯,現(xiàn)在都沒(méi)有人關(guān)心它的設(shè)計(jì)是如何的馍迄,因?yàn)榇蠹叶疾挥盟?duì)于流量代理軟件來(lái)說(shuō)局骤,性能不單純是一個(gè)指標(biāo)攀圈,它應(yīng)該屬于功能的一部分。代理軟件在請(qǐng)求鏈路中加了一層峦甩,為了保證整體耗時(shí)可控赘来,一定需要讓消耗在這一層的時(shí)間盡可能少甚至忽略不計(jì)。而代理請(qǐng)求是一個(gè)IO密集型任務(wù)凯傲,因此一定需要使用多路服用的技術(shù)犬辰。像nginx,使用了master+多worker的多進(jìn)程架構(gòu)冰单,這樣除了通過(guò)進(jìn)程的隔離機(jī)制盡可能保證可用性外忧风,還能夠充分利用多核狮腿。同時(shí)每個(gè)進(jìn)程內(nèi)部的主要部分是一個(gè)基于epoll的異步IO,大大提高了性能吃度。其實(shí)除了nginx這種方式以外贴硫,像以Golang為代表的基于單進(jìn)程多線程的green thread英遭,也能夠解決這樣的問(wèn)題,每個(gè)green thread也是基于epoll的異步IO汁尺。

對(duì)于配置文件來(lái)說(shuō)多律,這里和nginx有比較大的差別。nginx設(shè)計(jì)之初大部分公司還是人肉運(yùn)維辽装,因此它把易用性放在首位相味。一個(gè)好讀易懂語(yǔ)法簡(jiǎn)單的但又富有表達(dá)力的配置文件丰涉,能夠極大地減少用戶配置nginx的復(fù)雜性,也能幫助他們更快上手玲销。而到了現(xiàn)在摘符,網(wǎng)關(guān)集群的規(guī)模已經(jīng)是非常非常大了,人肉地挨個(gè)去配置nginx.conf幾乎不可能了瘩绒。同時(shí)锁荔,nginx作為接入層蝙砌,承接了太多太多的外部流量跋理,一個(gè)nginx.conf的location塊已經(jīng)多得數(shù)不清了前普,早已拆分從上百個(gè)xxx.conf拭卿,通過(guò)include來(lái)加載贱纠。這種規(guī)模的業(yè)務(wù)場(chǎng)景下,配置文件再也談不上簡(jiǎn)單易讀惠桃。這時(shí)候我們更需要的是類似配置中心這樣的操作界面刽射,通過(guò)界面的操作來(lái)控制網(wǎng)關(guān)的行為剃执。配置的下發(fā)也都應(yīng)該做成自動(dòng)化懈息,最終一致辫继,可灰度可回滾的。因?yàn)槲覀兌际窃诮缑嫔咸顚懕韱吻菜#耘渲梦募旧砭筒辉傩枰獫M足human readable了炮车,最終配置長(zhǎng)什么樣其實(shí)無(wú)所謂了瘦穆,只要應(yīng)用好解析就行扛或。由于人工配置可能會(huì)有失誤,對(duì)配置文件進(jìn)行一些自動(dòng)化校驗(yàn)也很關(guān)鍵悲伶,因此配置文件需要滿足結(jié)構(gòu)化,這樣方便進(jìn)行讀取和檢測(cè)蒂萎。比如最常見的就是JSON格式淮椰。另一方面是要考慮配置文件的可擴(kuò)展性,因?yàn)橄到y(tǒng)的每個(gè)功能都需要可配置泻拦,同時(shí)還得考慮按什么維度去配置争拐,每個(gè)配置項(xiàng)是否支持特定條件才生效晦雨,特定條件怎么在配置中表達(dá),先后順序是什么…最后闹瞧,一個(gè)很關(guān)鍵的問(wèn)題是奥邮,配置平臺(tái)一般來(lái)說(shuō)還是挺復(fù)雜,包括前后端以及各種推送存儲(chǔ)脚粟,如果能夠?qū)娱_源平臺(tái)就好了核无。那么如果對(duì)接Istio這類的控制平面团南,我們就需要支持xDS協(xié)議…

另一個(gè)問(wèn)題也是非常重要的堕担,就是熱升級(jí)和配置熱更新。配置的熱更新幾乎所有軟件都是采用的reload方式佑惠,而不是直接在內(nèi)存中更新配置對(duì)象膜楷。這么做最主要的原因是避免鎖帶來(lái)的開銷赌厅。如果直接在內(nèi)存中更新配置特愿,相當(dāng)于配置對(duì)象被改寫,同時(shí)處理請(qǐng)求時(shí)又會(huì)讀取配置目养。這就是最直接的data race癌蚁。為了避免data race引起的各種問(wèn)題努释,必然需要對(duì)配置對(duì)象加上一個(gè)讀寫鎖伐蒂,而鎖又引入的額外的性能開銷。使用reload方式饿自,意味著在兩次reload之間配置是不可變的,這就完全不需要考慮data race了复唤。但是reload也有它的問(wèn)題佛纫,比如如果要保證過(guò)程平滑呈宇,那么就需要做graceful reload,不能生硬地中斷正在處理的請(qǐng)求甥啄。如果只是C/S模型的請(qǐng)求,請(qǐng)求由client發(fā)起宫盔,server只是被動(dòng)響應(yīng)那還簡(jiǎn)單灼芭,處理完請(qǐng)求不再讀取client的數(shù)據(jù)就行了彼绷。但是如果是雙向通信比如服務(wù)端推送或者websocket苛预,這時(shí)處理起來(lái)就比較麻煩笋熬。我們得考慮平滑地遷移長(zhǎng)鏈接胳螟。而且考慮到部署方式越來(lái)越偏向于k8s以pod為單位的容器化部署,我們的熱升級(jí)不再是單純的物理機(jī)上操作秘遏,需要考慮跨容器的平滑長(zhǎng)鏈接遷移邦危。這方面螞蟻金服的mosn做了一些探索倦蚪,也是值得學(xué)習(xí)的陵且。

多協(xié)議轉(zhuǎn)換也是在設(shè)計(jì)時(shí)需要著重花功夫思考的問(wèn)題慕购。如果要適應(yīng)內(nèi)網(wǎng)環(huán)境沪悲,那么對(duì)多協(xié)議的支持是必須要考慮的殿如。一開始開發(fā),肯定不可能覆蓋所有的協(xié)議握截,所以需要設(shè)計(jì)出擴(kuò)展的口子飞崖,為后續(xù)添加功能做準(zhǔn)備。從傳輸層考慮谨胞,可以分為TCP和UDP兩類請(qǐng)求固歪。TCP是一定要支持的而且是重中之重,那么接下來(lái)考慮我們是否需要支持UDP的反響代理胯努。由于最新的http3是基于quic牢裳,本質(zhì)就是udp,那么未來(lái)我們是不是也需要能夠反響代理http3請(qǐng)求叶沛?如果需要的話蒲讯,那就得考慮udp。接下來(lái)需要考慮最重要的灰署,就是如何抽象協(xié)議轉(zhuǎn)換判帮。協(xié)議轉(zhuǎn)換簡(jiǎn)單的來(lái)說(shuō)就是解析協(xié)議(decode)溉箕,以及按照新協(xié)議進(jìn)行編碼(encode)。但解析時(shí)針對(duì)不同協(xié)議有不同的解析方式抗楔,應(yīng)該怎么抽象贪婉?是定一個(gè)interface尤蒿,不同協(xié)議各自實(shí)現(xiàn)interface然后由core代碼來(lái)調(diào)度,還是不同協(xié)議完全自己實(shí)現(xiàn)協(xié)議解析讳侨?解析后的數(shù)據(jù)用什么數(shù)據(jù)結(jié)構(gòu)表示勇婴?怎么在后續(xù)各個(gè)模塊之間流轉(zhuǎn)?這些都是設(shè)計(jì)時(shí)需要思考的問(wèn)題。并且慰技,網(wǎng)上幾乎沒(méi)有文章講這些內(nèi)容艾帐,大部分都需要自己去讀nginx或者envoy的源碼去悟事扭。螞蟻mosn自己總結(jié)了一個(gè)協(xié)議解析框架,本質(zhì)上是對(duì)協(xié)議編解碼的抽象過(guò)程進(jìn)行了部分的具象化(這句話本身有點(diǎn)抽象),由于具象化宰睡,因此有了部分可復(fù)用的能力,能夠降低協(xié)議接入的開發(fā)成本。

總結(jié)

實(shí)現(xiàn)一個(gè)類似nginx的更現(xiàn)代的流量轉(zhuǎn)發(fā)服務(wù)器是一個(gè)看起來(lái)不復(fù)雜(知乎上各種嘴炮帝甚至都不屑),但其實(shí)內(nèi)部的設(shè)計(jì)和實(shí)現(xiàn)都不是一件容易的事情,比單純做個(gè)proxy難上很多很多逝薪。說(shuō)了這么多,我也想立個(gè)flag:使用rust開發(fā)一個(gè)包含上述功能,并同時(shí)適合作為http反響代理/k8s ingress和service mesh sidecar的"現(xiàn)代nginx"。為什么要用rust缘琅?第一,性能好;第二,安全;第三,我學(xué)了很久但依然感覺(jué)不太熟的樣子,得找個(gè)大項(xiàng)目實(shí)操一把

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末通惫,一起剝皮案震驚了整個(gè)濱河市遵湖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異沪摄,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)舱痘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門芭逝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)胖翰,“玉大人培他,你說(shuō)我怎么就攤上這事猛遍〈” “怎么了乙帮?”我有些...
    開封第一講書人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)极景。 經(jīng)常有香客問(wèn)我察净,道長(zhǎng),這世上最難降的妖魔是什么盼樟? 我笑而不...
    開封第一講書人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任氢卡,我火速辦了婚禮,結(jié)果婚禮上晨缴,老公的妹妹穿的比我還像新娘译秦。我一直安慰自己,他們只是感情好击碗,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開白布筑悴。 她就那樣靜靜地躺著,像睡著了一般稍途。 火紅的嫁衣襯著肌膚如雪阁吝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,196評(píng)論 1 308
  • 那天械拍,我揣著相機(jī)與錄音突勇,去河邊找鬼。 笑死殊者,一個(gè)胖子當(dāng)著我的面吹牛与境,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播猖吴,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼摔刁,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了海蔽?” 一聲冷哼從身側(cè)響起共屈,我...
    開封第一講書人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤绑谣,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后拗引,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體借宵,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年矾削,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了壤玫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡哼凯,死狀恐怖欲间,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情断部,我是刑警寧澤猎贴,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站蝴光,受9級(jí)特大地震影響她渴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蔑祟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一觉渴、第九天 我趴在偏房一處隱蔽的房頂上張望侧到。 院中可真熱鬧,春花似錦、人聲如沸浙踢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)荷愕。三九已至,卻和暖如春牍帚,著一層夾襖步出監(jiān)牢的瞬間儡遮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工暗赶, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鄙币,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓蹂随,卻偏偏與公主長(zhǎng)得像十嘿,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子岳锁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359