Logtail技術(shù)分享(一) : Polling + Inotify 組合下的日志保序采集方案

日志數(shù)據(jù)采集

提到數(shù)據(jù)分析,大部分人首先想到的都是Hadoop,流計算,API等數(shù)據(jù)加工的方式。如果從整個過程來看,數(shù)據(jù)分析其實包含了4個過程:采集,存儲,計算和理解四個步驟。

采集:從各種產(chǎn)生數(shù)據(jù)的源頭,將數(shù)據(jù)集中到存儲系統(tǒng)。包括硬盤上的歷史數(shù)據(jù),用戶網(wǎng)頁的點擊,傳感器等等

存儲:以各種適合計算的模式集中式存儲數(shù)據(jù),其中既包含大規(guī)模的存儲系統(tǒng)(例如數(shù)倉),也有例如臨時的存儲(例如Kafka類消息中間件)

計算:形態(tài)多種多樣,但大部分計算完成后會將結(jié)果再放入存儲

理解:利用機(jī)器學(xué)習(xí)、可視化、通知等手段將結(jié)果呈現(xiàn)出來

數(shù)據(jù)采集是一門很大的范疇,從實時性上和規(guī)模上分,一般可以分為3類:

實時采集:例如日志,database change log等

定時任務(wù):例如每隔5分鐘從FTP或數(shù)據(jù)源去批量導(dǎo)出數(shù)據(jù)

線下導(dǎo)數(shù)據(jù):例如郵寄硬盤,AWS Snowmobile 卡車等 從數(shù)據(jù)的價值以及體量上而言,實時數(shù)據(jù)采集毫無疑問最重要的,而其中最大的部分就是日志實時采集。

日志采集Agent做了哪些工作?

日志采集Agent看起來很簡單:安裝在操作系統(tǒng)中,將實時產(chǎn)生的日志(文本)數(shù)據(jù)采集到類似消息中間件(類似Kafka)服務(wù)中。很多人可能覺得這是一個tail 命令就能干的,哪有這么復(fù)雜?

如果我們把其中細(xì)節(jié)展開就會發(fā)現(xiàn)一大堆工作,除了需要解決分布式日志匯聚的問題,還需要處理各種日志格式、不同采集目錄、不同運行環(huán)境、多租戶資源隔離、資源限制、配置管理、系統(tǒng)監(jiān)控、容錯、升級等等問題,而日志采集Agent就是為了解決這些問題應(yīng)運而生的產(chǎn)物。

試想如果不用Agent,就拿最簡單的收集nginx訪問日志來講,需要寫一個腳本定期檢測access.log有無更新,把更新的日志發(fā)送到服務(wù)端,除此之外還需要將原始訪問日志解析成key/value字段、處理日志輪轉(zhuǎn)、處理本地/服務(wù)端網(wǎng)絡(luò)異常、處理訪問流量burst時的削峰填谷、處理腳本異常等等,當(dāng)一個接一個的問題解決完之后,回過頭原來你又造了一遍輪子。

阿里云日志服務(wù)logtail就是一款進(jìn)行日志實時采集的Agent,當(dāng)前幾十萬臺部署logtail的設(shè)備運行在各種不同環(huán)境上(集團(tuán)、螞蟻、阿里云,還有用戶部署在公網(wǎng)、IOT設(shè)備),每天采集數(shù)PB的數(shù)據(jù),支撐上千種應(yīng)用的日志采集。從剛開始幾個應(yīng)用、幾千臺、每天幾T數(shù)據(jù)的規(guī)模發(fā)展到今天,我們踩過很多坑,也從中學(xué)到很多,積累了很多寶貴的經(jīng)驗。

本期主要和大家一起分享logtail設(shè)計中對于輪詢和事件模式共存情況下如何解決日志采集保序、高效、可靠的問題。

為什么要輪詢+事件

什么是輪詢什么是事件

對于日志采集,大家很容易想到通過定期檢測日志文件有無更新來進(jìn)行日志采集,這種我們一般稱之為輪詢(polling)的方式。輪詢是一種主動探測的收集方式,相對也存在被動監(jiān)聽的方式,我們一般稱之為事件模式。事件模式依賴于操作系統(tǒng)的事件通知,在linux下2.6.13內(nèi)核版本引入inotify, 而windows在xp中引入FindFirstChangeNotification,兩者都支持以被動監(jiān)聽的方式獲取日志文件的修改事件。

