Nacos 配置實(shí)時(shí)更新原理分析

上篇文章《Nacos 配置中心原理分析》我和大家分析了 Nacos 的配置中心原理们衙,主要分析了 Nacos 客戶(hù)端是如何感知到服務(wù)端的配置變更的戴差,但是只是從客戶(hù)端的角度進(jìn)行了分析布轿,并沒(méi)有從服務(wù)端的角度進(jìn)行分析谎势,本篇文章我將結(jié)合服務(wù)端從兩個(gè)角度來(lái)分析配置變更是如何通知到客戶(hù)端的壶笼。

PS:文章有點(diǎn)長(zhǎng)狮腿,因?yàn)樯婕暗蕉鄠€(gè)細(xì)節(jié)需要闡述腿宰,如果看不下去的話,可以直接轉(zhuǎn)到文末看結(jié)論即可缘厢。

一吃度、客戶(hù)端

從上篇文章中我們已經(jīng)知道了 Nacos 的客戶(hù)端維護(hù)了一個(gè)長(zhǎng)輪詢(xún)的任務(wù),去檢查服務(wù)端的配置信息是否發(fā)生變更贴硫,如果發(fā)生了變更椿每,那么客戶(hù)端會(huì)拿到變更的 groupKey 再根據(jù) groupKey 去獲取配置項(xiàng)的最新值即可。

每次都靠客戶(hù)端去發(fā)請(qǐng)求夜畴,詢(xún)問(wèn)服務(wù)端我所關(guān)注的配置項(xiàng)有沒(méi)有發(fā)生變更拖刃,那請(qǐng)求的間隔改設(shè)置為多少才合適呢?

如果間隔時(shí)間設(shè)置的太長(zhǎng)的話有可能無(wú)法及時(shí)獲取服務(wù)端的變更贪绘,如果間隔時(shí)間設(shè)置的太短的話兑牡,那么頻繁的請(qǐng)求對(duì)于服務(wù)端來(lái)說(shuō)無(wú)疑也是一種負(fù)擔(dān)。

所以最好的方式是客戶(hù)端每隔一段長(zhǎng)度適中的時(shí)間去服務(wù)端請(qǐng)求税灌,而在這期間如果配置發(fā)生變更均函,服務(wù)端能夠主動(dòng)將變更后的結(jié)果推送給客戶(hù)端,這樣既能保證客戶(hù)端能夠?qū)崟r(shí)感知到配置的變化菱涤,也降低了服務(wù)端的壓力苞也。

客戶(hù)端長(zhǎng)輪詢(xún)

現(xiàn)在讓我們?cè)俅位氐娇蛻?hù)端長(zhǎng)輪詢(xún)的部分,也就是 LongPollingRunnable 中的 checkUpdateDataIds 方法粘秆,該方法就是用來(lái)訪問(wèn)服務(wù)端的配置是否發(fā)生變更的如迟,該方法最終會(huì)調(diào)用如下圖所示的方法:

check-update-config.jpg

請(qǐng)注意圖中紅框部分的內(nèi)容,客戶(hù)端是通過(guò)一個(gè) http 的 post 請(qǐng)求去獲取服務(wù)端的結(jié)果的,并且設(shè)置了一個(gè)超時(shí)時(shí)間:30s殷勘。

這個(gè)信息很關(guān)鍵此再,為什么客戶(hù)端要等待 30s 才超時(shí)呢?不應(yīng)該越快得到結(jié)果越好嗎玲销,我們來(lái)驗(yàn)證下該方法是不是真的等待了 30s输拇。

在 LongPollingRunnable 中的 checkUpdateDataIds 方法前后加上時(shí)間計(jì)算,然后將所消耗的時(shí)間打印出來(lái)策吠,如下圖所示:

print-cost-check-update-config.jpg

然后我們啟動(dòng)客戶(hù)端瘩绒,觀察打印的日志,如下圖所示:

