Spring Cloud Gateway:新一代API網(wǎng)關(guān)服務(wù)

Spring Cloud Gateway 為 SpringBoot 應(yīng)用提供了API網(wǎng)關(guān)支持关摇,具有強大的智能路由與過濾器功能,本文將對其用法進行詳細介紹浮禾。

Gateway 簡介

Gateway是在Spring生態(tài)系統(tǒng)之上構(gòu)建的API網(wǎng)關(guān)服務(wù),基于Spring 5,Spring Boot 2和 Project Reactor等技術(shù)比被。Gateway旨在提供一種簡單而有效的方式來對API進行路由,以及提供一些強大的過濾器功能泼舱, 例如:熔斷等缀、限流、重試等娇昙。

Spring Cloud Gateway 具有如下特性:

基于Spring Framework 5, Project Reactor 和 Spring Boot 2.0 進行構(gòu)建尺迂;

動態(tài)路由:能夠匹配任何請求屬性;

可以對路由指定 Predicate(斷言)和 Filter(過濾器)冒掌;

集成Hystrix的斷路器功能噪裕;

集成 Spring Cloud 服務(wù)發(fā)現(xiàn)功能;

易于編寫的 Predicate(斷言)和 Filter(過濾器)股毫;

請求限流功能膳音;

支持路徑重寫。

相關(guān)概念

Route(路由):路由是構(gòu)建網(wǎng)關(guān)的基本模塊皇拣,它由ID严蓖,目標URI薄嫡,一系列的斷言和過濾器組成,如果斷言為true則匹配該路由颗胡;

Predicate(斷言):指的是Java 8 的 Function Predicate毫深。 輸入類型是Spring框架中的ServerWebExchange。 這使開發(fā)人員可以匹配HTTP請求中的所有內(nèi)容毒姨,例如請求頭或請求參數(shù)哑蔫。如果請求與斷言相匹配,則進行路由弧呐;

Filter(過濾器):指的是Spring框架中GatewayFilter的實例闸迷,使用過濾器,可以在請求被路由前后對請求進行修改俘枫。

創(chuàng)建 api-gateway模塊

這里我們創(chuàng)建一個api-gateway模塊來演示Gateway的常用功能腥沽。

在pom.xml中添加相關(guān)依賴

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency>Copy to clipboardErrorCopied

兩種不同的配置路由方式

Gateway 提供了兩種不同的方式用于配置路由,一種是通過yml文件來配置鸠蚪,另一種是通過Java Bean來配置今阳,下面我們分別介紹下。

使用yml配置

在application.yml中進行配置:

server:

? port: 9201

service-url:

? user-service: http://localhost:8201

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? ? - id: path_route #路由的ID

? ? ? ? ? uri: ${service-url.user-service}/user/{id} #匹配后路由地址

? ? ? ? ? predicates: # 斷言茅信,路徑相匹配的進行路由

? ? ? ? ? ? - Path=/user/{id}Copy to clipboardErrorCopied

啟動eureka-server盾舌,user-service和api-gateway服務(wù),并調(diào)用該地址測試:http://localhost:9201/user/1

我們發(fā)現(xiàn)該請求被路由到了user-service的該路徑上:http://localhost:8201/user/1

使用Java Bean配置

添加相關(guān)配置類蘸鲸,并配置一個RouteLocator對象:

/**

* Created by macro on 2019/9/24.

*/@ConfigurationpublicclassGatewayConfig{@BeanpublicRouteLocatorcustomRouteLocator(RouteLocatorBuilderbuilder){returnbuilder.routes().route("path_route2",r->r.path("/user/getByUsername").uri("http://localhost:8201/user/getByUsername")).build();}}Copy to clipboardErrorCopied

重新啟動api-gateway服務(wù)妖谴,并調(diào)用該地址測試:http://localhost:9201/user/getByUsername?username=macro

我們發(fā)現(xiàn)該請求被路由到了user-service的該路徑上:http://localhost:8201/user/getByUsername?username=macro

Route Predicate 的使用

Spring Cloud Gateway將路由匹配作為Spring WebFlux HandlerMapping基礎(chǔ)架構(gòu)的一部分。 Spring Cloud Gateway包括許多內(nèi)置的Route Predicate工廠酌摇。 所有這些Predicate都與HTTP請求的不同屬性匹配膝舅。 多個Route Predicate工廠可以進行組合,下面我們來介紹下一些常用的Route Predicate妙痹。

注意:Predicate中提到的配置都在application-predicate.yml文件中進行修改铸史,并用該配置啟動api-gateway服務(wù)。

After Route Predicate