輪詢vs事件

下面來看看輪詢和事件之間的區(qū)別,對比如下:

輪詢事件

實現(xiàn)復(fù)雜度低高

跨平臺不依賴操作系統(tǒng)不同操作系統(tǒng)單獨實現(xiàn)

采集延遲高低

資源消耗高低

系統(tǒng)限制基本無限制依賴內(nèi)核/驅(qū)動

資源限制基本無限制依賴系統(tǒng)

大規(guī)模場景支持較差支持

輪詢相對事件的實現(xiàn)復(fù)雜度要低很多、原始支持跨平臺而且對于系統(tǒng)限制性不高;但輪詢的采集延遲(默認(rèn)加上輪詢間隔一半的采集延遲)以及資源消耗較高,而且在文件規(guī)模較大(十萬級/百萬級)時輪詢一次的時間較長,采集延遲非常高。

傳統(tǒng)Agent怎么做

一般Agent(例如logstash、fluentd、filebeats、nxlog等)都采用基于輪詢的方式,相對事件實現(xiàn)較為簡單,而且對于大部分輕量級場景基本適用。但這種方式就會暴露以上對比中出現(xiàn)的采集延遲、資源消耗以及大規(guī)模環(huán)境支持的問題,部分對于這些條件要求較高的應(yīng)用只能望而卻步。

logtail的方案是什么

為了同時兼顧采集效率以及支持各類特殊采集場景,logtail使用了輪詢與事件并存的混合方式(目前只支持linux,windows下方案正在集成中)。一方面借力inotify的低延遲與低性能消耗,另一方面使用輪詢兼容不支持事件的運行環(huán)境。然而混合方案相比純粹輪詢/事件的方案都要復(fù)雜,這里主要存在3個問題:

1. 如何解決高效采集的問題

2. 如何解決日志順序保證問題

3. 如何保證可靠性問題

下面圍繞這些問題對我們的方案進(jìn)行展開

logtail輪詢+inotify事件實現(xiàn)方式

輪詢+inotify事件混合方案簡介

logtail內(nèi)部以事件的方式觸發(fā)日志讀取行為,輪詢和inotify作為較為獨立的兩個模塊,對于同一文件/模塊會分別產(chǎn)生獨立的Create/Modify/Delete事件,事件分別存儲于Polling Event Queue和Inotify Event Queue中。

輪詢模塊由DirFilePolling和ModifyPolling兩個線程組成,DirFilePolling負(fù)責(zé)根據(jù)用戶配置定期遍歷文件夾,將符合日志采集配置的文件加入到modify cache中;ModifyPolling負(fù)責(zé)定期掃描modify cache中文件狀態(tài),對比上一次狀態(tài)(Dev、Inode、Modify Time、Size),若發(fā)現(xiàn)更新則生成modify event。

Inotify屬于事件監(jiān)聽方式,因此不存在獨立線程,該模塊根據(jù)用戶配置監(jiān)聽對應(yīng)的目錄以及子目錄,當(dāng)監(jiān)聽目錄存在變化,內(nèi)核會將事件push到相應(yīng)的file descriptor中。

最終由Event Handler線程負(fù)責(zé)將兩個事件隊列合并(merge)到內(nèi)部的Event Queue中,并處理相應(yīng)的Create/Modify/Delete事件,進(jìn)行實際的日志讀取。

高效性如何保證

相信讀者在看到混合兩個字時一定想到一個非常明顯的問題:logtail采用了兩種方案,那是不是開銷就是2倍啊?答案當(dāng)然不是,logtail在混合方案中采取了以下幾個措施來保證兩種方案混合的情況下如何采兩家之長并盡可能去兩家之短:

1. 事件合并(merge):為減少輪詢產(chǎn)生的事件和inotify產(chǎn)生的事件多次觸發(fā)事件處理行為,logtail在事件處理之前將重復(fù)的輪詢/inotify事件進(jìn)行合并,減少無效的事件處理行為;