long-polling-cost-result.jpg

從打印出來(lái)的日志可以看出來(lái)草讶,客戶(hù)端足足等了29.5+s,才請(qǐng)求到服務(wù)端的結(jié)果堕战。然后客戶(hù)端得到服務(wù)端的結(jié)果之后拍霜,再做一些后續(xù)的操作嘱丢,全部都執(zhí)行完畢之后,在 finally 中又重新調(diào)用了自身越驻,也就是說(shuō)這個(gè)過(guò)程是一直循環(huán)下去的缀旁。

長(zhǎng)輪詢(xún)時(shí)修改配置

現(xiàn)在我們可以確定的是勺鸦,客戶(hù)端向服務(wù)端發(fā)起一次請(qǐng)求,最少要29.5s才能得到結(jié)果懊渡,當(dāng)然啦剃执,這是在配置沒(méi)有發(fā)生變化的情況下懈息。

如果客戶(hù)端在長(zhǎng)輪詢(xún)時(shí)配置發(fā)生變更的話,該請(qǐng)求需要多長(zhǎng)時(shí)間才會(huì)返回呢戒祠,我們繼續(xù)做一個(gè)實(shí)驗(yàn)速种,在客戶(hù)端長(zhǎng)輪詢(xún)時(shí)修改配置配阵,結(jié)果如下圖所示:

long-polling-cost-result-2.jpg

上圖中紅框中就是我在客戶(hù)端一發(fā)起請(qǐng)求時(shí)就更新配置后打印的結(jié)果馏颂,從結(jié)果可以看出來(lái)該請(qǐng)求并沒(méi)有等到 29.5s+ 才返回救拉,而是一個(gè)很短的時(shí)間就返回了亿絮,具體多久需要從服務(wù)端的實(shí)現(xiàn)中查詢(xún)答案麸拄。

到目前為止我們已經(jīng)知道了客戶(hù)端執(zhí)行長(zhǎng)輪詢(xún)的邏輯拢切,以及每次請(qǐng)求的響應(yīng)時(shí)間會(huì)隨著服務(wù)端配置是否變更而發(fā)生變化,具體可以用下圖描述:

nacos-client-request.jpg

二、服務(wù)端

分析完客戶(hù)端的情況主穗,接下來(lái)要重點(diǎn)分析服務(wù)端是如何實(shí)現(xiàn)的忽媒,并且要帶著幾個(gè)問(wèn)題去尋找答案:

  • 客戶(hù)端長(zhǎng)輪詢(xún)的響應(yīng)時(shí)間會(huì)受什么影響
  • 為什么更改了配置信息后客戶(hù)端會(huì)立即得到響應(yīng)
  • 客戶(hù)端的超時(shí)時(shí)間為什么要設(shè)置為30s

帶著以上這些問(wèn)題我們從服務(wù)端的代碼中去探尋結(jié)論猾浦。

首先我們從客戶(hù)端發(fā)送的 http 請(qǐng)求中可以知道,請(qǐng)求的是服務(wù)端的 /v1/cs/configs/listener 這個(gè)接口音瓷。

我們找到該接口對(duì)應(yīng)的方法绳慎,在 ConfigController 類(lèi)中杏愤,如下圖所示:

com.alibaba.nacos.config.server.controller.ConfigController.java

config-controller-listener.jpg

Nacos 的服務(wù)端是通過(guò) spring 對(duì)外提供的 http 服務(wù)珊楼,對(duì) HttpServletRequest 中的參數(shù)進(jìn)行轉(zhuǎn)換后,然后交給一個(gè)叫 inner 的對(duì)象去執(zhí)行画舌。

下面我們進(jìn)入這個(gè)叫 inner 的對(duì)象中去曲聂,該 inner 對(duì)象是 ConfigServletInner 類(lèi)的實(shí)例佑惠,具體的方法如下所示:

com.alibaba.nacos.config.server.controller.ConfigServletInner.java

