你都用過(guò)SpringCloud的哪些組件,它們的原理是什么吐葵?

前言

看到文章的題目了嗎规揪?就是這么抽象和籠統(tǒng)的一個(gè)問(wèn)題,確實(shí)是我面試中真實(shí)被問(wèn)到的温峭,某共享貨車平臺(tái)的真實(shí)面試問(wèn)題猛铅。

SpringCloud確實(shí)是用過(guò),但是那是三四年前了凤藏,那個(gè)時(shí)候SpringCloud剛開(kāi)始流行沒(méi)多久奸忽,我們技術(shù)總監(jiān)讓我們調(diào)研一下堕伪,然后算上我在內(nèi)的三個(gè)同事就一人買了一本SpringCloud的書籍,開(kāi)始看栗菜,開(kāi)始研究欠雌,正好那個(gè)時(shí)候DDD也比較火,然后我們就一邊研究的SpringCloud一邊按照DDD的模型搭建自己的項(xiàng)目疙筹。

但是這個(gè)項(xiàng)目最后做了三個(gè)月富俄,才完成了一期。后面二期還沒(méi)開(kāi)始腌歉,我就撤了蛙酪。所以SpringCloud總共的使用時(shí)間就兩三個(gè)月齐苛,所以對(duì)這部分知識(shí)掌握的并不扎實(shí)翘盖,而且入職了新公司之后,都是使用公司自己封裝的框架凹蜂,也已經(jīng)三年沒(méi)有用過(guò)SpringCloud了馍驯,這次是要面試換工作了,所以決定將這方面的知識(shí)玛痊,總結(jié)一下汰瘫。

服務(wù)治理 Spring Cloud Eureka

我們之前在使用服務(wù)之間相互調(diào)用的時(shí)候,一般是靠一些靜態(tài)配置來(lái)完成的擂煞。比如服務(wù)A混弥,要調(diào)用服務(wù)B來(lái)完成一個(gè)業(yè)務(wù)操作時(shí),為了實(shí)現(xiàn)服務(wù)B的高可用对省,一般是通過(guò)手動(dòng)配置來(lái)完成服務(wù)B的服務(wù)實(shí)例清單的維護(hù)蝗拿。

隨著業(yè)務(wù)的發(fā)展,系統(tǒng)功能越來(lái)越復(fù)雜蒿涎,相應(yīng)的服務(wù)不斷增加哀托,而且服務(wù)的IP還一直在變化,靜態(tài)配置來(lái)維護(hù)各服務(wù)劳秋,就會(huì)變得越來(lái)越困難仓手。

image

這個(gè)時(shí)候就出現(xiàn)了服務(wù)治理框架,Spring Cloud Eureka玻淑。

Spring Cloud Eureka 主要是圍繞著服務(wù)注冊(cè)與服務(wù)發(fā)現(xiàn)機(jī)制來(lái)完成對(duì)微服務(wù)的自動(dòng)化管理的嗽冒。

服務(wù)注冊(cè)

Eureka提供了服務(wù)端組件,我們也稱為注冊(cè)中心补履。每個(gè)服務(wù)都向Eureka的服務(wù)注冊(cè)中心辛慰,登記自己提供服務(wù)的元數(shù)據(jù),包括服務(wù)的ip地址干像、端口號(hào)帅腌、版本號(hào)驰弄、通信協(xié)議等。這樣注冊(cè)中心速客,就將各個(gè)服務(wù)維護(hù)在了一個(gè)服務(wù)清單中(雙層Map戚篙,第一層key是服務(wù)名,第二層key是實(shí)例名溺职,value是服務(wù)地址加端口)岔擂。

image

服務(wù)注冊(cè)中心,還會(huì)以心跳的方式去監(jiān)聽(tīng)清單中的服務(wù)是否可用(默認(rèn)30秒)浪耘,若不可用(服務(wù)續(xù)約時(shí)間默認(rèn)90秒)乱灵,需從清單中剔除,達(dá)到排除故障服務(wù)的效果七冲。