在指定時間之后的請求會匹配該路由怯伊。

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? ? - id: after_route

? ? ? ? ? uri: ${service-url.user-service}

? ? ? ? ? predicates:

? ? ? ? ? ? - After=2019-09-24T16:30:00+08:00[Asia/Shanghai]Copy to clipboardErrorCopied

Before Route Predicate

在指定時間之前的請求會匹配該路由琳轿。

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? ? - id: before_route

? ? ? ? ? uri: ${service-url.user-service}

? ? ? ? ? predicates:

? ? ? ? ? ? - Before=2019-09-24T16:30:00+08:00[Asia/Shanghai]Copy to clipboardErrorCopied

Between Route Predicate

在指定時間區(qū)間內(nèi)的請求會匹配該路由。

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? ? - id: before_route

? ? ? ? ? uri: ${service-url.user-service}

? ? ? ? ? predicates:

? ? ? ? ? ? - Between=2019-09-24T16:30:00+08:00[Asia/Shanghai], 2019-09-25T16:30:00+08:00[Asia/Shanghai]Copy to clipboardErrorCopied

Cookie Route Predicate

帶有指定Cookie的請求會匹配該路由耿芹。

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? ? - id: cookie_route

? ? ? ? ? uri: ${service-url.user-service}

? ? ? ? ? predicates:

? ? ? ? ? ? - Cookie=username,macroCopy to clipboardErrorCopied

使用curl工具發(fā)送帶有cookie為username=macro的請求可以匹配該路由崭篡。

curlhttp://localhost:9201/user/1 --cookie"username=macro"Copy to clipboardErrorCopied

Header Route Predicate

帶有指定請求頭的請求會匹配該路由。

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? - id: header_route

? ? ? ? uri: ${service-url.user-service}

? ? ? ? predicates:

? ? ? ? - Header=X-Request-Id, \d+Copy to clipboardErrorCopied

使用curl工具發(fā)送帶有請求頭為X-Request-Id:123的請求可以匹配該路由吧秕。

curlhttp://localhost:9201/user/1 -H"X-Request-Id:123"Copy to clipboardErrorCopied

Host Route Predicate

帶有指定Host的請求會匹配該路由琉闪。

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? ? - id: host_route

? ? ? ? ? uri: ${service-url.user-service}

? ? ? ? ? predicates:

? ? ? ? ? ? - Host=**.macrozheng.comCopy to clipboardErrorCopied

使用curl工具發(fā)送帶有請求頭為Host:www.macrozheng.com的請求可以匹配該路由。

curlhttp://localhost:9201/user/1 -H"Host:www.macrozheng.com"Copy to clipboardErrorCopied

Method Route Predicate

發(fā)送指定方法的請求會匹配該路由砸彬。

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? - id: method_route

? ? ? ? uri: ${service-url.user-service}

? ? ? ? predicates:

? ? ? ? - Method=GETCopy to clipboardErrorCopied

使用curl工具發(fā)送GET請求可以匹配該路由颠毙。

curlhttp://localhost:9201/user/1Copy to clipboardErrorCopied

使用curl工具發(fā)送POST請求無法匹配該路由斯入。

curl-X POST http://localhost:9201/user/1Copy to clipboardErrorCopied

Path Route Predicate

發(fā)送指定路徑的請求會匹配該路由。

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? ? - id: path_route

? ? ? ? ? uri: ${service-url.user-service}/user/{id}

? ? ? ? ? predicates:

? ? ? ? ? ? - Path=/user/{id}Copy to clipboardErrorCopied

使用curl工具發(fā)送/user/1路徑請求可以匹配該路由蛀蜜。

curlhttp://localhost:9201/user/1Copy to clipboardErrorCopied

使用curl工具發(fā)送/abc/1路徑請求無法匹配該路由刻两。

curlhttp://localhost:9201/abc/1Copy to clipboardErrorCopied

Query Route Predicate

帶指定查詢參數(shù)的請求可以匹配該路由。

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? - id: query_route

? ? ? ? uri: ${service-url.user-service}/user/getByUsername

? ? ? ? predicates:

? ? ? ? - Query=usernameCopy to clipboardErrorCopied

使用curl工具發(fā)送帶username=macro查詢參數(shù)的請求可以匹配該路由滴某。

curlhttp://localhost:9201/user/getByUsername?username=macroCopy to clipboardErrorCopied

使用curl工具發(fā)送帶不帶查詢參數(shù)的請求無法匹配該路由磅摹。

curlhttp://localhost:9201/user/getByUsernameCopy to clipboardErrorCopied

RemoteAddr Route Predicate