2. 輪詢自動降級:如果在系統(tǒng)支持且資源足夠的場景下,inotify無論從延遲和性能消耗都要優(yōu)于輪詢,因此當(dāng)某個目錄inotify可以正常工作時,則該目錄的輪詢進(jìn)行自動降級,輪詢間隔大幅降低到對CPU基本無影響的程度;

3. 輪詢與inotify cache共享:日志采集中的很大一部分開銷來源于日志文件匹配,在集團(tuán)內(nèi)外經(jīng)常會出現(xiàn)一臺機(jī)器上logtail配置了上百種不同的配置的情況,對于一個文件需要對上百個配置進(jìn)行逐一判斷是否匹配。logtail內(nèi)部對于匹配結(jié)果維護(hù)了一個cache,而且cache對于輪詢和inotify共享,盡可能減少這部分較大的開銷。

日志收集順序保證

日志收集順序難點分析

日志順序性保證是日志采集需要提供的基本功能,也是較難實現(xiàn)的一種功能,尤其在以下幾種場景并存的情況下:

1. 日志輪轉(zhuǎn)(rotate):日志輪轉(zhuǎn)是指當(dāng)日志滿足一定條件(日志跨天、超過一定條數(shù)、超過一定大小)進(jìn)行重命名/壓縮/刪除后重新創(chuàng)建并寫入的情況,例如Ngnix訪問日志可設(shè)置以20M位單位進(jìn)行輪轉(zhuǎn),當(dāng)日志超過20M時,將access.log重命名為access.log.1,之前的access.log.1重命名為access.log.2,以此類推。agent需要保證日志輪轉(zhuǎn)時收集順序與日志產(chǎn)生順序相同;

2. 不同配置方式:優(yōu)秀的日志采集agent并不應(yīng)該強(qiáng)制限制用戶的配置方式,尤其在指定日志采集文件名時,有的用戶習(xí)慣配置成*.log,有的用戶習(xí)慣配置成*.log*,而無論哪種配置agent都應(yīng)該能夠兼容,不會出現(xiàn)*.log在日志輪轉(zhuǎn)情況下少收集或*.log*在日志輪轉(zhuǎn)情況下多收集的情況;

3. 輪詢與inotify并存問題:若系統(tǒng)不支持inotify,則只有輪詢產(chǎn)生的事件,而若inotify正常工作,那么同一文件的修改會產(chǎn)生兩次事件,而且由于inotify延遲較低,所以事件很可能會先于輪詢的事件被處理。我們需要保證延遲到來的事件不會影響日志exactly once的讀取;

基于輪轉(zhuǎn)隊列與文件簽名的日志采集方法

基本概念

在logtail中,我們設(shè)計了一套用于在日志輪轉(zhuǎn)、不同用戶配置、輪詢與inotify并存、日志解析阻塞情況下依然可以保證日志采集順序的機(jī)制。本文將重點該機(jī)制的實現(xiàn)方法,在展開之前首先介紹logtail中用到的幾個基本概念:

文件的dev和inode標(biāo)識

dev這里指的是設(shè)備編號、inode是該文件在file system中的唯一標(biāo)識,通過dev+inode的組合可唯一標(biāo)識一個文件(這里需要排除硬連接)。文件的move操作雖然可以改變文件名,但并不涉及文件的刪除創(chuàng)建,dev+inode并不會變化,因此通過dev+inode可以非常方便的判斷一個文件是否發(fā)生了輪轉(zhuǎn)。

inode引用計數(shù)

每個文件都對應(yīng)著一個inode,inode指向文件的meta信息,其中有一個字段是reference count,默認(rèn)文件創(chuàng)建時引用計數(shù)為1,引用計數(shù)為0時文件被文件系統(tǒng)回收。以下情況會改變文件的引用計數(shù):若文件open,則引用計數(shù)加1,文件close后減1;硬連接創(chuàng)建引用計數(shù)加1;文件/硬鏈接刪除,引用計數(shù)減1。因此,雖然文件被刪除,但只要有應(yīng)用保持該文件的open狀態(tài),則該文件并不會被文件系統(tǒng)回收,應(yīng)用還可以對該文件進(jìn)行讀取。