Eureka注冊(cè)中心提供了高可用方案痛倚,可以支持集群部署注冊(cè)中心,然后多個(gè)注冊(cè)中心實(shí)例之間又相互注冊(cè)澜躺,這樣每個(gè)實(shí)例中都有一樣的服務(wù)清單了蝉稳。

服務(wù)發(fā)現(xiàn)

Eureka不但提供服務(wù)端,還提供了客戶端掘鄙,客戶端是在各個(gè)服務(wù)中運(yùn)行的耘戚。

Eureka客戶端主要有兩個(gè)作用:

  • 向注冊(cè)中心注冊(cè)自身提供的服務(wù),并周期性的發(fā)送心跳來(lái)更新它非服務(wù)租約 操漠。
  • 同時(shí)收津,也能從服務(wù)端查詢當(dāng)前注冊(cè)的服務(wù)信息,并把他們緩存到本地浊伙,并周期性的刷新服務(wù)狀態(tài) 撞秋。

在Eureka Server中注冊(cè)的服務(wù),相互之間調(diào)用吧黄,不再是通過(guò)指定的具體實(shí)例地址部服,而是通過(guò)向服務(wù)名發(fā)請(qǐng)求實(shí)現(xiàn)調(diào)用,因?yàn)槊總€(gè)服務(wù)服務(wù)都是多實(shí)例拗慨,并且實(shí)例地址還有可能經(jīng)常變廓八。

但是通過(guò)服務(wù)名稱調(diào)用,并不知道具體的服務(wù)實(shí)例位置赵抢,因此需要向注冊(cè)中心咨詢剧蹂,并獲取所有服務(wù)實(shí)例清單,然后實(shí)現(xiàn)服務(wù)的請(qǐng)求訪問(wèn)烦却。

舉例

image

服務(wù)A的一個(gè)業(yè)務(wù)操作宠叼,需要調(diào)用服務(wù)B和服務(wù)C來(lái)完成。

那么服務(wù)A和服務(wù)B和服務(wù)C都將自己注冊(cè)到Eureka的注冊(cè)中心,然后服務(wù)A通過(guò)咨詢注冊(cè)中心冒冬,將注冊(cè)中心的服務(wù)列表清單緩存到自己本地伸蚯。

通過(guò)服務(wù)名稱獲取到服務(wù)B和服務(wù)C的服務(wù)實(shí)例地址,最后通過(guò)一種輪詢策略取出一個(gè)具體的服務(wù)實(shí)例地址來(lái)進(jìn)行調(diào)用简烤。

總結(jié)一下

Eureka Client : 主要是將服務(wù)本身注冊(cè)到Eureka Server中剂邮,同時(shí)查詢Eureka Server的注冊(cè)服務(wù)列表緩存到本地 。

Eureka Server: 注冊(cè)中心横侦,保存了所有注冊(cè)服務(wù)的元數(shù)據(jù)挥萌,包括ip地址,端口等信息枉侧。

客戶端負(fù)載均衡 Spring Cloud Ribbon

服務(wù)的調(diào)用方引瀑,在通過(guò)Eureka Client緩存到本地的注冊(cè)表之后,通過(guò)服務(wù)名稱榨馁,找到具體的服務(wù)對(duì)應(yīng)的實(shí)例地址憨栽,但是被調(diào)用方的服務(wù)地址是有多個(gè)的,那么該用那個(gè)地址去進(jìn)行調(diào)用呢辆影?

服務(wù)A:
192.168.12.10:9001
192.168.12.11:9001
192.168.12.12:9001

這個(gè)時(shí)候 Spring Cloud Ribbon 就出現(xiàn)了徒像,它是專門解決這個(gè)問(wèn)題的黍特,它的作用就是做負(fù)載均衡蛙讥,會(huì)均勻的把請(qǐng)求分發(fā)到每臺(tái)機(jī)器上。