do-polling-config.jpg

可以看到該方法是一個(gè)輪詢(xún)的接口膜楷,除了支持長(zhǎng)輪詢(xún)外還支持短輪詢(xún)的邏輯把将,這里我們只關(guān)心長(zhǎng)輪詢(xún)的部分察蹲,也就是圖中紅框中的部分催训。

再次進(jìn)入 longPollingService 的 addLongPollingClient 方法漫拭,如下圖所示:

com.alibaba.nacos.config.server.service.LongPollingService.java

add-long-polling-client.jpg

從該方法的名字我們可以知道采驻,該方法主要是將客戶(hù)端的長(zhǎng)輪詢(xún)請(qǐng)求添加到某個(gè)東西中去礼旅,在方法的最后一行我們得到了答案:服務(wù)端將客戶(hù)端的長(zhǎng)輪詢(xún)請(qǐng)求封裝成一個(gè)叫 ClientLongPolling 的任務(wù),交給 scheduler 去執(zhí)行菲嘴。

但是請(qǐng)注意我用紅框圈出來(lái)的代碼龄坪,服務(wù)端拿到客戶(hù)端提交的超時(shí)時(shí)間后,又減去了 500ms 也就是說(shuō)服務(wù)端在這里使用了一個(gè)比客戶(hù)端提交的時(shí)間少 500ms 的超時(shí)時(shí)間烛卧,也就是 29.5s总放,看到這個(gè) 29.5s 我們應(yīng)該有點(diǎn)興奮了跟磨。

PS:這里的 timeout 不一定一直是 29.5抵拘,當(dāng) isFixedPolling() 方法為 true 時(shí)僵蛛,timeout 將會(huì)是一個(gè)固定的間隔時(shí)間,這里為了描述簡(jiǎn)單就直接用 29.5 來(lái)進(jìn)行說(shuō)明飘言。

接下來(lái)我們來(lái)看服務(wù)端封裝的 ClientLongPolling 的任務(wù)到底執(zhí)行的什么操作姿鸿,如下圖所示:

com.alibaba.nacos.config.server.service.LongPollingService.ClientLongPolling.java

client-long-polling.jpg

ClientLongPolling 被提交給 scheduler 執(zhí)行之后苛预,實(shí)際執(zhí)行的內(nèi)容可以拆分成以下四個(gè)步驟:

  • 1.創(chuàng)建一個(gè)調(diào)度的任務(wù)热某,調(diào)度的延時(shí)時(shí)間為 29.5s
  • 2.將該 ClientLongPolling 自身的實(shí)例添加到一個(gè) allSubs 中去
  • 3.延時(shí)時(shí)間到了之后胳螟,首先將該 ClientLongPolling 自身的實(shí)例從 allSubs 中移除
  • 4.獲取服務(wù)端中保存的對(duì)應(yīng)客戶(hù)端請(qǐng)求的 groupKeys 是否發(fā)生變更糖耸,將結(jié)果寫(xiě)入 response 返回給客戶(hù)端

整個(gè)過(guò)程可以用下面的圖進(jìn)行描述:

client-long-polling-process.jpg

這里出現(xiàn)了一個(gè)很關(guān)鍵的 allSubs 對(duì)象蔬捷,該對(duì)象是一個(gè) ConcurrentLinkedQueue 隊(duì)列,ClientLongPolling 將自身添加到隊(duì)列中去肯定是有原因的凰兑,這里需要對(duì) allSubs 留個(gè)心眼审丘。

調(diào)度任務(wù)

我們先不管 allSubs 隊(duì)列具體做了什么事滩报,先來(lái)看下服務(wù)端過(guò)了 29.5s 的延時(shí)時(shí)間后脓钾,執(zhí)行調(diào)度任務(wù)時(shí)做了什么,也就是上圖中對(duì)應(yīng)的第三昌妹、第四步飞崖。