文件簽名(signature)

dev+inode只能保證同一時刻該文件的唯一性,但并不代表整個life cycle中的唯一性。在文件從文件系統(tǒng)中刪除時,對應(yīng)的inode也會被回收,內(nèi)核file system實現(xiàn)中存在分配唯一inode的機(jī)制,為了提高inode分配性能,回收的inode會保留在文件系統(tǒng)的cache中,下一次創(chuàng)建文件時,若存在inode cache則直接將該inode賦給新文件。因此純粹通過dev+inode判斷輪轉(zhuǎn)并不可行(例如日志文件到達(dá)一定size被刪除后,重新創(chuàng)建繼續(xù)寫,只要期間沒有其他文件創(chuàng)建,則dev+inode都沒變),logtail中使用日志文件的前1024字節(jié)的hash作為該文件的簽名(signature),只有當(dāng)dev+inode+signature一致的情況下才會認(rèn)為該文件是輪轉(zhuǎn)的文件。

在logtail的設(shè)計中利用了以上幾個概念的功能,下面介紹一下日志收集順序保證的幾個數(shù)據(jù)結(jié)構(gòu):

LogFileReader

LogFileReader存儲了日志文件讀取的元數(shù)據(jù),包括sorcePath、signature、devInode、deleteFlag、filePtr、readOffset、lastUpdateTime、readerQueue(LogFileReaderQueue)。其中sorcePath是reader文件路徑,,signature是文件的簽名,devInode是改文件的dev+inode組合,deleteFlag用于標(biāo)識該文件是否被刪除,filePtr是文件指針,readOffset代表當(dāng)前日志解析進(jìn)度,lastUpdateTime記錄最后一次進(jìn)行讀取的時間,readerQueue標(biāo)識該reader所在的讀取隊列(參見下面介紹)。

LogFileReaderQueue

LogFileReaderQueue中存儲sourcePath相同且未采集完畢的reader列表,reader按照日志文件創(chuàng)建順序進(jìn)行排列。

NamedLogFileReaderQueueMap

以sourcePath為key/LogFileReaderQueue為value的map,用于存儲當(dāng)前正在讀取的所有ReaderQueue

DevInodeLogFileReaderMap

以devInode為key/LogFileReader為value的map,用于存儲當(dāng)前正在讀取的所有Reader

RotatorLogFileReaderMap

以devInode為key/LogFileReader為value的map,用于存儲處于輪轉(zhuǎn)狀態(tài)且已經(jīng)讀取完畢的Reader

事件處理流程

logtail基于以上的數(shù)據(jù)結(jié)構(gòu)實現(xiàn)了日志數(shù)據(jù)順序讀取,具體處理流程如下:

CreateEvent處理方式

對于日志的Create Event,首先從當(dāng)前的devInodeReaderMap中查找是否存在該dev+inode的Reader(因為在輪詢和Inotify共存的情況下,可能會出現(xiàn)在處理Create Event時Reader已經(jīng)被創(chuàng)建的情況),若不存在則創(chuàng)建Reader。

Reader通過dev+inode和sourcePath創(chuàng)建,創(chuàng)建Reader后需加入到devInodeReaderMap以及其sourcePath對應(yīng)的ReaderQueue尾部

DeleteEvent處理方式

對于日志文件的Delete Event,若該Reader所在隊列長度大于1(當(dāng)前解析進(jìn)度落后,文件雖被刪除但日志未采集完成),則忽略此Delete事件;若Reader所在隊列長度為1,設(shè)置該Reader的deleteFlag,若一定時間內(nèi)該Reader沒有處理過Modify事件且日志解析完畢則刪除該Reader

ModifyEvent處理方式

首先根據(jù)dev+inode查找devInodeReaderMap,找到該Reader所在的ReaderQueue,獲取ReaderQueue的隊列首部的Reader進(jìn)行日志讀取操作;

日志讀取時首先檢查signature是否改變,若改變則認(rèn)為日志被truncate寫,從文件頭開始讀取;若signature未改變,則從readOffset處開始讀取并更新readOffset

