聊聊高并發(fā)系統(tǒng)限流特技-2

轉載來自開濤的聊聊高并發(fā)系統(tǒng)限流特技-2

上一篇《聊聊高并發(fā)系統(tǒng)限流特技-1》講了限流算法、應用級限流、分布式限流;本篇將介紹接入層限流實現(xiàn)瘪菌。

接入層限流

接入層通常指請求流量的入口撒会,該層的主要目的有:負載均衡、非法請求過濾师妙、請求聚合诵肛、緩存、降級默穴、限流怔檩、A/B測試、服務質量監(jiān)控等等蓄诽,可以參考筆者寫的《使用Nginx+Lua(OpenResty)開發(fā)高性能Web應用》薛训。

對于Nginx接入層限流可以使用Nginx自帶了兩個模塊:連接數(shù)限流模塊ngx_http_limit_conn_module和漏桶算法實現(xiàn)的請求限流模塊ngx_http_limit_req_module。還可以使用OpenResty提供的Lua限流模塊lua-resty-limit-traffic進行更復雜的限流場景若专。

limit_conn用來對某個KEY對應的總的網絡連接數(shù)進行限流许蓖,可以按照如IP、域名維度進行限流调衰。limit_req用來對某個KEY對應的請求的平均速率進行限流膊爪,并有兩種用法:平滑模式(delay)和允許突發(fā)模式(nodelay)。

ngx_http_limit_conn_module

limit_conn是對某個KEY對應的總的網絡連接數(shù)進行限流嚎莉∶壮辏可以按照IP來限制IP維度的總連接數(shù),或者按照服務域名來限制某個域名的總連接數(shù)趋箩。但是記住不是每一個請求連接都會被計數(shù)器統(tǒng)計赃额,只有那些被Nginx處理的且已經讀取了整個請求頭的請求連接才會被計數(shù)器統(tǒng)計。

配置示例:

================================