首先將自身從 allSubs 隊(duì)列中刪除掉谨胞,也就是如注釋中說(shuō)的:刪除訂閱關(guān)系胯努,從這里我們可以知道 allSubs 和 ClientLongPolling 之間維持了一種訂閱關(guān)系叶沛,而 ClientLongPolling 是被訂閱的。

PS:刪除掉訂閱關(guān)系之后,訂閱方就無(wú)法對(duì)被訂閱方進(jìn)行通知了氓侧。

然后服務(wù)端對(duì)客戶(hù)端提交上來(lái)的 groupKey 進(jìn)行檢查约巷,如果發(fā)現(xiàn)某一個(gè) groupKey 的 md5 值還不是最新的独郎,則說(shuō)明客戶(hù)端的配置項(xiàng)還沒(méi)發(fā)生變更,所以將該 groupKey 放到一個(gè) changedGroupKeys 列表中谓谦,最后將該 changedGroupKeys 返回給客戶(hù)端反粥。

對(duì)于客戶(hù)端來(lái)說(shuō)才顿,只要拿到 changedGroupKeys 即可尤蒿,后續(xù)的操作我在上一篇文章中已經(jīng)分析過(guò)了腰池。

服務(wù)端數(shù)據(jù)變更

服務(wù)端直到調(diào)度任務(wù)的延時(shí)時(shí)間到了之前巩螃,ClientLongPolling 都不會(huì)有其他的任務(wù)可做,所以在這段時(shí)間內(nèi)爷耀,該 allSubs 隊(duì)列肯定有事情需要進(jìn)行處理歹叮。

回想到我們?cè)诳蛻?hù)端長(zhǎng)輪詢(xún)期間咆耿,更改了配置之后爹橱,客戶(hù)端能夠立即得到響應(yīng)愧驱,所以我們有理由相信组砚,這個(gè)隊(duì)列可能會(huì)跟配置變更有關(guān)系糟红。

現(xiàn)在我們找一下在 dashboard 上修改配置后乌叶,調(diào)用的請(qǐng)求准浴,可以很容易的找到該請(qǐng)求對(duì)應(yīng)的 url為:/v1/cs/configs 并且是一個(gè) POST 請(qǐng)求兄裂,具體的方法是 ConfigController 中的 publishConfig 方法晰奖,如下圖所示:

publish-config.jpg

我只截取了重要的部分匾南,從紅框中的代碼可以看出蛔外,修改配置后夹厌,服務(wù)端首先將配置的值進(jìn)行了持久化層的更新矛纹,然后觸發(fā)了一個(gè) ConfigDataChangeEvent 的事件或南。

具體的 fireEvent 的方法如下圖所示:

com.alibaba.nacos.config.server.utils.event.EventDispatcher.java

fire-event.jpg

fireEvent 方法實(shí)際上是觸發(fā)的 AbstractEventListener 的 onEvent 方法采够,而所有的 listener 是保存在一個(gè)叫 listeners 對(duì)象中的蹬癌。

被觸發(fā)的 AbstractEventListener 對(duì)象則是通過(guò) addEventListener 方法添加到 listeners 中的逝薪,所以我們只需要找到 addEventListener 方法在何處被調(diào)用的,就知道有哪些 AbstractEventListener 需要被觸發(fā) onEvent 回調(diào)方法了。

可以找到是在 AbstractEventListener 類(lèi)的構(gòu)造方法中感局,將自身注冊(cè)進(jìn)去了询微,如下圖所示:

com.alibaba.nacos.config.server.utils.event.EventDispatcher.AbstractEventListener.java

abstract-event-listener.jpg

而 AbstractEventListener 是一個(gè)抽象類(lèi)撑毛,所以實(shí)際注冊(cè)的應(yīng)該是 AbstractEventListener 的子類(lèi)藻雌,所以我們需要找到所以繼承自 AbstractEventListener 的類(lèi)胯杭,如下圖所示:

abstract-event-listener-subclass.jpg

可以看到 AbstractEventListener 所有的子類(lèi)中做个,有一個(gè)我們熟悉的身影居暖,他就是我們剛剛一直在研究的 LongPollingService太闺。

所以到這里我們就知道了,當(dāng)我們從 dashboard 中更新了配置項(xiàng)之后莺奸,實(shí)際會(huì)調(diào)用到 LongPollingService 的 onEvent 方法灭贷。

現(xiàn)在我們繼續(xù)回到 LongPollingService 中甚疟,查看一下 onEvent 方法览妖,如下圖所示:

on-event.jpg

com.alibaba.nacos.config.server.service.LongPollingService.DataChangeTask.java

發(fā)現(xiàn)當(dāng)觸發(fā)了 LongPollingService 的 onEvent 方法時(shí)讽膏,實(shí)際是執(zhí)行了一個(gè)叫 DataChangeTask 的任務(wù)府树,應(yīng)該是通過(guò)該任務(wù)來(lái)通知客戶(hù)端服務(wù)端的數(shù)據(jù)已經(jīng)發(fā)生了變更奄侠,我們進(jìn)入 DataChangeTask 中看下具體的代碼,如下圖所示:

data-change-task.jpg

代碼很簡(jiǎn)單,可以總結(jié)為兩個(gè)步驟:

  • 1.遍歷 allSubs 的隊(duì)列

首先遍歷 allSubs 的隊(duì)列旅急,該隊(duì)列中維持的是所有客戶(hù)端的請(qǐng)求任務(wù)坠非,需要找到與當(dāng)前發(fā)生變更的配置項(xiàng)的 groupKey 相等的 ClientLongPolling 任務(wù)

  • 2.往客戶(hù)端寫(xiě)響應(yīng)數(shù)據(jù)

在第一步找到具體的 ClientLongPolling 任務(wù)后炎码,只需要將發(fā)生變更的 groupKey 通過(guò)該 ClientLongPolling 寫(xiě)入到響應(yīng)對(duì)象中秋泳,就完成了一次數(shù)據(jù)變更的 “推送” 操作了

如果 DataChangeTask 任務(wù)完成了數(shù)據(jù)的 “推送” 之后迫皱,ClientLongPolling 中的調(diào)度任務(wù)又開(kāi)始執(zhí)行了怎么辦呢卓起?

很簡(jiǎn)單戏阅,只要在進(jìn)行 “推送” 操作之前奕筐,先將原來(lái)等待執(zhí)行的調(diào)度任務(wù)取消掉就可以了离赫,這樣就防止了推送操作寫(xiě)完響應(yīng)數(shù)據(jù)之后渊胸,調(diào)度任務(wù)又去寫(xiě)響應(yīng)數(shù)據(jù),這時(shí)肯定會(huì)報(bào)錯(cuò)的瓢捉。

可以從 sendResponse 方法中看到泡态,確實(shí)是這樣做的:

send-response.jpg

問(wèn)題解答

現(xiàn)在讓我們回到剛開(kāi)始的時(shí)候提的幾個(gè)問(wèn)題某弦,相信大家已經(jīng)有了答案了靶壮。

  • 客戶(hù)端長(zhǎng)輪詢(xún)的響應(yīng)時(shí)間會(huì)受什么影響

客戶(hù)端長(zhǎng)輪詢(xún)的響應(yīng)時(shí)間腾降,設(shè)置的是30s螃壤,但是有時(shí)響應(yīng)很快奸晴,有時(shí)響應(yīng)很慢日麸,這取決于服務(wù)端的配置有沒(méi)有發(fā)生變化代箭。當(dāng)配置發(fā)生變化時(shí)嗡综,響應(yīng)很快就會(huì)返回蛤高,當(dāng)配置一直沒(méi)有發(fā)生變化時(shí)戴陡,會(huì)等到 29.5s 之后再進(jìn)行響應(yīng)恤批。

  • 為什么更改了配置信息后客戶(hù)端會(huì)立即得到響應(yīng)