若該日志文件讀取完畢(readOffset==fileSize)且ReaderQueue的size > 1,則從ReaderQueue中移除該Reader并加入到rotatorReadrMap中(日志已經(jīng)發(fā)生了輪轉(zhuǎn),且輪轉(zhuǎn)后的文件已經(jīng)讀取完畢,所以可以從ReaderQueue中移除),此時繼續(xù)把Modify Event push到Event隊列中,觸發(fā)隊列后續(xù)文件的讀取,進(jìn)入下一循環(huán);若日志文件讀取完畢且ReaderQueue的size==1(size為1說明該文件并沒有輪轉(zhuǎn),極有可能后續(xù)還有寫入,所以不能從ReaderQueue中移除),則完成次輪Modify Event處理,進(jìn)入下一循環(huán)

若日志文件沒有讀取完成,則把Modify Event push到Event隊列中,進(jìn)入下一循環(huán)(避免所有時間都被同一文件占用,保證日志文件讀取公平性)

RotatorLogFileReaderMap主要用于解決輪詢事件延遲問題:當(dāng)inotify事件處理完成、日志讀取完畢、ReaderQueue size > 1同時發(fā)生,若直接刪除該Reader,則輪詢的事件到達(dá)時,將會查找不到Reader并創(chuàng)建一個新的Reader重新進(jìn)行日志讀取。因此我們在Reader讀取完畢時將其放入到RotatorLogFileReaderMap保存,若事件查找不到Reader時會檢測RotatorLogFileReaderMap,若存在則跳過此次事件處理,避免多重事件造成日志重復(fù)采集的情況。

日志采集可靠性保證

考慮到性能、資源、性價比等問題,logtail在設(shè)計之初并不保證exact once或者at least once,但這并不代表logtail不可靠,有很多用戶基于logtail采集的access日志用來計費。下面主要介紹可靠性中較難解決的三個場景:

1. 日志解析阻塞:由于各種原因(網(wǎng)絡(luò)阻塞、日志burst寫入、流量控制、CPU/磁盤負(fù)載)等問題可能造成日志解析進(jìn)度落后于日志產(chǎn)生速度,而在此時若發(fā)生日志輪轉(zhuǎn),logtail需在有限資源占用情況下盡可能保證輪轉(zhuǎn)后的日志文件不丟失

2. 采集配置更新/進(jìn)程升級:配置更新或進(jìn)行升級時需要中斷采集并重新初始化采集上下文,logtail需要保證在配置更新/進(jìn)程升級時即使日志發(fā)生輪轉(zhuǎn)也不會丟失日志

3. 進(jìn)程crash、宕機(jī)等異常情況:在進(jìn)程crash或宕機(jī)時,logtail需盡可能保證日志重復(fù)采集數(shù)盡可能的少丟失日志

日志采集阻塞處理

正常情況下,日志采集進(jìn)度和日志產(chǎn)生進(jìn)度一致,此時ReaderQueue中只有一個Reader處于采集狀態(tài)。如上圖所示,正在被采集的access.log由于磁盤上存在、應(yīng)用和logtail正在打開,所以引用計數(shù)為3,其他輪轉(zhuǎn)的日志文件引用計數(shù)為1。

而當(dāng)應(yīng)用日志burst寫入、網(wǎng)絡(luò)暫時性阻塞、服務(wù)端Quota不足、CPU/磁盤負(fù)載較高等情況發(fā)生,日志采集進(jìn)度可能落后于日志產(chǎn)生進(jìn)度,此時我們希望logtail能夠在一定的資源限制下盡可能保留住這些日志,等待網(wǎng)絡(luò)恢復(fù)或系統(tǒng)負(fù)載下降時將這些日志采集到服務(wù)器,并且保證日志采集順序不會因為采集阻塞而混亂。

如上圖所示,logtail內(nèi)部通過保持輪轉(zhuǎn)日志file descriptor的打開狀態(tài)來防止日志采集阻塞時未采集完成的日志文件被file system回收(在ReaderQueue中的file descriptor一直保持打開狀態(tài),保證文件引用計數(shù)至少為1)。通過ReaderQueue的順序讀取保證日志采集順序與日志產(chǎn)生順序一致。