Ribbon默認(rèn)使用 Round Ribbon 的策略進(jìn)行負(fù)載均衡灭衷,具體就是采用輪詢的方式進(jìn)行請(qǐng)求次慢。

Ribbon除了有 Round Ribbon 這種輪詢策略,還有其他策略以及自定義策略翔曲。

主要有:

  • RandomRole : 從服務(wù)實(shí)例清單中隨機(jī)選擇一個(gè)服務(wù)實(shí)例迫像。
  • RoundRobinRule : 按照線性輪詢的方式依次選擇每個(gè)服務(wù)實(shí)例。
  • RetryRule :根據(jù)輪詢方式進(jìn)行瞳遍,且具備重試機(jī)制進(jìn)行選擇實(shí)例闻妓。
  • WeightedResponseTimeRule :對(duì) RoundRobinRule 的擴(kuò)展,增加了根據(jù)實(shí)例的運(yùn)行情況來(lái)計(jì)算權(quán)重掠械,并根據(jù)權(quán)重來(lái)挑選實(shí)例由缆。
  • ZoneAvoidanceRule :根據(jù)服務(wù)方的zone區(qū)域和可用性來(lái)輪詢選擇。

Spring Cloud Ribbon具體的執(zhí)行示例如下:

image

實(shí)例代碼

下面的代碼就是通過(guò)Ribbon調(diào)用服務(wù)的代碼實(shí)例猾蒂。

@RestController
public class ConsumerController {
    @Autowired
    RestTemplate restTemplate;
    @GetMapping("/ribbon-consumer")
    public String helloConsumer(){
        return restTemplate.getForEntity("http://example-service/index",String.class).getBody();
    }
}

可以看到Ribbon也是通過(guò)發(fā)起http請(qǐng)求均唉,來(lái)進(jìn)行的調(diào)用,只不過(guò)是通過(guò)調(diào)用服務(wù)名的地址來(lái)實(shí)現(xiàn)的肚菠。雖然說(shuō)Ribbon不用去具體請(qǐng)求服務(wù)實(shí)例的ip地址或域名了舔箭,但是每調(diào)用一個(gè)接口都還要手動(dòng)去發(fā)起Http請(qǐng)求,也是比較繁瑣的蚊逢,而且返回類型也比較抽象层扶,所以Spring Cloud對(duì)調(diào)用方式進(jìn)行了升級(jí)封裝箫章。

聲明式服務(wù)調(diào)用 Spring Cloud Feign

Spring Cloud 為了簡(jiǎn)化服務(wù)間的調(diào)用,在Ribbon的基礎(chǔ)上進(jìn)行了進(jìn)一步的封裝镜会。單獨(dú)抽出了一個(gè)組件炉抒,就是Spring Cloud Feign。在引入Spring Cloud Feign后稚叹,我們只需要?jiǎng)?chuàng)建一個(gè)接口并用注解的方式來(lái)配置它焰薄,即可完成對(duì)服務(wù)提供方的接口綁定。

Spring Cloud Feign具備可插拔的注解支持扒袖,并擴(kuò)展了Spring MVC的注解支持塞茅。

下面我們來(lái)看一個(gè)具體的例子:

服務(wù)方具體的接口定義與實(shí)現(xiàn)代碼如下:

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
/**
 * 接口定義
 */
@FeignClient(value="service-hi",fallback = TestFeignServiceImpl.class)
public interface TestFeignService {

    @RequestMapping(value="/hi",method = RequestMethod.GET)
    String sayHi(@RequestParam("name") String name);
}
/**
 * 具體的服務(wù)實(shí)現(xiàn)
 */
@Component
public class TestFeignServiceImpl implements TestFeignService {
    @Override
    public String sayHi(String name) {
        return "你好,"+name;
    }
}

調(diào)用方的使用代碼如下:

@RestController
public class TestController
{
    @Resource
    private TestFeignService testFeignService;

    @RequestMapping(value="/hi",method = RequestMethod.GET)
    public String sayHi(@RequestParam String name)
    {
        // 調(diào)用遠(yuǎn)程服務(wù)
        return testFeignService.sayHi(name);
    }
}

通過(guò)上面的代碼,我們可以看到季率,調(diào)用方通過(guò)Feign進(jìn)程遠(yuǎn)程服務(wù)調(diào)用的時(shí)候野瘦,非常簡(jiǎn)單,就向是在調(diào)用本地服務(wù)一樣飒泻。

像之前的建立連接鞭光,構(gòu)造請(qǐng)求,發(fā)起請(qǐng)求泞遗,獲取響應(yīng)惰许,解析響應(yīng)等等操作,對(duì)使用者來(lái)說(shuō)都是透明化的史辙,使用者不用關(guān)心服務(wù)是怎么實(shí)現(xiàn)調(diào)用的汹买,直接使用即可。

那么Feign是如何實(shí)現(xiàn)這套封裝邏輯的呢聊倔?

其實(shí) Feign底層主要是靠動(dòng)態(tài)代理來(lái)實(shí)現(xiàn)這整個(gè)服務(wù)的調(diào)用過(guò)程的晦毙。

主要邏輯如下:

  • 如果一個(gè)接口上定義了@FeignClient注解,F(xiàn)eign就會(huì)根據(jù)這個(gè)接口生成一個(gè)動(dòng)態(tài)代理類耙蔑。
  • 如果調(diào)用方见妒,在調(diào)用這個(gè)定義了@FeignClient注解的接口時(shí),本質(zhì)上是會(huì)調(diào)用Feign生成的代理類甸陌。
  • Feign生成的動(dòng)態(tài)代理類须揣,會(huì)根據(jù)具體接口方法中的@RequestMapping等注解,來(lái)動(dòng)態(tài)構(gòu)造出需要請(qǐng)求的服務(wù)地址邀层。
  • 最后針對(duì)這個(gè)地址返敬,再通過(guò)Ribbon發(fā)起服務(wù)調(diào)用,解析響應(yīng)等操作寥院。
image

因?yàn)镾pring Cloud Feign的使用方式比Spring Cloud Ribbon更方便劲赠,所以一般項(xiàng)目中都是使用Feign,而且Feign還有繼承特性,可以將遠(yuǎn)程服務(wù)接口繼承過(guò)來(lái)然后再進(jìn)行自己的個(gè)性化擴(kuò)展凛澎。因此Feign的使用范圍以及普及率更高一些霹肝。

服務(wù)容錯(cuò)保護(hù) Spring Cloud Hystrix

在微服務(wù)架構(gòu)中,我們將系統(tǒng)拆分成多個(gè)服務(wù)單元塑煎,各個(gè)服務(wù)之間通過(guò)服務(wù)注冊(cè)與訂閱的方式互相依賴沫换。

我們以一個(gè)電商網(wǎng)站下單的過(guò)程來(lái)舉例,在下單的業(yè)務(wù)操作過(guò)程中需要調(diào)用庫(kù)存服務(wù)最铁,支付服務(wù)讯赏,積分、物流等服務(wù)冷尉。 假設(shè)訂單服務(wù)最多同一時(shí)間只能處理50個(gè)請(qǐng)求漱挎,這個(gè)時(shí)候如果積分服務(wù)掛了,那么每次訂單服務(wù)去調(diào)用積分服務(wù)的時(shí)候雀哨,都會(huì)卡這么一段時(shí)間磕谅,然后才返回超時(shí)異常 。

在這種場(chǎng)景下會(huì)有什么問(wèn)題呢雾棺?