http {

limit_conn_zone$binary_remote_addr zone=addr:10m;

limit_conn_log_level error;

limit_conn_status 503;

...

server {

...

location /limit {

limit_conn addr 1;

}

================================

limit_conn:要配置存放KEY和計數(shù)器的共享內存區(qū)域和指定KEY的最大連接數(shù)叫确;此處指定的最大連接數(shù)是1跳芳,表示Nginx最多同時并發(fā)處理1個連接;

limit_conn_zone:用來配置限流KEY竹勉、及存放KEY對應信息的共享內存區(qū)域大蟹膳琛;此處的KEY是“$binary_remote_addr”其表示IP地址次乓,也可以使用如$server_name作為KEY來限制域名級別的最大連接數(shù)吓歇;

limit_conn_status:配置被限流后返回的狀態(tài)碼,默認返回503票腰;

limit_conn_log_level:配置記錄被限流后的日志級別城看,默認error級別。

limit_conn的主要執(zhí)行過程如下所示:

1杏慰、請求進入后首先判斷當前l(fā)imit_conn_zone中相應KEY的連接數(shù)是否超出了配置的最大連接數(shù)测柠;

2.1炼鞠、如果超過了配置的最大大小,則被限流鹃愤,返回limit_conn_status定義的錯誤狀態(tài)碼簇搅;

2.2完域、否則相應KEY的連接數(shù)加1软吐,并注冊請求處理完成的回調函數(shù);

3吟税、進行請求處理凹耙;

4、在結束請求階段會調用注冊的回調函數(shù)對相應KEY的連接數(shù)減1肠仪。

limt_conn可以限流某個KEY的總并發(fā)/請求數(shù)肖抱,KEY可以根據(jù)需要變化。

按照IP限制并發(fā)連接數(shù)配置示例:

首先定義IP維度的限流區(qū)域:

================================

limit_conn_zone $binary_remote_addrzone=perip:10m;

================================

接著在要限流的location中添加限流邏輯:

================================

location /limit {

limit_conn perip 2;

echo "123";

}

================================

即允許每個IP最大并發(fā)連接數(shù)為2异旧。

使用AB測試工具進行測試意述,并發(fā)數(shù)為5個,總的請求數(shù)為5個:

================================

ab -n 5 -c 5 http://localhost/limit

================================

將得到如下access.log輸出:

================================

[08/Jun/2016:20:10:51+0800] [1465373451.802] 200

[08/Jun/2016:20:10:51+0800] [1465373451.803] 200

[08/Jun/2016:20:10:51 +0800][1465373451.803] 503

[08/Jun/2016:20:10:51 +0800][1465373451.803] 503

[08/Jun/2016:20:10:51 +0800][1465373451.803] 503

================================

此處我們把access log格式設置為log_format main? '[$time_local] [$msec] $status'吮蛹;分別是“日期日期秒/毫秒值響應狀態(tài)碼”荤崇。

如果被限流了,則在error.log中會看到類似如下的內容:

================================

2016/06/08 20:10:51 [error] 5662#0: *5limiting connections by zone "perip", client: 127.0.0.1, server: _,request: "GET /limit HTTP/1.0", host: "localhost"

================================

按照域名限制并發(fā)連接數(shù)配置示例:

首先定義域名維度的限流區(qū)域:

================================

limit_conn_zone $ server_name zone=perserver:10m;

================================

接著在要限流的location中添加限流邏輯:

================================

location /limit {

limit_conn perserver 2;

echo "123";

}

================================

即允許每個域名最大并發(fā)請求連接數(shù)為2潮针;這樣配置可以實現(xiàn)服務器最大連接數(shù)限制术荤。

ngx_http_limit_req_module

limit_req是令牌桶算法實現(xiàn),用于對指定KEY對應的請求進行限流每篷,比如按照IP維度限制請求速率瓣戚。

配置示例:

================================

http {

limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

limit_conn_log_level error;

limit_conn_status 503;

...

server {

...

location /limit {

limit_req zone=one burst=5 nodelay;

}

================================

limit_req:配置限流區(qū)域、桶容量(突發(fā)容量焦读,默認0)子库、是否延遲模式(默認延遲);

limit_req_zone:配置限流KEY矗晃、及存放KEY對應信息的共享內存區(qū)域大小仑嗅、固定請求速率;此處指定的KEY是“$binary_remote_addr”表示IP地址喧兄;固定請求速率使用rate參數(shù)配置无畔,支持10r/s和60r/m,即每秒10個請求和每分鐘60個請求吠冤,不過最終都會轉換為每秒的固定請求速率(10r/s為每100毫秒處理一個請求浑彰;60r/m,即每1000毫秒處理一個請求)拯辙。

limit_conn_status:配置被限流后返回的狀態(tài)碼郭变,默認返回503颜价;

limit_conn_log_level:配置記錄被限流后的日志級別,默認error級別诉濒。

limit_req的主要執(zhí)行過程如下所示:

1周伦、請求進入后首先判斷最后一次請求時間相對于當前時間(第一次是0)是否需要限流,如果需要限流則執(zhí)行步驟2未荒,否則執(zhí)行步驟3专挪;

2.1、如果沒有配置桶容量(burst)片排,則桶容量為0寨腔;按照固定速率處理請求;如果請求被限流率寡,則直接返回相應的錯誤碼(默認503)迫卢;

2.2、如果配置了桶容量(burst>0)且延遲模式(沒有配置nodelay)冶共;如果桶滿了乾蛤,則新進入的請求被限流;如果沒有滿則請求會以固定平均速率被處理(按照固定速率并根據(jù)需要延遲處理請求捅僵,延遲使用休眠實現(xiàn))家卖;

2.3、如果配置了桶容量(burst>0)且非延遲模式(配置了nodelay)命咐;不會按照固定速率處理請求篡九,而是允許突發(fā)處理請求;如果桶滿了醋奠,則請求被限流榛臼,直接返回相應的錯誤碼;

3窜司、如果沒有被限流沛善,則正常處理請求;

4塞祈、Nginx會在相應時機進行選擇一些(3個節(jié)點)限流KEY進行過期處理金刁,進行內存回收。

場景2.1測試

首先定義IP維度的限流區(qū)域:

================================

limit_req_zone $binary_remote_addrzone=test:10m rate=500r/s;

================================

限制為每秒500個請求议薪,固定平均速率為2毫秒一個請求尤蛮。

接著在要限流的location中添加限流邏輯:

================================

location /limit {

limit_req zone=test;

echo "123";

}

================================

即桶容量為0(burst默認為0),且延遲模式斯议。

使用AB測試工具進行測試产捞,并發(fā)數(shù)為2個,總的請求數(shù)為10個:

================================

ab -n 10 -c 2 http://localhost/limit

================================

將得到如下access.log輸出:

================================

[08/Jun/2016:20:25:56+0800] [1465381556.410] 200

[08/Jun/2016:20:25:56 +0800][1465381556.410] 503

[08/Jun/2016:20:25:56 +0800][1465381556.411] 503

[08/Jun/2016:20:25:56+0800] [1465381556.411] 200

[08/Jun/2016:20:25:56 +0800][1465381556.412] 503

[08/Jun/2016:20:25:56 +0800][1465381556.412] 503

================================

雖然每秒允許500個請求哼御,但是因為桶容量為0坯临,所以流入的請求要么被處理要么被限流焊唬,無法延遲處理;另外平均速率在2毫秒左右看靠,比如1465381556.410和1465381556.411被處理了赶促;有朋友會說這固定平均速率不是1毫秒嘛,其實這是因為實現(xiàn)算法沒那么精準造成的挟炬。

如果被限流在error.log中會看到如下內容:

================================

2016/06/08 20:25:56 [error] 6130#0: *1962limiting requests, excess: 1.000 by zone "test", client: 127.0.0.1,server: _, request: "GET /limit HTTP/1.0", host:"localhost"

================================

如果被延遲了在error.log(日志級別要INFO級別)中會看到如下內容:

================================

2016/06/10 09:05:23 [warn] 9766#0: *97021delaying request, excess: 0.368, by zone "test", client: 127.0.0.1,server: _, request: "GET /limit HTTP/1.0", host:"localhost"

================================

場景2.2測試

首先定義IP維度的限流區(qū)域:

================================

limit_req_zone $binary_remote_addr ? ?zone=test:10m rate=2r/s;

================================

為了方便測試設置速率為每秒2個請求鸥滨,即固定平均速率是500毫秒一個請求。

接著在要限流的location中添加限流邏輯:

================================

location /limit {

limit_req zone=test burst=3;

echo "123";

}

================================

固定平均速率為500毫秒一個請求辟宗,通容量為3爵赵,如果桶滿了新的請求被限流吝秕,否則可以進入桶中排隊并等待(實現(xiàn)延遲模式)泊脐。

為了看出限流效果我們寫了一個req.sh腳本:

================================

ab -c 6 -n 6 http://localhost/limit

sleep 0.3

ab -c 6 -n 6 http://localhost/limit

================================

首先進行6個并發(fā)請求6次URL,然后休眠300毫秒烁峭,然后再進行6個并發(fā)請求6次URL容客;中間休眠目的是為了能跨越2秒看到效果,如果看不到如下的效果可以調節(jié)休眠時間约郁。

將得到如下access.log輸出:

================================

[09/Jun/2016:08:46:43+0800] [1465433203.959] 200

[09/Jun/2016:08:46:43 +0800][1465433203.959] 503

[09/Jun/2016:08:46:43 +0800][1465433203.960] 503

[09/Jun/2016:08:46:44+0800] [1465433204.450] 200

[09/Jun/2016:08:46:44+0800] [1465433204.950] 200

[09/Jun/2016:08:46:45 +0800][1465433205.453] 200

[09/Jun/2016:08:46:45 +0800][1465433205.766] 503

[09/Jun/2016:08:46:45 +0800][1465433205.766] 503

[09/Jun/2016:08:46:45 +0800][1465433205.767] 503

[09/Jun/2016:08:46:45+0800] [1465433205.950] 200

[09/Jun/2016:08:46:46+0800] [1465433206.451] 200

[09/Jun/2016:08:46:46+0800] [1465433206.952] 200

================================

桶容量為3缩挑,即桶中在時間窗口內最多流入3個請求,且按照2r/s的固定速率處理請求(即每隔500毫秒處理一個請求)鬓梅;桶計算時間窗口(1.5秒)=速率(2r/s)/桶容量(3)供置,也就是說在這個時間窗口內桶最多暫存3個請求。因此我們要以當前時間往前推1.5秒和1秒來計算時間窗口內的總請求數(shù)绽快;另外因為默認是延遲模式芥丧,所以時間窗內的請求要被暫存到桶中,并以固定平均速率處理請求:

第一輪:有4個請求處理成功了坊罢,按照漏桶桶容量應該最多3個才對续担;這是因為計算算法的問題,第一次計算因沒有參考值活孩,所以第一次計算后物遇,后續(xù)的計算才能有參考值,因此第一次成功可以忽略憾儒;這個問題影響很小可以忽略询兴;而且按照固定500毫秒的速率處理請求。

第二輪:因為第一輪請求是突發(fā)來的起趾,差不多都在1465433203.959時間點诗舰,只是因為漏桶將速率進行了平滑變成了固定平均速率(每500毫秒一個請求);而第二輪計算時間應基于1465433203.959阳掐;而第二輪突發(fā)請求差不多都在1465433205.766時間點始衅,因此計算桶容量的時間窗口應基于1465433203.959和1465433205.766來計算冷蚂,計算結果為1465433205.766這個時間點漏桶為空了,可以流入桶中3個請求汛闸,其他請求被拒絕蝙茶;又因為第一輪最后一次處理時間是1465433205.453,所以第二輪第一個請求被延遲到了1465433205.950诸老。這里也要注意固定平均速率只是在配置的速率左右隆夯,存在計算精度問題,會有一些偏差别伏。

如果桶容量改為1(burst=1)蹄衷,執(zhí)行req.sh腳本可以看到如下輸出:

================================

[09/Jun/2016:09:04:30+0800] [1465434270.362] 200

[09/Jun/2016:09:04:30 +0800][1465434270.371] 503

[09/Jun/2016:09:04:30 +0800] [1465434270.372]503

[09/Jun/2016:09:04:30 +0800][1465434270.372] 503

[09/Jun/2016:09:04:30 +0800][1465434270.372] 503

[09/Jun/2016:09:04:30+0800] [1465434270.864] 200

[09/Jun/2016:09:04:31 +0800][1465434271.178] 503

[09/Jun/2016:09:04:31 +0800][1465434271.178] 503

[09/Jun/2016:09:04:31 +0800][1465434271.178] 503

[09/Jun/2016:09:04:31 +0800][1465434271.178] 503

[09/Jun/2016:09:04:31 +0800][1465434271.179] 503

[09/Jun/2016:09:04:31+0800] [1465434271.366] 200

================================

桶容量為1,按照每1000毫秒一個請求的固定平均速率處理請求厘肮。

場景2.3測試

首先定義IP維度的限流區(qū)域:

================================

limit_req_zone $binary_remote_addrzone=test:10m rate=2r/s;

================================

為了方便測試配置為每秒2個請求愧口,固定平均速率是500毫秒一個請求。

接著在要限流的location中添加限流邏輯:

================================

location /limit {

limit_req zone=test burst=3 nodelay;

echo "123";

}

================================

桶容量為3类茂,如果桶滿了直接拒絕新請求耍属,且每秒2最多兩個請求,桶按照固定500毫秒的速率以nodelay模式處理請求巩检。

為了看到限流效果我們寫了一個req.sh腳本:

================================

ab -c 6 -n 6 http://localhost/limit

sleep 1

ab -c 6 -n 6 http://localhost/limit

sleep 0.3

ab -c 6 -n 6 http://localhost/limit

sleep 0.3

ab -c 6 -n 6 http://localhost/limit

sleep 0.3

ab -c 6 -n 6 http://localhost/limit

sleep 2

ab -c 6 -n 6 http://localhost/limit

================================

將得到類似如下access.log輸出:

================================

[09/Jun/2016:14:30:11+0800] [1465453811.754] 200

[09/Jun/2016:14:30:11+0800] [1465453811.755] 200

[09/Jun/2016:14:30:11+0800] [1465453811.755] 200

[09/Jun/2016:14:30:11+0800] [1465453811.759] 200

[09/Jun/2016:14:30:11 +0800][1465453811.759] 503

[09/Jun/2016:14:30:11 +0800][1465453811.759] 503

[09/Jun/2016:14:30:12+0800] [1465453812.776] 200

[09/Jun/2016:14:30:12+0800] [1465453812.776] 200

[09/Jun/2016:14:30:12 +0800][1465453812.776] 503

[09/Jun/2016:14:30:12 +0800][1465453812.777] 503

[09/Jun/2016:14:30:12 +0800][1465453812.777] 503

[09/Jun/2016:14:30:12 +0800][1465453812.777] 503

[09/Jun/2016:14:30:13 +0800] [1465453813.095]503

[09/Jun/2016:14:30:13 +0800][1465453813.097] 503

[09/Jun/2016:14:30:13 +0800][1465453813.097] 503

[09/Jun/2016:14:30:13 +0800][1465453813.097] 503

[09/Jun/2016:14:30:13 +0800][1465453813.097] 503

[09/Jun/2016:14:30:13 +0800][1465453813.098] 503

[09/Jun/2016:14:30:13+0800] [1465453813.425] 200

[09/Jun/2016:14:30:13 +0800][1465453813.425] 503

[09/Jun/2016:14:30:13 +0800][1465453813.425] 503

[09/Jun/2016:14:30:13 +0800][1465453813.426] 503

[09/Jun/2016:14:30:13 +0800][1465453813.426] 503

[09/Jun/2016:14:30:13 +0800][1465453813.426] 503

[09/Jun/2016:14:30:13+0800] [1465453813.754] 200

[09/Jun/2016:14:30:13 +0800][1465453813.755] 503

[09/Jun/2016:14:30:13 +0800][1465453813.755] 503

[09/Jun/2016:14:30:13 +0800][1465453813.756] 503

[09/Jun/2016:14:30:13 +0800][1465453813.756] 503

[09/Jun/2016:14:30:13 +0800][1465453813.756] 503

[09/Jun/2016:14:30:15+0800] [1465453815.278] 200

[09/Jun/2016:14:30:15+0800] [1465453815.278] 200

[09/Jun/2016:14:30:15+0800] [1465453815.278] 200

[09/Jun/2016:14:30:15 +0800][1465453815.278] 503

[09/Jun/2016:14:30:15 +0800][1465453815.279] 503

[09/Jun/2016:14:30:15 +0800][1465453815.279] 503

[09/Jun/2016:14:30:17+0800] [1465453817.300] 200

[09/Jun/2016:14:30:17+0800] [1465453817.300] 200

[09/Jun/2016:14:30:17+0800] [1465453817.300] 200

[09/Jun/2016:14:30:17+0800] [1465453817.301] 200

[09/Jun/2016:14:30:17 +0800][1465453817.301] 503

[09/Jun/2016:14:30:17 +0800][1465453817.301] 503

================================

桶容量為3(厚骗,即桶中在時間窗口內最多流入3個請求,且按照2r/s的固定速率處理請求(即每隔500毫秒處理一個請求)兢哭;桶計算時間窗口(1.5秒)=速率(2r/s)/桶容量(3)领舰,也就是說在這個時間窗口內桶最多暫存3個請求。因此我們要以當前時間往前推1.5秒和1秒來計算時間窗口內的總請求數(shù)迟螺;另外因為配置了nodelay冲秽,是非延遲模式,所以允許時間窗內突發(fā)請求的煮仇;另外從本示例會看出兩個問題:

第一輪和第七輪:有4個請求處理成功了劳跃;這是因為計算算法的問題,本示例是如果2秒內沒有請求浙垫,然后接著突然來了很多請求刨仑,第一次計算的結果將是不正確的;這個問題影響很小可以忽略夹姥;

第五輪:1.0秒計算出來是3個請求杉武;此處也是因計算精度的問題,也就是說limit_req實現(xiàn)的算法不是非常精準的辙售,假設此處看成相對于2.75的話轻抱,1.0秒內只有1次請求,所以還是允許1次請求的旦部。

如果限流出錯了祈搜,可以配置錯誤頁面:

================================

proxy_intercept_errorson;recursive_error_pageson;error_page 503//www.jd.com/error.aspx;

================================

limit_conn_zone/limit_req_zone定義的內存不足较店,則后續(xù)的請求將一直被限流,所以需要根據(jù)需求設置好相應的內存大小容燕。

此處的限流都是單Nginx的梁呈,假設我們接入層有多個nginx,此處就存在和應用級限流相同的問題蘸秘;那如何處理呢官卡?一種解決辦法:建立一個負載均衡層將按照限流KEY進行一致性哈希算法將請求哈希到接入層Nginx上,從而相同KEY的將打到同一臺接入層Nginx上醋虏;另一種解決方案就是使用Nginx+Lua(OpenResty)調用分布式限流邏輯實現(xiàn)寻咒。

lua-resty-limit-traffic

之前介紹的兩個模塊使用上比較簡單,指定KEY颈嚼、指定限流速率等就可以了毛秘,如果我們想根據(jù)實際情況變化KEY、變化速率粘舟、變化桶大小等這種動態(tài)特性熔脂,使用標準模塊就很難去實現(xiàn)了,因此我們需要一種可編程來解決我們問題柑肴;而OpenResty提供了lua限流模塊lua-resty-limit-traffic,通過它可以按照更復雜的業(yè)務邏輯進行動態(tài)限流處理了旬薯。其提供了limit.conn和limit.req實現(xiàn)晰骑,算法與nginx limit_conn和limit_req是一樣的。

此處我們來實現(xiàn)ngx_http_limit_req_module中的【場景2.2測試】绊序,不要忘記下載lua-resty-limit-traffic模塊并添加到OpenResty的lualib中硕舆。

配置用來存放限流用的共享字典:

================================

lua_shared_dict limit_req_store 100m;

================================

以下是實現(xiàn)【場景2.2測試】的限流代碼limit_req.lua:

================================

local limit_req = require "resty.limit.req"

local rate = 2 --固定平均速率 2r/s

local burst = 3? --桶容量

local error_status = 503

local nodelay = false --是否需要不延遲處理

local lim, err = limit_req.new("limit_req_store", rate, burst)

if not lim then --沒定義共享字典

ngx.exit(error_status)

end

local key = ngx.var.binary_remote_addr --IP維度的限流

--流入請求,如果請求需要被延遲則delay > 0

local delay, err = lim:incoming(key, true)

if not delay and err == "rejected" then --超出桶大小了

ngx.exit(error_status)

end

if delay > 0 then? --根據(jù)需要決定是延遲或者不延遲處理

if nodelay then

--直接突發(fā)處理了

else

ngx.sleep(delay) --延遲處理

end

end

================================

即限流邏輯再nginx access階段被訪問骤公,如果不被限流繼續(xù)后續(xù)流程抚官;如果需要被限流要么sleep一段時間繼續(xù)后續(xù)流程,要么返回相應的狀態(tài)碼拒絕請求阶捆。

在分布式限流中我們使用了簡單的Nginx+Lua進行分布式限流凌节,有了這個模塊也可以使用這個模塊來實現(xiàn)分布式限流。

另外在使用Nginx+Lua時也可以獲取ngx.var.connections_active進行過載保護洒试,即如果當前活躍連接數(shù)超過閾值進行限流保護倍奢。

================================

if tonumber(ngx.var.connections_active) >= tonumber(limit) then//限流end

================================

到此筆者在工作中涉及的限流用法就介紹完,這些算法中有些允許突發(fā)垒棋,有些會整形為平滑卒煞,有些計算算法簡單粗暴;其中令牌桶算法和漏桶算法實現(xiàn)上是類似的叼架,只是表述的方向不太一樣畔裕,對于業(yè)務來說不必刻意去區(qū)分它們衣撬;因此需要根據(jù)實際場景來決定如何限流,最好的算法不一定是最適用的扮饶。

參考資料

https://en.wikipedia.org/wiki/Token_bucket

https://en.wikipedia.org/wiki/Leaky_bucket

http://redis.io/commands/incr

http://nginx.org/en/docs/http/ngx_http_limit_req_module.html

http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html

https://github.com/openresty/lua-resty-limit-traffic

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末淮韭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子贴届,更是在濱河造成了極大的恐慌靠粪,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件毫蚓,死亡現(xiàn)場離奇詭異占键,居然都是意外死亡,警方通過查閱死者的電腦和手機元潘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門畔乙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人翩概,你說我怎么就攤上這事牲距。” “怎么了钥庇?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵牍鞠,是天一觀的道長。 經常有香客問我评姨,道長难述,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任吐句,我火速辦了婚禮胁后,結果婚禮上,老公的妹妹穿的比我還像新娘嗦枢。我一直安慰自己墓赴,他們只是感情好悼嫉,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布步咪。 她就那樣靜靜地躺著坷备,像睡著了一般。 火紅的嫁衣襯著肌膚如雪择葡。 梳的紋絲不亂的頭發(fā)上紧武,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音敏储,去河邊找鬼阻星。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的妥箕。 我是一名探鬼主播滥酥,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼畦幢!你這毒婦竟也來了坎吻?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤宇葱,失蹤者是張志新(化名)和其女友劉穎瘦真,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體黍瞧,經...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡诸尽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了印颤。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片您机。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖年局,靈堂內的尸體忽然破棺而出际看,到底是詐尸還是另有隱情,我是刑警寧澤矢否,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布仲闽,位于F島的核電站,受9級特大地震影響兴喂,放射性物質發(fā)生泄漏蔼囊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一衣迷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧酱酬,春花似錦壶谒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至挑社,卻和暖如春陨界,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背痛阻。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工菌瘪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓俏扩,卻偏偏與公主長得像糜工,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子录淡,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內容