從指定遠程地址發(fā)起的請求可以匹配該路由。

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? - id: remoteaddr_route

? ? ? ? uri: ${service-url.user-service}

? ? ? ? predicates:

? ? ? ? - RemoteAddr=192.168.1.1/24Copy to clipboardErrorCopied

使用curl工具從192.168.1.1發(fā)起請求可以匹配該路由霎奢。

curlhttp://localhost:9201/user/1Copy to clipboardErrorCopied

Weight Route Predicate

使用權(quán)重來路由相應(yīng)請求户誓,以下表示有80%的請求會被路由到localhost:8201,20%會被路由到localhost:8202幕侠。

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? - id: weight_high

? ? ? ? uri: http://localhost:8201

? ? ? ? predicates:

? ? ? ? - Weight=group1, 8

? ? ? - id: weight_low

? ? ? ? uri: http://localhost:8202

? ? ? ? predicates:

? ? ? ? - Weight=group1, 2Copy to clipboardErrorCopied

Route Filter 的使用

路由過濾器可用于修改進入的HTTP請求和返回的HTTP響應(yīng)帝美,路由過濾器只能指定路由進行使用。Spring Cloud Gateway 內(nèi)置了多種路由過濾器橙依,他們都由GatewayFilter的工廠類來產(chǎn)生证舟,下面我們介紹下常用路由過濾器的用法。

AddRequestParameter GatewayFilter

給請求添加參數(shù)的過濾器窗骑。

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? ? - id: add_request_parameter_route

? ? ? ? ? uri: http://localhost:8201

? ? ? ? ? filters:

? ? ? ? ? ? - AddRequestParameter=username, macro

? ? ? ? ? predicates:

? ? ? ? ? ? - Method=GETCopy to clipboardErrorCopied

以上配置會對GET請求添加username=macro的請求參數(shù),通過curl工具使用以下命令進行測試漆枚。

curlhttp://localhost:9201/user/getByUsernameCopy to clipboardErrorCopied

相當(dāng)于發(fā)起該請求:

curlhttp://localhost:8201/user/getByUsername?username=macroCopy to clipboardErrorCopied

StripPrefix GatewayFilter

對指定數(shù)量的路徑前綴進行去除的過濾器创译。

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? - id: strip_prefix_route

? ? ? ? uri: http://localhost:8201

? ? ? ? predicates:

? ? ? ? - Path=/user-service/**

? ? ? ? filters:

? ? ? ? - StripPrefix=2Copy to clipboardErrorCopied

以上配置會把以/user-service/開頭的請求的路徑去除兩位,通過curl工具使用以下命令進行測試墙基。

curlhttp://localhost:9201/user-service/a/user/1Copy to clipboardErrorCopied

相當(dāng)于發(fā)起該請求:

curlhttp://localhost:8201/user/1Copy to clipboardErrorCopied

PrefixPath GatewayFilter

與StripPrefix過濾器恰好相反软族,會對原有路徑進行增加操作的過濾器。

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? - id: prefix_path_route

? ? ? ? uri: http://localhost:8201

? ? ? ? predicates:

? ? ? ? - Method=GET

? ? ? ? filters:

? ? ? ? - PrefixPath=/userCopy to clipboardErrorCopied

以上配置會對所有GET請求添加/user路徑前綴残制,通過curl工具使用以下命令進行測試立砸。

curlhttp://localhost:9201/1Copy to clipboardErrorCopied

相當(dāng)于發(fā)起該請求:

curlhttp://localhost:8201/user/1Copy to clipboardErrorCopied

Hystrix GatewayFilter

Hystrix 過濾器允許你將斷路器功能添加到網(wǎng)關(guān)路由中,使你的服務(wù)免受級聯(lián)故障的影響初茶,并提供服務(wù)降級處理颗祝。

要開啟斷路器功能,我們需要在pom.xml中添加Hystrix的相關(guān)依賴:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency>Copy to clipboardErrorCopied

然后添加相關(guān)服務(wù)降級的處理類:

/**

* Created by macro on 2019/9/25.

*/@RestControllerpublicclassFallbackController{@GetMapping("/fallback")publicObjectfallback(){Map<String,Object>result=newHashMap<>();result.put("data",null);result.put("message","Get request fallback!");result.put("code",500);returnresult;}}Copy to clipboardErrorCopied

在application-filter.yml中添加相關(guān)配置恼布,當(dāng)路由出錯時會轉(zhuǎn)發(fā)到服務(wù)降級處理的控制器上:

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? ? - id: hystrix_route

? ? ? ? ? uri: http://localhost:8201

? ? ? ? ? predicates:

? ? ? ? ? ? - Method=GET

? ? ? ? ? filters:

? ? ? ? ? ? - name: Hystrix

? ? ? ? ? ? ? args:

? ? ? ? ? ? ? ? name: fallbackcmd

? ? ? ? ? ? ? ? fallbackUri: forward:/fallbackCopy to clipboardErrorCopied

關(guān)閉user-service螺戳,調(diào)用該地址進行測試:http://localhost:9201/user/1?,發(fā)現(xiàn)已經(jīng)返回了服務(wù)降級的處理信息折汞。

RequestRateLimiter GatewayFilter

RequestRateLimiter 過濾器可以用于限流倔幼,使用RateLimiter實現(xiàn)來確定是否允許當(dāng)前請求繼續(xù)進行,如果請求太大默認會返回HTTP 429-太多請求狀態(tài)爽待。

在pom.xml中添加相關(guān)依賴:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis-reactive</artifactId></dependency>Copy to clipboardErrorCopied

添加限流策略的配置類损同,這里有兩種策略一種是根據(jù)請求參數(shù)中的username進行限流翩腐,另一種是根據(jù)訪問IP進行限流;

/**

* Created by macro on 2019/9/25.

*/@ConfigurationpublicclassRedisRateLimiterConfig{@BeanKeyResolveruserKeyResolver(){returnexchange->Mono.just(exchange.getRequest().getQueryParams().getFirst("username"));}@BeanpublicKeyResolveripKeyResolver(){returnexchange->Mono.just(exchange.getRequest().getRemoteAddress().getHostName());}}Copy to clipboardErrorCopied

我們使用Redis來進行限流膏燃,所以需要添加Redis和RequestRateLimiter的配置栗菜,這里對所有的GET請求都進行了按IP來限流的操作;

server:

? port: 9201

spring:

? redis:

? ? host: localhost

? ? password: 123456

? ? port: 6379

? cloud:

? ? gateway:

? ? ? routes:

? ? ? ? - id: requestratelimiter_route

? ? ? ? ? uri: http://localhost:8201

? ? ? ? ? filters:

? ? ? ? ? ? - name: RequestRateLimiter

? ? ? ? ? ? ? args:

? ? ? ? ? ? ? ? redis-rate-limiter.replenishRate: 1 #每秒允許處理的請求數(shù)量

? ? ? ? ? ? ? ? redis-rate-limiter.burstCapacity: 2 #每秒最大處理的請求數(shù)量

? ? ? ? ? ? ? ? key-resolver: "#{@ipKeyResolver}" #限流策略蹄梢,對應(yīng)策略的Bean

? ? ? ? ? predicates:

? ? ? ? ? ? - Method=GET

logging:

? level:

? ? org.springframework.cloud.gateway: debugCopy to clipboardErrorCopied

多次請求該地址:http://localhost:9201/user/1?疙筹,會返回狀態(tài)碼為429的錯誤;

Retry GatewayFilter

對路由請求進行重試的過濾器禁炒,可以根據(jù)路由請求返回的HTTP狀態(tài)碼來確定是否進行重試而咆。

修改配置文件:

spring:

? cloud:

? ? gateway:

? ? ? routes:

? ? ? - id: retry_route

? ? ? ? uri: http://localhost:8201

? ? ? ? predicates:

? ? ? ? - Method=GET

? ? ? ? filters:

? ? ? ? - name: Retry

? ? ? ? ? args:

? ? ? ? ? ? retries: 1 #需要進行重試的次數(shù)

? ? ? ? ? ? statuses: BAD_GATEWAY #返回哪個狀態(tài)碼需要進行重試,返回狀態(tài)碼為5XX進行重試

? ? ? ? ? ? backoff:

? ? ? ? ? ? ? firstBackoff: 10ms

? ? ? ? ? ? ? maxBackoff: 50ms

? ? ? ? ? ? ? factor: 2

? ? ? ? ? ? ? basedOnPreviousValue: falseCopy to clipboardErrorCopied

當(dāng)調(diào)用返回500時會進行重試幕袱,訪問測試地址:http://localhost:9201/user/111

可以發(fā)現(xiàn)user-service控制臺報錯2次暴备,說明進行了一次重試。

