Pomelo框架參考

翻譯:死月咬最,校對:葉岬原文連接

Pomelo(柚子)是一個可以讓開發(fā)者便捷開發(fā)的游戲服務(wù)端框架。下面是其一些Pomelo的主要設(shè)計思想。

概述

在這一節(jié)中我們會展示Pomelo是什么抛虫。

在游戲服務(wù)端中通常有著各種各樣的任務(wù)松靡,形如客戶端連接的管理简僧、游戲世界狀態(tài)的管理以及計算游戲的邏輯。不同的任務(wù)可能會又不同的資源需求雕欺,比如IO開銷或者CPU開銷等岛马。但是在一個進程中處理所有的作業(yè)顯然是非常不切實際的。所以將一個游戲服務(wù)端分割成一些簡小服務(wù)端進程是一種趨勢屠列。每個服務(wù)端只需處理一種單一的服務(wù)啦逆,比如說連接服務(wù)、場景服務(wù)或者聊天服務(wù)笛洛。所有這些服務(wù)進程之間都有著互相的聯(lián)系夏志,從而構(gòu)成整個大千游戲世界。

要從頭開發(fā)一個基于上述模型的游戲服務(wù)端的話苛让,必須消耗非常多的時間沟蔑,而且處理起那些形如服務(wù)端資源規(guī)劃、建立以及管理網(wǎng)絡(luò)連接狱杰、進程間發(fā)送和接收消息等非常冗雜的作業(yè)也會顯得非常力不從心瘦材。更糟糕的是,這些作業(yè)在開始一個新游戲的時候又得不斷重復(fù)仿畸。所以就需要有一個救世主來把你從繁雜冗余重復(fù)的工作中拯救出來食棕,比如說BigWorld引擎(非常著名和給力朗和,同時也非常貴和復(fù)雜)。現(xiàn)在Pomelo給你提供來另一個選擇(開源簿晓,簡單眶拉,迅捷)來達到你的要求。

Pomelo框架包括以下的功能模塊:

Pomelo框架
Pomelo框架

<center><small>Pomelo 結(jié)構(gòu)</small></center>

  • 服務(wù)端管理模塊負(fù)責(zé)定義服務(wù)端類型憔儿,建立和監(jiān)控所有服務(wù)進程镀层。
  • 網(wǎng)絡(luò)模塊是進程間通信的基礎(chǔ),也提供了RPC和頻道(Channel)來隱藏所有的底層詳情皿曲。
  • 應(yīng)用模塊代表了關(guān)注配置和生命周期管理相關(guān)的服務(wù)流程的進程上下文環(huán)境唱逢。(求大神翻譯這句)

服務(wù)器類型

Pomelo在為一個游戲服務(wù)器群集可定制所有服務(wù)端模板的基礎(chǔ)上提供一個靈活的服務(wù)端類型系統(tǒng)。它將服務(wù)端類型分為兩大類——前端服務(wù)端和后端服務(wù)端屋休。

Pomelo服務(wù)端類型
Pomelo服務(wù)端類型

<center><small>Pomelo服務(wù)端類型</small></center>

總而言之坞古,前端服務(wù)端是負(fù)責(zé)與客戶端的通信然后把這些請求轉(zhuǎn)發(fā)給后端服務(wù)端,而后端服務(wù)端就是實現(xiàn)游戲邏輯的戰(zhàn)場了劫樟。

本質(zhì)上痪枫,前端和后端服務(wù)端都是服務(wù)端容器〉蓿基于服務(wù)端容器奶陈,開發(fā)者可以根據(jù)自己的意愿自由定制他們的服務(wù)端類型。開發(fā)者擁有全部的權(quán)限來決定一個服務(wù)端需要提供哪種類型的服務(wù)附较。比如說吃粒,你如果在后端服務(wù)端碼了聊天服務(wù)的代碼那么你就可以弄出一個聊天服務(wù)端,又比如你在后端服務(wù)端碼了狀態(tài)服務(wù)的代碼你也可以搞出一個狀態(tài)服務(wù)端拒课。