如果目前電商網(wǎng)站正在搞活動(dòng)膊夹,進(jìn)行搶購(gòu)活動(dòng),下單的人非常多捌浩,這種高并發(fā)的場(chǎng)景下放刨,訂單服務(wù)的已經(jīng)同時(shí)在處理50個(gè)下單請(qǐng)求了,并且都卡在了請(qǐng)求積分服務(wù)的過(guò)程中嘉栓。訂單服務(wù)已經(jīng)沒(méi)有能力去處理其他請(qǐng)求了宏榕。

那么其他服務(wù)再來(lái)調(diào)用訂單服務(wù)時(shí)拓诸,發(fā)訂單服務(wù)無(wú)響應(yīng)侵佃,這樣就導(dǎo)致訂單服務(wù)也不可用了。然后其他依賴訂單服務(wù)的服務(wù)奠支,也最終會(huì)導(dǎo)致不可用馋辈。 這就是微服務(wù)架構(gòu)中的服務(wù)雪崩。

[圖片上傳失敗...(image-599796-1611122749671)]

就上圖所示倍谜,如果多個(gè)服務(wù)之間相互調(diào)用迈螟,而不做任何保護(hù)措施的話,那么一個(gè)服務(wù)掛了尔崔,就會(huì)產(chǎn)生連鎖反應(yīng)答毫,導(dǎo)致其他服務(wù)也掛了。

其實(shí)就算是積分服務(wù)掛了季春,也并不應(yīng)該導(dǎo)致訂單服務(wù)也掛了洗搂,積分服務(wù)掛了,我們可以跳過(guò)積分服務(wù),或者是放一個(gè)默認(rèn)值耘拇,然后繼續(xù)往下走撵颊,等著積分服務(wù)恢復(fù)了,可以手動(dòng)恢復(fù)一下數(shù)據(jù)惫叛。

那么Spring Cloud Hystrix就是解決這個(gè)問(wèn)題的組件倡勇,他主要是起到熔斷,隔離嘉涌,降級(jí)的作用妻熊。

Spring Cloud Hystrix其實(shí)是會(huì)為每一個(gè)服務(wù)開(kāi)辟一個(gè)線程池,然后每個(gè)線程池中的線程用于對(duì)服務(wù)的調(diào)用請(qǐng)求仑最。這樣就算是積分服務(wù)掛了固耘,那也只是調(diào)用積分服務(wù)的線程池出現(xiàn)問(wèn)題了,而其他服務(wù)的線程池還正常工作词身。 這就是服務(wù)的隔離厅目。

這樣訂單服務(wù)在的調(diào)用積分服務(wù)的時(shí)候,如果發(fā)現(xiàn)有問(wèn)題了法严,積分服務(wù)可以通過(guò) Hystrix返回一個(gè)默認(rèn)值(默認(rèn)是5秒內(nèi)20次調(diào)用失敗就熔斷) 损敷。這樣訂單服務(wù)就不用在這里卡住了,可以繼續(xù)往下調(diào)用其他服務(wù)進(jìn)行業(yè)務(wù)操作了深啤。 這就是服務(wù)的熔斷拗馒。

雖然說(shuō)是積分服務(wù)掛了,并且也返回了默認(rèn)值了溯街,但是后續(xù)如果積分服務(wù)恢復(fù)了诱桂,想恢復(fù)數(shù)據(jù)怎么辦呢?這個(gè)時(shí)候積分服務(wù)可以將姐收到的請(qǐng)求記錄下來(lái)呈昔,或者是打到日志中挥等,能為后面恢復(fù)數(shù)據(jù)提供依據(jù)就行。 這就是服務(wù)的降級(jí) 堤尾。

整個(gè)過(guò)程大致如下圖所示:

image

API網(wǎng)關(guān)服務(wù)Spring Cloud Zuul