當(dāng)ReaderQueue的size大于1時說明日志解析出現(xiàn)阻塞,此時logtail會將該ReaderQueue中所有Reader的file descriptor保持打開狀態(tài),這樣即使在日志文件輪轉(zhuǎn)后被刪除或被壓縮(本質(zhì)還是被刪除)時logtail依然能夠采集到該日志。

當(dāng)日志輪轉(zhuǎn)時(dev+inode變化,文件名未變),logtail會根據(jù)新的dev+inode創(chuàng)建Reader,并加入其文件名對應(yīng)的ReaderQueue尾部,ReaderQueue保持順序讀取,以此保證日志文件解析順序。

若日志采集進(jìn)度一直低于日志產(chǎn)生進(jìn)度,則很有可能出現(xiàn)ReaderQueue會無限增長的情況,因此logtail內(nèi)部對于ReaderQueue設(shè)置了上限,當(dāng)size超過上限時禁止后續(xù)Reader的創(chuàng)建

配置更新/升級過程處理

logtail配置采用中心化的管理方式,用戶只需在管理頁面配置,保存后會自動將配置更新到遠(yuǎn)程的logtail節(jié)點。此外logtail具備自動升級的功能,當(dāng)推出新版本時,logtail會自動從服務(wù)器下載最新版本并升級到該版本。

為保證配置更新/升級過程中日志數(shù)據(jù)不丟失,在logtail升級過程中,會將當(dāng)前所有Reader的狀態(tài)保存到內(nèi)存/本地的checkpoint文件中;當(dāng)新配置應(yīng)用/新版本啟動后,會加載上一次保存的checkpoint,并通過checkpoint恢復(fù)Reader的狀態(tài)。

然而在老版本checkpoint保存完畢到新版本Reader創(chuàng)建完成的時間段內(nèi),很有可能出現(xiàn)日志輪轉(zhuǎn)的情況,因此新版本在加載checkpoint時,會檢查對應(yīng)checkpoint的文件名、dev+inode有無變化

若文件名與dev+inode未變且signature未變,則直接根據(jù)該checkpoint創(chuàng)建Reader

若文件名與dev+inode變化則從當(dāng)前目錄查找對應(yīng)的dev+inode,若查找到則對比signature是否變化;若signature未變則認(rèn)為是文件輪轉(zhuǎn),根據(jù)新文件名創(chuàng)建Reader;若signature變化則認(rèn)為是該文件被刪除后重新創(chuàng)建,忽略該checkpoint。

進(jìn)程crash、宕機(jī)等異常情況處理

進(jìn)程異常crash:logtail運行時會產(chǎn)生兩個進(jìn)程,分別是守護(hù)進(jìn)程和工作進(jìn)程,當(dāng)工作進(jìn)程異常crash時(概率極低)守護(hù)進(jìn)程會立即重新拉起工作進(jìn)程

進(jìn)程重新啟動時狀態(tài)恢復(fù):logtail除配置更新/進(jìn)程升級會保存checkpoint外,還會定期將采集進(jìn)度dump到本地,進(jìn)程重新啟動的過程與版本升級的過程相似:除了恢復(fù)正常日志文件狀態(tài)外,還會查找輪轉(zhuǎn)后的日志,盡可能降低日志丟失風(fēng)險

click.aliyun.com/m/30605/原文鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,517評論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,087評論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,521評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,493評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,207評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,603評論 1 325
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,624評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,813評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,364評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,110評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,305評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,874評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,532評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,953評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,209評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,033評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,268評論 2 375

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

  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 11,067評論 6 13
  • 一個基本的計算機(jī)系統(tǒng)由“硬件”和“軟件”組成,一臺Linux設(shè)備,主要的組成如下圖所示: 一般情況下,我們所說的L...
    時待吾閱讀 1,660評論 0 16
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,810評論 18 139
  • 今天傍晚,孩子說他想要大象鈣片,他們班某某都吃了。我領(lǐng)著他去藥店,去了兩家都沒有。回家后他依然哭鬧。眼看七點了,桌...
    閆苑苑閱讀 259評論 0 0
  • VPN好像還是不行,明天繼續(xù)看一下。然后明天下午唱K去~
    GSES94閱讀 145評論 0 0