所以啊開發(fā)者們只需要在Pomelo上面掐指一算來決定需要多少前段服務(wù)端和后端服務(wù)端來堆成一坨游戲服務(wù)端徐勃,然后為這些服務(wù)端結(jié)點碼上應(yīng)有的代碼。接著Pomelo就會開始滾動然后能滾起所有的服務(wù)進程早像。

服務(wù)端容器
服務(wù)端容器

<center><small>服務(wù)端容器</small></center>

客戶端請求機制

這一節(jié)我們會講一下服務(wù)端是如何處理客戶端請求的僻肖。

請求和響應(yīng)

在Pomelo里,消息將為氛圍兩類——請求和通知卢鹦。這兩者的不同點如下所示:

請求和通知
請求和通知

<center><small>請求和通知</small></center>

請求是雙向消息臀脏,也就是說服務(wù)端接收到一個客戶端消息的時候就得發(fā)回客戶端一個響應(yīng)消息。這個時候Pomelo就會射出一個與請求相關(guān)聯(lián)的回調(diào)冀自∪嘀桑客戶端如下弄出一個請求:

pomleo.request('connector.helloHandler.ask',
    {
        msg: 'What is your name?'
    }, function(resp) 
    {
        // We can get the name from response
    }
);

然后通知就是單向消息,服務(wù)端不需要提供相應(yīng)凡纳∏灾玻客戶端需如下弄出一個請求:

pomelo.notify('connector.helloHandler.sayHi',
    {
        msg: 'Hi'
    }
);

如何處理客戶端消息

Pomelo將進程流*分為兩部分:處理機和過濾器。處理機負(fù)責(zé)提供游戲邏輯荐糜,過濾器需要做前置和后續(xù)工作巷怜,比如日志和超時處理等葛超。兩者分工如下圖所示:

客戶端請求處理
客戶端請求處理

前置過濾器

客戶端而來的消息需要通過前置過濾器鏈來做一些前置處理,比如說驗證當(dāng)前玩家登錄狀態(tài)以及日志記錄延塑。前置過濾器的接口如下:

filter.before = function(msg, session, next)

msg是從客戶端接收的消息對象绣张;session是當(dāng)前玩家的會話對象;next是接下去的流程的回調(diào)函數(shù)关带。

前置過濾器需要調(diào)用next函數(shù)來跑到前置過濾器鏈中的下一個前置過濾器侥涵。當(dāng)它穿過了整條前置過濾器鏈時,它將最終撲進處理機的懷抱宋雏。如果next函數(shù)的第一個參數(shù)傳入錯誤芜飘,那么說明蹦跶出了一個錯誤,就需要停止這個進程流磨总,比如說這個玩家不自覺還沒有登錄嗦明。這時這個消息就需要被傳進一個全局錯誤處理機(稍后再做解釋)。

處理機

處理機是實現(xiàn)游戲邏輯的天堂蚪燕。它的接口如下:

handler.methodName = function(msg, session, next)

參數(shù)跟前置過濾器差不多娶牌。處理一個請求消息時,處理機需要傳進響應(yīng)對象馆纳,這是一個簡單的Json對象诗良,將作為下一個回調(diào)函數(shù)的第二個參數(shù)。對于一個通知消息來說鲁驶,只需要將第二個參數(shù)留空即可鉴裹。

如果在處理的過程中又蹦跶出了一個錯誤,只需要傳入一個錯誤對象給next函數(shù)的第一個參數(shù)即可灵嫌,跟之前的前置過濾器一樣壹罚。

錯誤處理機

錯誤處理機是一個可選項葛作,它將處理全局錯誤——比如說未知錯誤的處理以及錯誤的報告寿羞。錯誤處理機如下設(shè)置:

app.set('errorHandler', handleFunc);

一個錯誤處理機的接口又該如下申明:

errorHandler = function(err, msg, resp, session, next)

err是前置過濾器或者處理機傳給的錯誤對象;resp是處理機本來將要傳給客戶端的響應(yīng)消息。剩下的參數(shù)跟之前講的一樣赂蠢。

后續(xù)過濾器