通過(guò)上面幾個(gè)組件的結(jié)合使用肝劲,已經(jīng)能夠完成一個(gè)基本的微服務(wù)架構(gòu)了。但是當(dāng)一個(gè)系統(tǒng)中微服務(wù)的數(shù)量逐漸增多時(shí)郭宝,一些通用的邏輯辞槐,例如:權(quán)限校驗(yàn)機(jī)制,請(qǐng)求過(guò)濾粘室,請(qǐng)求路由榄檬,限流等等,這些每個(gè)服務(wù)對(duì)外提供能力的時(shí)候都要考慮到的邏輯衔统,就會(huì)變得冗余鹿榜。

這個(gè)時(shí)候API網(wǎng)關(guān)的概念應(yīng)運(yùn)而生先朦,它類似于面向?qū)ο笤O(shè)計(jì)模式中的Facade模式(門面模式/外觀模式),所有的外部客戶端訪問(wèn)都需要經(jīng)過(guò)它來(lái)進(jìn)行調(diào)度和過(guò)濾犬缨。主要實(shí)現(xiàn)請(qǐng)求路由喳魏、負(fù)載均衡、校驗(yàn)過(guò)濾怀薛、服務(wù)限流等功能刺彩。

Spring Cloud Zuul就是Spring Cloud提供的API網(wǎng)關(guān)組件,它 通過(guò)與Eureka進(jìn)行整合枝恋,將自身注冊(cè)為Eureka下的應(yīng)用创倔,從Eureka下獲取所有服務(wù)的實(shí)例,來(lái)進(jìn)行服務(wù)的路由焚碌。

Zuul還提供了一套過(guò)濾器機(jī)制畦攘,開(kāi)發(fā)者可以自己指定哪些規(guī)則的請(qǐng)求需要執(zhí)行校驗(yàn)邏輯,只有通過(guò)校驗(yàn)邏輯的請(qǐng)求才會(huì)被路由到具體服務(wù)實(shí)例上十电,否則返回錯(cuò)誤提示知押。

image

Spring Cloud Zuul的依賴包 spring-cloud-starter-zuul 本身就包含了對(duì)s pring-cloud-starter-hystrixspring-cloud-starter-ribbon 模塊的依賴,所以Zuul天生就擁有線程隔離和斷路器的自我保護(hù)功能鹃骂,以及對(duì)服務(wù)調(diào)用的客戶端負(fù)載功能台盯。

Zuul的路由實(shí)現(xiàn)是通過(guò)Path和serviceId還實(shí)現(xiàn)的,path是一個(gè)http請(qǐng)求去除ip和端口號(hào)后的方法路徑畏线,例如: http://192.168.20.12:9001/api-zuul/123 静盅,那么path就是 /api-zuul/123 ,Zuul在配置時(shí)支持模糊匹配寝殴,若123是動(dòng)態(tài)參數(shù)蒿叠,可以將path配置成 /pai-zuul/** ,serviceId就是服務(wù)在Eureka中注冊(cè)的服務(wù)名稱蚣常。