2019-10-2714:08:53.435 ERROR2280---[nio-8201-exec-2]o.a.c.c.C.[.[.[/].[dispatcherServlet]:Servlet.service()forservlet[dispatcherServlet]incontext with path[]threw exception[Request processing failed;nested exception is java.lang.NullPointerException]with root causejava.lang.NullPointerException: null? ? at com.macro.cloud.controller.UserController.getUser(UserController.java:34)~[classes/:na]Copy to clipboardErrorCopied

結(jié)合注冊中心使用

我們上次講到使用Zuul作為網(wǎng)關(guān)結(jié)合注冊中心進行使用時们豌,默認情況下Zuul會根據(jù)注冊中心注冊的服務(wù)列表涯捻,以服務(wù)名為路徑創(chuàng)建動態(tài)路由,Gateway同樣也實現(xiàn)了該功能望迎。下面我們演示下Gateway結(jié)合注冊中心如何使用默認的動態(tài)路由和過濾器障癌。

使用動態(tài)路由

在pom.xml中添加相關(guān)依賴:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>Copy to clipboardErrorCopied

添加application-eureka.yml配置文件:

server:

? port: 9201

spring:

? application:

? ? name: api-gateway

? cloud:

? ? gateway:

? ? ? discovery:

? ? ? ? locator:

? ? ? ? ? enabled: true #開啟從注冊中心動態(tài)創(chuàng)建路由的功能

? ? ? ? ? lower-case-service-id: true #使用小寫服務(wù)名,默認是大寫

eureka:

? client:

? ? service-url:

? ? ? defaultZone: http://localhost:8001/eureka/

logging:

? level:

? ? org.springframework.cloud.gateway: debugCopy to clipboardErrorCopied

使用application-eureka.yml配置文件啟動api-gateway服務(wù)辩尊,訪問http://localhost:9201/user-service/user/1?涛浙,可以路由到user-service的http://localhost:8201/user/1?處。

使用過濾器

在結(jié)合注冊中心使用過濾器的時候摄欲,我們需要注意的是uri的協(xié)議為lb轿亮,這樣才能啟用Gateway的負載均衡功能。

修改application-eureka.yml文件胸墙,使用了PrefixPath過濾器我注,會為所有GET請求路徑添加/user路徑并路由;

server:

? port: 9201

spring:

? application:

? ? name: api-gateway

? cloud:

? ? gateway:

? ? ? routes:

? ? ? ? - id: prefixpath_route

? ? ? ? ? uri: lb://user-service #此處需要使用lb協(xié)議

? ? ? ? ? predicates:

? ? ? ? ? ? - Method=GET

? ? ? ? ? filters:

? ? ? ? ? ? - PrefixPath=/user

? ? ? discovery:

? ? ? ? locator:

? ? ? ? ? enabled: true

eureka:

? client:

? ? service-url:

? ? ? defaultZone: http://localhost:8001/eureka/

logging:

? level:

? ? org.springframework.cloud.gateway: debugCopy to clipboardErrorCopied

使用application-eureka.yml配置文件啟動api-gateway服務(wù)迟隅,訪問http://localhost:9201/1?但骨,可以路由到user-service的http://localhost:8201/user/1?處。

使用到的模塊

springcloud-learning

├── eureka-server -- eureka注冊中心

├── user-service -- 提供User對象CRUD接口的服務(wù)

└── api-gateway -- gateway作為網(wǎng)關(guān)的測試服務(wù)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末玻淑,一起剝皮案震驚了整個濱河市嗽冒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌补履,老刑警劉巖添坊,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異箫锤,居然都是意外死亡贬蛙,警方通過查閱死者的電腦和手機雨女,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阳准,“玉大人氛堕,你說我怎么就攤上這事∫坝” “怎么了讼稚?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長绕沈。 經(jīng)常有香客問我锐想,道長,這世上最難降的妖魔是什么乍狐? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任赠摇,我火速辦了婚禮,結(jié)果婚禮上浅蚪,老公的妹妹穿的比我還像新娘藕帜。我一直安慰自己,他們只是感情好惜傲,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布洽故。 她就那樣靜靜地躺著,像睡著了一般操漠。 火紅的嫁衣襯著肌膚如雪收津。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天浊伙,我揣著相機與錄音,去河邊找鬼长捧。 笑死嚣鄙,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的串结。 我是一名探鬼主播哑子,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼肌割!你這毒婦竟也來了卧蜓?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤把敞,失蹤者是張志新(化名)和其女友劉穎弥奸,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奋早,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡盛霎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年赠橙,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片愤炸。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡期揪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出规个,到底是詐尸還是另有隱情凤薛,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布诞仓,位于F島的核電站缤苫,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏狂芋。R本人自食惡果不足惜榨馁,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望帜矾。 院中可真熱鬧翼虫,春花似錦、人聲如沸屡萤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽死陆。三九已至招拙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間措译,已是汗流浹背别凤。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留领虹,地道東北人规哪。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像塌衰,于是被迫代替她去往敵國和親诉稍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354