因?yàn)榉?wù)端會(huì)在更改了配置信息后,找到具體的客戶(hù)端請(qǐng)求中的 response诀浪,然后直接將結(jié)果寫(xiě)入 response 中棋返,就像服務(wù)端對(duì)客戶(hù)端進(jìn)行的數(shù)據(jù) “推送” 一樣,所以客戶(hù)端會(huì)很快得到響應(yīng)雷猪。

  • 客戶(hù)端的超時(shí)時(shí)間為什么要設(shè)置為30s

這應(yīng)該是一個(gè)經(jīng)驗(yàn)值睛竣,該超時(shí)時(shí)間關(guān)系到服務(wù)端調(diào)度任務(wù)的等待時(shí)間,服務(wù)端在前29.5s 只需要進(jìn)行等待求摇,最后的 0.5s 才進(jìn)行配置變更檢查射沟。

如果設(shè)置的太短,那服務(wù)端等待的時(shí)間就太短与境,如果這時(shí)配置變更的比較頻繁,那很可能無(wú)法在等待期對(duì)客戶(hù)端做推送摔刁,而是滑動(dòng)到檢查期對(duì)數(shù)據(jù)進(jìn)行檢查后才能將數(shù)據(jù)變更發(fā)回給客戶(hù)端挥转,檢查期相比等待期需要進(jìn)行數(shù)據(jù)的檢查,涉及到 IO 操作共屈,而 IO 操作是比較昂貴的绑谣,我們應(yīng)該盡量在等待期就將數(shù)據(jù)變更發(fā)送給客戶(hù)端。

http 請(qǐng)求本來(lái)就是無(wú)狀態(tài)的趁俊,所以沒(méi)必要也不能將超時(shí)時(shí)間設(shè)置的太長(zhǎng)域仇,這樣是對(duì)資源的一種浪費(fèi)。

結(jié)論

1寺擂、客戶(hù)端的請(qǐng)求到達(dá)服務(wù)端后暇务,服務(wù)端將該請(qǐng)求加入到一個(gè)叫 allSubs 的隊(duì)列中,等待配置發(fā)生變更時(shí) DataChangeTask 主動(dòng)去觸發(fā)怔软,并將變更后的數(shù)據(jù)寫(xiě)入響應(yīng)對(duì)象垦细,如下圖所示:

nacos-config-update-1.jpg

2、與此同時(shí)服務(wù)端也將該請(qǐng)求封裝成一個(gè)調(diào)度任務(wù)去執(zhí)行挡逼,等待調(diào)度的期間就是等待 DataChangeTask 主動(dòng)觸發(fā)的括改,如果延遲時(shí)間到了 DataChangeTask 還未觸發(fā)的話,則調(diào)度任務(wù)開(kāi)始執(zhí)行數(shù)據(jù)變更的檢查家坎,然后將檢查的結(jié)果寫(xiě)入響應(yīng)對(duì)象嘱能,如下圖所示:

nacos-config-update-2.jpg

基于上述的分析,最終總結(jié)了以下結(jié)論:

  • 1.Nacos 客戶(hù)端會(huì)循環(huán)請(qǐng)求服務(wù)端變更的數(shù)據(jù),并且超時(shí)時(shí)間設(shè)置為30s,當(dāng)配置發(fā)生變化時(shí)徙邻,請(qǐng)求的響應(yīng)會(huì)立即返回,否則會(huì)一直等到 29.5s+ 之后再返回響應(yīng)
  • 2.Nacos 客戶(hù)端能夠?qū)崟r(shí)感知到服務(wù)端配置發(fā)生了變化对粪。
  • 3.實(shí)時(shí)感知是建立在客戶(hù)端拉和服務(wù)端“推”的基礎(chǔ)上右冻,但是這里的服務(wù)端“推”需要打上引號(hào),因?yàn)榉?wù)端和客戶(hù)端直接本質(zhì)上還是通過(guò) http 進(jìn)行數(shù)據(jù)通訊的著拭,之所以有“推”的感覺(jué)纱扭,是因?yàn)榉?wù)端主動(dòng)將變更后的數(shù)據(jù)通過(guò) http 的 response 對(duì)象提前寫(xiě)入了。