zuul.routes.api-zuul.path= /api-zuul/**
zuul.routes.api-zuul.serviceId= service-jimoer

有了統(tǒng)一的網(wǎng)關(guān)后市咽,再做統(tǒng)一的鑒權(quán)、限流史隆、認(rèn)證授權(quán)魂务、安全等方面的工作就會(huì)變的更加方便了。

總結(jié)

上面總結(jié)了Spring Cloud的幾個(gè)核心組件泌射,其實(shí)Spring Cloud 除了這幾個(gè)組件還有一些其他的組件,例如:

  • 分布式配置中心Spring Cloud Config 鬓照;
  • 消息總線Spring Cloud Bus 熔酷;
  • 消息驅(qū)動(dòng)Spring Cloud Stream
  • 分布式服務(wù)跟蹤Spring Cloud Sleuth 豺裆。

主要是后面這些組件我們平時(shí)用的不多拒秘,而且對(duì)于微服務(wù)來(lái)說(shuō)有些是有替代品的号显,所以我暫時(shí)就沒(méi)有總結(jié)。還有一點(diǎn)畢竟我這次總結(jié)是為了解決面試的問(wèn)題躺酒,所以后面如果在實(shí)際的工作中用到了剩下的這些組件押蚤,我會(huì)繼續(xù)總結(jié)的。

好了羹应,總結(jié)一下這次的幾個(gè)組件的內(nèi)容吧揽碘。

  • Spring Cloud Eureka 各個(gè)微服務(wù)在啟動(dòng)時(shí)將自己注冊(cè)到Eureka Server中,并且各個(gè)服務(wù)中的Eureka Client又能從注冊(cè)中心獲取各個(gè)服務(wù)的實(shí)例地址清單园匹。
  • Spring Cloud Ribbon 各個(gè)服務(wù)相互調(diào)用的時(shí)候雳刺,通過(guò)Ribbon來(lái)進(jìn)行客戶端的負(fù)載均衡,從多個(gè)實(shí)例中根據(jù)一定的策略選擇一臺(tái)進(jìn)行請(qǐng)求裸违。
  • Spring Cloud Feign 基于動(dòng)態(tài)代理機(jī)制掖桦,根據(jù)注解和參數(shù)拼接URL,選擇具體的服務(wù)實(shí)例發(fā)起請(qǐng)求供汛,簡(jiǎn)化了服務(wù)間相互調(diào)用的開(kāi)發(fā)工作枪汪。
  • Spring Cloud Hystrix 調(diào)用每個(gè)服務(wù)的時(shí)候都是通過(guò)線程池中的線程來(lái)發(fā)起的,不同的服務(wù)走不同的線程池怔昨,實(shí)現(xiàn)了服務(wù)的隔離料饥,而且服務(wù)不可用時(shí)還提供了熔斷機(jī)制以及支持降低措施。
  • Spring Cloud Zuul 外部請(qǐng)求統(tǒng)一通過(guò)Zuul網(wǎng)關(guān)來(lái)進(jìn)入朱监,支持自定義路由規(guī)則岸啡,自定義過(guò)濾規(guī)則,可以實(shí)現(xiàn)同一的鑒權(quán)赫编、限流巡蘸、認(rèn)證等功能。

最后來(lái)一個(gè)整體的架構(gòu)圖擂送,將各個(gè)組件串起來(lái)悦荒。

image

``

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市嘹吨,隨后出現(xiàn)的幾起案子搬味,更是在濱河造成了極大的恐慌,老刑警劉巖蟀拷,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碰纬,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡问芬,警方通過(guò)查閱死者的電腦和手機(jī)悦析,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)此衅,“玉大人强戴,你說(shuō)我怎么就攤上這事亭螟。” “怎么了骑歹?”我有些...
    開(kāi)封第一講書人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵预烙,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我道媚,道長(zhǎng)扁掸,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任衰琐,我火速辦了婚禮也糊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘羡宙。我一直安慰自己狸剃,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布狗热。 她就那樣靜靜地躺著钞馁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪匿刮。 梳的紋絲不亂的頭發(fā)上僧凰,一...
    開(kāi)封第一講書人閱讀 51,190評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音熟丸,去河邊找鬼训措。 笑死,一個(gè)胖子當(dāng)著我的面吹牛光羞,可吹牛的內(nèi)容都是我干的绩鸣。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼纱兑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼呀闻!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起潜慎,我...
    開(kāi)封第一講書人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤捡多,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后铐炫,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體垒手,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年驳遵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了淫奔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡堤结,死狀恐怖唆迁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情竞穷,我是刑警寧澤唐责,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站瘾带,受9級(jí)特大地震影響鼠哥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜看政,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一朴恳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧允蚣,春花似錦于颖、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至冒晰,卻和暖如春同衣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背壶运。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工耐齐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蒋情。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓埠况,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親恕出。 傳聞我的和親對(duì)象是個(gè)殘疾皇子询枚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

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