前面講的進程流最終會由后續(xù)過濾器來擦屁股绪穆。后續(xù)過濾器將負(fù)責(zé)后續(xù)的處理,比如釋放請求上下文資源虱岂,記錄該請求的處理時間玖院。不過它不要修改響應(yīng)消息,因為其實在進入這個后續(xù)過濾器鏈中之前第岖,消息就已經(jīng)被一股腦發(fā)送到客戶端了难菌。

后續(xù)過濾器接口聲明如下:

filter.after = function(err, msg, resp, session, next)

所有的參數(shù)都跟之前說的一樣。

會話

會話是一個保持玩家狀態(tài)的鍵對對象蔑滓,它可以是以這個玩家id作為鍵名郊酒。Pomelo擁有兩種類型的會話:全局會話和本地會話遇绞。

全局會話是由與客戶端直連的前端服務(wù)端生成的并且就位于前端服務(wù)端。這是存儲玩家信息的全局地方燎窘。傳客戶端消息的時候它將弄出一個拷貝和客戶端消息一起傳給后端服務(wù)端摹闽。這時后端服務(wù)端就會得到一份會話拷貝,也就是本地會話了褐健。

本地會話應(yīng)該是一個只讀的對象付鹿,至少只在本地是可讀寫的*。在本地會話的修改并不會影響到全局上的那位蚜迅。如果你想將本地會話同步到全局會話的話就需要調(diào)用推送本地會話的方法舵匾。更多細(xì)節(jié)請參考API文檔中的本地會話服務(wù)。

頻道和廣播

在這一節(jié)我們會搞一下服務(wù)器是如何把消息推送給客戶端的谁不。

頻道

屎一樣多的消息將要在游戲服務(wù)端被推送纽匙,比如當(dāng)一個玩家在一個場景中從A點移動到B點的時候,服務(wù)器就需要推送一個AOI(Area of Interest)消息給周圍的玩家拍谐。頻道就是推送消息的這么個工具烛缔。

頻道是一個玩家ID的合集。你可以把一個玩家ID加入到某個頻道轩拨,同樣也可以從中移除践瓷。如果你通過頻道來推送消息,那么該頻道中的所有成員都將收到這條消息亡蓉。你可以創(chuàng)建任意多個頻道來自定義消息推送區(qū)域晕翠,這些頻道互相之間是獨立的。

頻道分類

Pomelo有兩種頻道:命名頻道和匿名頻道砍濒。

創(chuàng)建一個命名頻道時淋肾,你需要給它指定一個頻道名,這樣它才會返回一個頻道實例爸邢。命名頻道并不會自動釋放樊卓,你需要記得調(diào)用 channel.destroy 方法來釋放它。命名頻道通常用來保持長時間關(guān)系的訂閱杠河,比如說聊天服務(wù)碌尔。

匿名頻道通過 channelService.pushMessageByUids 來使用的,沒有頻道名也沒有頻道實例返回券敌。匿名頻道用于那些頻道成員變動頻繁的或者推送的都是臨時消息的時候唾戚,比如AOI消息。

頻道的更多用法請參見API文檔待诅。

這兩種頻道本質(zhì)上都是相同的叹坦,即使他們看起來是兩個媽生的。首先卑雁,頻道需要將連接至它們的前端服務(wù)端分組募书。然后它需要將消息連通玩家ID通過分組一起推送到各自的前端服務(wù)端轧钓,最后天女散花至各個客戶端。

頻道廣播
頻道廣播

<center><small>頻道廣播</samll></center>

RPC框架

在這一節(jié)锐膜,我們將解決各服務(wù)端之間通信不打架的問題毕箍。

RPC的用途

進程間需要互相配合合作,它們之間的通信是非常重要且復(fù)雜的道盏。Pomelo的RPC(Remote Procedure Call而柑,遠(yuǎn)程過程調(diào)用)框架就是一個將進程們?nèi)嗄笤谝黄鸬挠行侄巍?/p>