至此儡遮,正如標(biāo)題所說(shuō)的乳蛾,推+拉打造 Nacos 配置信息的實(shí)時(shí)更新的原理已經(jīng)分析清楚了。

逅弈逐碼鄙币,專(zhuān)注于原創(chuàng)分享屡久,用通俗易懂的圖文描述源碼及原理
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市爱榔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌糙及,老刑警劉巖详幽,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異浸锨,居然都是意外死亡唇聘,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)柱搜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)迟郎,“玉大人,你說(shuō)我怎么就攤上這事聪蘸∠苄ぃ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵健爬,是天一觀的道長(zhǎng)控乾。 經(jīng)常有香客問(wèn)我,道長(zhǎng)娜遵,這世上最難降的妖魔是什么蜕衡? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮设拟,結(jié)果婚禮上慨仿,老公的妹妹穿的比我還像新娘。我一直安慰自己纳胧,他們只是感情好镰吆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著躲雅,像睡著了一般鼎姊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,727評(píng)論 1 305
  • 那天相寇,我揣著相機(jī)與錄音慰于,去河邊找鬼。 笑死唤衫,一個(gè)胖子當(dāng)著我的面吹牛婆赠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播佳励,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼休里,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了赃承?” 一聲冷哼從身側(cè)響起妙黍,我...
    開(kāi)封第一講書(shū)人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瞧剖,沒(méi)想到半個(gè)月后拭嫁,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抓于,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年做粤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捉撮。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡怕品,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出巾遭,到底是詐尸還是另有隱情肉康,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布恢总,位于F島的核電站迎罗,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏片仿。R本人自食惡果不足惜纹安,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望砂豌。 院中可真熱鬧厢岂,春花似錦、人聲如沸阳距。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)筐摘。三九已至卒茬,卻和暖如春船老,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背圃酵。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工柳畔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人郭赐。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓薪韩,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親捌锭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子俘陷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

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

  • 動(dòng)態(tài)配置管理是 Nacos 的三大功能之一,通過(guò)動(dòng)態(tài)配置服務(wù)观谦,我們可以在所有環(huán)境中以集中和動(dòng)態(tài)的方式管理所有應(yīng)用程...
    逅弈閱讀 75,851評(píng)論 9 101
  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說(shuō)閱讀 10,989評(píng)論 6 13
  • 云應(yīng)用設(shè)計(jì)模式 下面的章節(jié)詳細(xì)介紹了一些設(shè)計(jì)模式拉盾,這些現(xiàn)有的設(shè)計(jì)模式可以有效地應(yīng)用到云服務(wù)應(yīng)用程序設(shè)計(jì)中去。 電路...
    AIOPstack閱讀 819評(píng)論 0 1
  • 文章首發(fā)于個(gè)人blog歡迎指正補(bǔ)充豁状,可聯(lián)系lionsom_lin@qq.com原文地址:《網(wǎng)絡(luò)是怎樣連接的》閱讀整...
    lionsom_lin閱讀 14,154評(píng)論 6 31
  • 體驗(yàn) 今天跟若蘭姐姐學(xué)習(xí)了理財(cái)盾剩,用錢(qián)來(lái)賺錢(qián),感受到了錢(qián)的來(lái)之不易替蔬。 爸爸說(shuō):錢(qián)是來(lái)之不易的,我們不要亂買(mǎi)東西屎暇,不要...
    林深葉茂閱讀 116評(píng)論 0 0