下面就是Pomelo的RPC框架需要思考的一些點。

  • 路由規(guī)則荷逞。路由規(guī)則決定一條消息應(yīng)該傳給哪個進程媒咳。路由規(guī)則與消息類型不同,不過它也同樣會被當(dāng)前玩家狀態(tài)或者其它一些東東影響种远。比如客戶端的一個簡單移動請求涩澡,當(dāng)當(dāng)前玩家處于場景1中,它就需要被路由給管理場景1的進程坠敷。如果玩家被傳送到場景2妙同,那么這之后的所有移動請求都需要被路由給場景2的進程中。而且不同的游戲這個規(guī)則是不同的膝迎。所以這里就需要一個開放的機制來讓開發(fā)者好定義路由規(guī)則粥帚。
  • 協(xié)議。不同游戲的服務(wù)端進程間的請求通信協(xié)議也是不同的限次。比如說有些服務(wù)端想要TCP協(xié)議芒涡,而有些則對UDP欲求不滿。

Pomelo的RPC框架引入抽象層來簡化和解決以上所述的問題卖漫。

RPC客戶端

RPC客戶端層體系結(jié)構(gòu)如下:

RPC客戶端體系結(jié)構(gòu)
RPC客戶端體系結(jié)構(gòu)

<center><small>RPC客戶端體系結(jié)構(gòu)</small></center>

上圖中RPC消息是一個文本消息费尽,包含一個RPC請求的描述,它包括RPC請求類型羊始、參數(shù)以及其它一些東西旱幼。Session是啟動RPC請求的玩家狀態(tài)的一個合集。

  • 郵箱層——郵箱層解決了通信協(xié)議的問題店枣。一個郵箱代表一個遠(yuǎn)程服務(wù)端速警,并且使用遠(yuǎn)程服務(wù)端ID作為該郵箱的ID,這樣就能通過服務(wù)端ID非常方便地找到相關(guān)聯(lián)的郵箱實例鸯两。郵箱實例涵蓋了當(dāng)前服務(wù)端與遠(yuǎn)程服務(wù)端的所有通信細(xì)節(jié),比如說如何建立連接长豁,該用何種協(xié)議钧唐,如何關(guān)閉連接等等。你可以實現(xiàn)不同的郵箱來讓它們支持不同的協(xié)議匠襟,而且它們的通信協(xié)議能很方便地進行切換钝侠,因為你只需要在郵箱層選擇合適的郵箱就可以了该园。
  • 郵局層——郵局層維持了當(dāng)前進程的所有郵箱實例。它會將RPC消息從上層通過郵箱ID傳送給對應(yīng)的郵箱實例帅韧。郵局層接收到一個決定對應(yīng)一個遠(yuǎn)程服務(wù)端將要生成何種類型的郵箱的郵箱工廠函數(shù)里初,然后返回一個相關(guān)聯(lián)的郵箱實例。對于一個服務(wù)端第一次嘗試連接遠(yuǎn)程服務(wù)端時忽舟,它將詢問郵箱工廠以生成一個郵箱實例双妨。所以開發(fā)者需要通過郵箱工廠函數(shù)來自定義通信機制。
  • 路由層——路由層用來提供路由規(guī)則叮阅。它接受一個路由函數(shù)刁品,然后用它來通過上層的RPC消息和會話決定目標(biāo)進程ID。然后這個ID就會通過郵局層浩姥,正如上文所述挑随。
  • 代理層——代理層提供了使調(diào)用遠(yuǎn)程方法看起來就像在調(diào)用本地方法并且隱藏所有RPC細(xì)節(jié)的本地代理實例。本地代理方法和遠(yuǎn)程方法的唯一區(qū)別在于它多了個會話(session)參數(shù)勒叠,包含了當(dāng)前玩家的狀態(tài)兜挨,這個參數(shù)在參數(shù)槽的第一個位置。下面是一個簡單的例子:

遠(yuǎn)程服務(wù):

remote.echo = function(msg, cb) {
  // …
};

本地代理:

proxy.echo = function(session, msg, cb) {
  // …
};

還有一個好辦法來調(diào)用遠(yuǎn)程函數(shù)眯分,那就是如果目標(biāo)服務(wù)端ID直接可用暑劝,那么可以通過調(diào)用rpcInvoke*函數(shù)來實現(xiàn)。

RPC服務(wù)端

RPC服務(wù)端的層次如下:

RPC服務(wù)端結(jié)構(gòu)體系
RPC服務(wù)端結(jié)構(gòu)體系

<center><small>RPC服務(wù)端結(jié)構(gòu)體系</small></center>

  • 接收器層(受體層)——接收器層通過網(wǎng)絡(luò)將遠(yuǎn)程服務(wù)導(dǎo)出颗搂。它將會監(jiān)聽一個端口担猛,通過指定協(xié)議接收以及解析RPC消息。需要指出的是丢氢,受體得與遠(yuǎn)程的同行們的郵箱層進行合作傅联,也就是說它們得用同樣的協(xié)議來使它們與各自能進行無障礙通信。接收器同樣是被接收器工廠函數(shù)定制的疚察。而且接收器得將RPC消息傳往上層蒸走。
  • 調(diào)度層——調(diào)度層解析RPC消息,導(dǎo)出消息類型以及RPC參數(shù)貌嫡,然后將RPC請求轉(zhuǎn)發(fā)至目標(biāo)遠(yuǎn)程服務(wù)比驻。
  • 遠(yuǎn)程服務(wù)層——遠(yuǎn)程服務(wù)層實現(xiàn)了開發(fā)者提供的服務(wù)邏輯,由Pomelo框架自動載入岛抄。

服務(wù)端擴展

這一節(jié)别惦,灑家一起討論討論如何擴展服務(wù)端進程的能力。

正如之前提到的夫椭,我們創(chuàng)建了很多類型的服務(wù)端掸掸,每個服務(wù)端都有自己的牛叉之處。比如說,前段服務(wù)端有著從客戶端接收消息的能力扰付,后端服務(wù)端有著從前段服務(wù)端進貢的消息堤撵。那么,我們又該如何維護和重用這些厲害的地方呢羽莺?此外实昨,我們該如何以非常優(yōu)雅和靈動的方式來擴展這些進程的能力呢?

“合體(組合)”將會是一個非常合適的途徑盐固。Pomelo有著一個組件系統(tǒng)來達到這個目標(biāo)荒给。

組件

組件是啥

在Pomelo里面,組件是可重用的服務(wù)單位闰挡。一個組件實例提供了若干種服務(wù)锐墙。比如說處理機組件載入處理機代碼后將會將客戶端消息傳給請求處理機。

一個組件實例要被注冊進進程上下文(被稱為應(yīng)用)长酗,這樣后者就會獲得該實例提供的能力溪北。組件實例可以通過應(yīng)用與其它組件進行交互合作。比方說一個連接組件接收到一個客戶端請求然后將它發(fā)送給應(yīng)用夺脾,那么一個處理機組件等下就有可能從應(yīng)用中獲取這條消息之拨。

組件系統(tǒng)模型如下所示:

組件系統(tǒng)
組件系統(tǒng)

<center><small>組件系統(tǒng)</small></center>

在代碼里面,組件是一個非常簡單的類咧叭,實現(xiàn)了一些必須的生命周期接口蚀乔,應(yīng)用需要觸發(fā)生命周期每個階段每個組件所需的回調(diào)函數(shù)。

組件的生命周期
組件的生命周期

<center><small>組件的生命周期</small></center>

  • start(cb)——服務(wù)端在啟動階段被調(diào)用的開始生命周期菲茬。注意:各組件需要調(diào)用cb函數(shù)來繼續(xù)接下去的步驟吉挣。組件也可以傳入一個粗偶的參數(shù)給cb來表示當(dāng)前組件啟動失敗,以此來使應(yīng)用結(jié)束這個進程婉弹。
  • afterStart(cb)——服務(wù)端在啟動之后的生命周期階段回調(diào)睬魂,需要在當(dāng)前進程所有被注冊組件啟動之后調(diào)用。它給這些組件進行一些協(xié)作間初始化的機會镀赌。
  • stop(force, cb)——服務(wù)端在停止生命周期階段的回調(diào)氯哮,當(dāng)服務(wù)端將要停止的時候調(diào)用。組件可以做一些清理作業(yè)商佛,比如沖刷此周期中的數(shù)據(jù)到數(shù)據(jù)庫喉钢。force參數(shù)如果為true的話表示所有的組件都需要被立即停止。

Pomelo的抽象級

基于組件系統(tǒng)良姆,應(yīng)用實際上是進程的骨干肠虽。它載入了所有的注冊組件,鞭策它們穿越了整個生命周期歇盼。但是應(yīng)用不能涉及到各組件的細(xì)節(jié)舔痕。所有的定制一個服務(wù)端進程的作業(yè)僅僅只是挑選必須的組件構(gòu)成一個應(yīng)用。所以應(yīng)用是非常干凈和靈活的豹缀,而組件的可重用性非常高伯复。此外,組件系統(tǒng)最終將所有服務(wù)端類型弄進一個統(tǒng)一進程邢笙。

Pomelo的抽象級
Pomelo的抽象級

<center><small>Pomelo的抽象級</small></center>

怎么注冊一個組件

如下:

app.load([name], comp, [opts])
  • name——可選的組件名啸如。命名的組件實例可以在被載入后通過app.components.name來訪問。
  • comp——組件實例或者組件工廠函數(shù)氮惯。如果comp是一個函數(shù)叮雳,那么應(yīng)用將會把它當(dāng)做一個工廠函數(shù),并且讓它返回一個組件實例妇汗。工廠函數(shù)有兩個參數(shù)appopts(看下文)帘不,并且它將返回一個組件實例。
  • opts——可選項杨箭,它將被傳入至組件工廠函數(shù)的第二個參數(shù)寞焙。

總結(jié)

我們將一整個服務(wù)端分尸成一些小塊服務(wù)端,以此來清晰化結(jié)構(gòu)體系和提高游戲服務(wù)端的可擴展性互婿。然后我們將所有的服務(wù)類型綜合成兩種服務(wù)端容器即前段和后端服務(wù)端捣郊,通過這樣的方式來簡化模型。我們討論了客戶端到服務(wù)端慈参、服務(wù)端到客戶端以及服務(wù)端之間的消息流。最后,我們介紹了組件系統(tǒng)占贫,把上面的所有物件合體構(gòu)成一個有機的整體同诫。總的看來壮锻,Pomelo提供了一個可擴展的靈活的框架來支持游戲服務(wù)端開發(fā)琐旁,并且趕走了所有的“躁點”和復(fù)雜的作業(yè)。

享受Pomelo的游戲開發(fā)過程吧躯保,親們旋膳!

更多信息請參見API文檔快速開始手冊結(jié)構(gòu)體系概述途事。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末验懊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子尸变,更是在濱河造成了極大的恐慌义图,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件召烂,死亡現(xiàn)場離奇詭異碱工,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門怕篷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來历筝,“玉大人,你說我怎么就攤上這事廊谓∈嶂恚” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵蒸痹,是天一觀的道長春弥。 經(jīng)常有香客問我,道長叠荠,這世上最難降的妖魔是什么匿沛? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮榛鼎,結(jié)果婚禮上逃呼,老公的妹妹穿的比我還像新娘。我一直安慰自己借帘,他們只是感情好蜘渣,可當(dāng)我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著肺然,像睡著了一般蔫缸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上际起,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天拾碌,我揣著相機與錄音,去河邊找鬼街望。 笑死校翔,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的灾前。 我是一名探鬼主播防症,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼哎甲!你這毒婦竟也來了蔫敲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤炭玫,失蹤者是張志新(化名)和其女友劉穎奈嘿,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吞加,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡裙犹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年尽狠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片叶圃。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡袄膏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盗似,到底是詐尸還是另有隱情哩陕,我是刑警寧澤平项,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布赫舒,位于F島的核電站,受9級特大地震影響闽瓢,放射性物質(zhì)發(fā)生泄漏接癌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一扣讼、第九天 我趴在偏房一處隱蔽的房頂上張望缺猛。 院中可真熱鬧,春花似錦椭符、人聲如沸荔燎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽有咨。三九已至,卻和暖如春蒸健,著一層夾襖步出監(jiān)牢的瞬間座享,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工似忧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留渣叛,地道東北人。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓盯捌,卻偏偏與公主長得像淳衙,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子饺著,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,527評論 2 349

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