SpringBoot-18 創(chuàng)建基于Dubbo框架的SpringBoot微服務(wù)

Dubbo 是原阿里巴巴 B2B 平臺(tái)技術(shù)部傾力打造的一款開源且優(yōu)秀的面向 Java 平臺(tái)的服務(wù)框架,歷經(jīng)三次大的迭代筛严,從最早盲從 OSGi 的坑里跳出來茄袖,再到序列化協(xié)議和通信框架的定型,最終才完善和成型,可以說摘刑,國內(nèi)開源服務(wù)化框架中無出其右者。

但是刻坊,Dubbo 研發(fā)的年代處于 Spring 框架的 XSD 時(shí)代枷恕,所以,使用上還是會(huì)更多以 XML 形式定義服務(wù)和訪問服務(wù)谭胚,但好在 SpringBoot 框架在 IoC 容器的配置方式上“不挑食”徐块,所以,我們還是可以讓 Dubbo 和 SpringBoot 框架友好相處灾而。

直接使用 Dubbo 開發(fā)微服務(wù)了胡控,為什么還要用 SpringBoot?旁趟,這是一個(gè)很好的問題昼激。

使用 SpringBoot 開發(fā)基于 Dubbo 框架的微服務(wù)的原因就是,我們將 Dubbo 微服務(wù)以 SpringBoot 形式標(biāo)準(zhǔn)化了锡搜。如此一來橙困,我們既可以享受 SpringBoot 框架和周邊的一系列研發(fā)支持,還可以用統(tǒng)一的形式發(fā)布耕餐、部署和運(yùn)維凡傅。

微服務(wù)的一個(gè)特點(diǎn)就是數(shù)量多,一個(gè)人應(yīng)對(duì) 1000 個(gè)相同操作接口的微服務(wù)和一個(gè)人應(yīng)對(duì) 1000 個(gè)不同操作接口的微服務(wù)相比來說肠缔,相信你會(huì)選擇前者夏跷。

2015 年到 2016年哼转,美元升值預(yù)期持續(xù)升溫,大家想必對(duì)匯率也比較關(guān)注拓春,所以释簿,我們不妨實(shí)現(xiàn)一個(gè)基于央行匯率的查詢服務(wù)。

1. 定義匯率查詢服務(wù)接口

我們新建 Maven 工程 currency-rates-api:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.keevol.springboot</groupId>
    <artifactId>currency-rates-api</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>currency-rates-api</name>
    <url>http://maven.apache.org</url>
    <properties>
        <java_source_version>1.8</java_source_version>
        <java_target_version>1.8</java_target_version>
        <file_encoding>UTF-8</file_encoding>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java_source_version}</source>
                    <target>${java_target_version}</target>
                    <encoding>${file_encoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <configuration>
                    <charset>${file_encoding}</charset>
                    <encoding>${file_encoding}</encoding>
                    <additionalparam>-Xdoclint:none</additionalparam>
                </configuration>
                <executions>
                    <execution>
                        <id>attach-javadocs</id>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project> 

然后定義匯率查詢服務(wù)接口:

public interface CurrencyRateService {
    ExchangeRate quote(CurrencyPair currencyPair) throws IOException;
} 

之后通過 mvn install 或者 mvn deploy 將 currency-rates-api 發(fā)布到本地或者遠(yuǎn)程 maven 倉庫硼莽。

2. 實(shí)現(xiàn)匯率查詢服務(wù)

新建 Maven 工程 currency-rates-service:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.keevol.springboot</groupId>
    <artifactId>currency-rates-service</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>currency-rates-service</name>
    <url>http://maven.apache.org</url>
    <properties>
        <java_source_version>1.8</java_source_version>
        <java_target_version>1.8</java_target_version>
        <file_encoding>UTF-8</file_encoding>
        <spring_version>4.1.6.RELEASE</spring_version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.keevol.springboot</groupId>
            <artifactId>currency-rates-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.3</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring_version}</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring_version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring_version}</version>
        </dependency>
    </dependencies>
</project> 

主要關(guān)注針對(duì) currency-rates-api 以及 Dubbo 框架的依賴定義。

項(xiàng)目創(chuàng)建完成后煮纵,我們著手實(shí)現(xiàn)服務(wù)接口:

public class CurrencyRateServiceImpl implements CurrencyRateService {
    private CurrencyRateRepository rateRepository;
    public ExchangeRate quote(CurrencyPair currencyPair) throws IOException {
        return rateRepository.get(currencyPair);
    }
    public CurrencyRateRepository getRateRepository() {
        return rateRepository;
    }
    public void setRateRepository(CurrencyRateRepository rateRepository) {
        this.rateRepository = rateRepository;
    }
}

其中懂鸵,CurrencyRateRepository 可以根據(jù)情況給出相應(yīng)的實(shí)現(xiàn),比如通過直接對(duì)接銀行的系統(tǒng)獲取匯率或者通過爬取官網(wǎng)數(shù)據(jù)獲得數(shù)據(jù)都可以行疏,這里不做過多解釋匆光。

服務(wù)實(shí)現(xiàn)之后,我們需要通過 Dubbo 框架暴露出去給外部使用酿联,所以终息,我們通過 Dubbo 的服務(wù)描述文件(即標(biāo)準(zhǔn)的 Spring 框架 XML 形式的配置文件)完成最終服務(wù)的對(duì)外開放:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:c="http://www.springframework.org/schema/c"
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd
        http://code.alibabatech.com/schema/dubbo
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <dubbo:application name="${dubbo.application.name}"
        owner="${dubbo.application.owner}" />
    <dubbo:protocol
        name="${dubbo.application.protocol.name}"
        port="${dubbo.application.protocol.port}" />
    <dubbo:service
        interface="com.keevol.springboot.services.currency.rates.CurrencyRateService"
        ref="serviceImpl" registry="N/A" />
    <bean id="serviceImpl"
        class="com.keevol.springboot.services.currency.rates.CurrencyRateServiceImpl" />
</beans>

因?yàn)橹皇窃褪纠哉耆茫覀儧]有定義更加嚴(yán)謹(jǐn)?shù)姆?wù)注冊(cè)方式(registry="N/A")周崭,生產(chǎn)環(huán)境下,大家還是需要選擇合適的注冊(cè)服務(wù)喳张,比如 Zookeeper续镇。

使用 Dubbo 框架的服務(wù)不依賴傳統(tǒng) J2EE 的容器對(duì)外提供服務(wù),而是以獨(dú)立進(jìn)程的形式對(duì)外服務(wù)销部,所以摸航,我們還需要提供一個(gè) Bootstrap 類用于啟動(dòng)我們的 Dubbo 服務(wù):

public class Bootstrap {
    public static void main(String[] args) throws IOException {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring/services.xml");
        ((AbstractApplicationContext) context).registerShutdownHook();
        System.in.read();
    }
}

至此,一個(gè)獨(dú)立部署運(yùn)行的 Dubbo 服務(wù)宣告完成舅桩。

3. 沒有 SpringBoot 什么事兒

不管是否使用 SpringBoot酱虎,基于 Dubbo 框架的服務(wù)從其服務(wù)的定義,到服務(wù)的實(shí)現(xiàn)擂涛,都是常規(guī)而無法省略的工作读串,但是:

  • 服務(wù)完成后,啟動(dòng) main 函數(shù)里的邏輯貌似每次都要編寫一樣的歼指?
  • 服務(wù)完成后爹土,以什么樣的形式發(fā)布并部署?zip 包踩身,還是 jar 包胀茵,亦或 war 包,甚至其他形式挟阻?

考慮到這些琼娘,就會(huì)涉及 SpringBoot旁赊,一旦將 Dubbo 服務(wù)以 SpringBoot 的形式封裝,Dubbo 服務(wù)就可以既享受 SpringBoot 的開發(fā)便捷性昨稼,又能以統(tǒng)一的形式發(fā)布和部署(比如可執(zhí)行的 jar 形式)侣诺。

雖然我們無法省略和簡化服務(wù)的定義和實(shí)現(xiàn)這些步驟,但 Dubbo 服務(wù)的 main 函數(shù)邏輯實(shí)際上是可以固化下來并且復(fù)用的熄浓,否則情臭,每個(gè)人給出的 Dubbo 服務(wù)實(shí)現(xiàn)的啟動(dòng)類都可能不一樣,進(jìn)而導(dǎo)致運(yùn)維操作不一樣赌蔑。

在上面我們給出的 main 函數(shù)實(shí)現(xiàn)中俯在,為了阻止 Dubbo 服務(wù)的進(jìn)程退出(主線程執(zhí)行完畢,無其他非 daemon 線程存活)娃惯。

我們使用了 IO 操作來達(dá)成這一目的(System.in.read())跷乐,但實(shí)際上,這不是一個(gè)很好的做法趾浅。更好的做法是愕提,我們?cè)O(shè)置一個(gè)服務(wù)是否關(guān)閉的開關(guān),只有當(dāng)外部調(diào)用相應(yīng)管理接口將服務(wù)關(guān)閉之后皿哨,再關(guān)閉當(dāng)前的 Dubbo 服務(wù)浅侨,所以,基于此思路往史,我們可以實(shí)現(xiàn)一個(gè) ShutdownLatch:

public interface ShutdownLatchMBean {
    String shutdown();
}
public class ShutdownLatch implements ShutdownLatchMBean {
    protected AtomicBoolean running = new AtomicBoolean(false);
    public long checkIntervalInSeconds = 10;
    private String domain = "com.wacai.lifecycles";
    public ShutdownLatch() {
    }
    public ShutdownLatch(String domain) {
        this.domain = domain;
    }
    public void await() throws Exception {
        if (running.compareAndSet(false, true)) {
            MBeanServer mBeanServer = ManagementFactory.get - PlatformMBeanServer();
            mBeanServer.registerMBean(this, new ObjectName(domain, "name", "ShutdownLatch"));
            while (running.get()) {
                TimeUnit.SECONDS.sleep(checkIntervalInSeconds);
            }
        }
    }
    @Override
    public String shutdown() {
        if (running.compareAndSet(true, false)) {
            return "shutdown signal sent, shutting down..";
        } else {
            return "shutdown signal had been sent, no need again and again and again...";
        }
    }
    public static void main(String[] args) throws Exception {
        ShutdownLatch latch = new ShutdownLatch("your_domain_for_mbeans");
        latch.await();
    }
}

ShutdownLatch 默認(rèn)以 JMX 的 MBean 暴露為管理接口仗颈,所以,Dubbo 服務(wù)的 main 函數(shù)可以規(guī)范為:

ApplicationContext context = new ClassPathXmlApplicationContext("spring/services.xml");
((AbstractApplicationContext) context).registerShutdownHook();
ShutdownLatch latch = new ShutdownLatch("your_domain_for_mbeans");
latch.await();

為了簡化基于 SpringBoot 的 Dubbo 服務(wù)開發(fā)椎例,我們可以將針對(duì) Dubbo 框架的依賴以及對(duì)服務(wù)啟動(dòng)類的規(guī)范封裝為一個(gè) spring-boot-starter-dubbo 這樣的自動(dòng)配置模塊挨决,此后,要開發(fā)一個(gè)基于 SpringBoot 的 Dubbo 服務(wù)订歪,只要依賴這一自動(dòng)配置模塊即可脖祈。

所以,我們新建 Maven 項(xiàng)目 spring-boot-starter-dubbo:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.keevol.springboot</groupId>
    <artifactId>spring-boot-starter-dubbo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>spring-boot-starter-dubbo</name>
    <description>Demo project for Spring Boot</description>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.1.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <properties>
        <java_source_version>1.8</java_source_version>
        <java_target_version>1.8</java_target_version>
        <file_encoding>UTF-8</file_encoding>
        <spring_version>4.1.6.RELEASE</spring_version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.3</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

項(xiàng)目的 pom.xml 中刷晋,我們可以重點(diǎn)關(guān)注針對(duì) spring-boot-starter 和 Dubbo 框架的依賴盖高。

所有的 SpringBoot 應(yīng)用啟動(dòng)都是基于標(biāo)準(zhǔn)的 SpringApplication.run 完成的,為了在啟動(dòng)類執(zhí)行完成后可以阻止 Dubbo 服務(wù)進(jìn)程的推出眼虱,我們需要在 SpringBoot 啟動(dòng)類的 main 函數(shù)最后調(diào)用 ShutdownLatch.await()喻奥。

但是如果要求每個(gè)開發(fā)者在自己的 SpringBoot 啟動(dòng)類中調(diào)用這段代碼,顯然這并沒有給開發(fā)者的工作帶來任何簡化捏悬,所以撞蚕,我們選擇使用 CommandLineRunner 來完成針對(duì) ShutdownLatch.await() 的調(diào)用工作。

教程前面已經(jīng)介紹過 CommandLineRunner过牙,任何注冊(cè)到 SpringBoot 應(yīng)用的 CommandLineRunner 都將在 SpringApplication.run 執(zhí)行完成后再執(zhí)行甥厦,恰好符合我們當(dāng)前場(chǎng)景需要纺铭,代碼如下所示:

public class DubboServiceLatchCommandLineRunner implements CommandLineRunner {
    private String domain = "com.keevol.services.management";
    @Override
    public void run(String... args) throws Exception {
        ShutdownLatch latch = new ShutdownLatch(getDomain());
        latch.await();
    }
    public String getDomain() {
        return domain;
    }
    public void setDomain(String domain) {
        this.domain = domain;
    }
}

然后我們需要將 DubboServiceLatchCommandLineRunner 注冊(cè)到 SpringBoot 應(yīng)用的容器之中,所以刀疙,定義一個(gè) JavaConfig 類如下:

@Configuration
@Order
public class DubboAutoConfiguration {
    protected Logger logger = LoggerFactory.getLogger(DubboAutoConf - iguration.class);
    @Value("${shutdown.latch.domain.name: com.keevol.services.management}")
    private String shutdownLatchDomainName;
    @Bean
    @ConditionalOnClass(name = "com.alibaba.dubbo.rpc.Exporter")
    public DubboServiceLatchCommandLineRunner configureDubboService-LatchCommandLineRunner() {
        logger.debug("DubboAutoConfiguration enabled by adding Dubbo-ServiceLatchCommandLineRunner.");
        DubboServiceLatchCommandLineRunner runner = new DubboServi-ceLatchCommandLineRunner();
        runner.setDomain(shutdownLatchDomainName);
        return runner;
    }
}

我們使用 @Order 標(biāo)注了該配置類以保證 DubboServiceLatchCommandLineRunner 在最后執(zhí)行舶赔,以避免阻塞其他邏輯的執(zhí)行。

萬里長征走到了最后一步谦秧,要實(shí)現(xiàn)一個(gè) SpringBoot 的自動(dòng)配置模塊竟纳,我們需要將 DubboAutoConfiguration 配置類通過 META-INF/spring.factories 配置文件注冊(cè)并發(fā)布:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.keevol.springboot.dubbo.autoconfigure.DubboAutoConfiguration 

至此,我們只要通過 mvn install 或者 mvn deploy 將 spring-boot-starter-dubbo 發(fā)布到本地或者遠(yuǎn)程 Maven 倉庫油够,以后開發(fā) Dubbo 服務(wù)就只需要在服務(wù)的項(xiàng)目依賴中添加如下依賴:

<dependency>
    <groupId>com.keevol.springboot</groupId>
    <artifactId>spring-boot-starter-dubbo</artifactId>
    <version>1.0.0</version>
</dependency>

然后以標(biāo)準(zhǔn)的 SpringApplication 加載 Dubbo 服務(wù)的配置并啟動(dòng)就可以了:

@SpringBootApplication
public class DubboWithSpringbootApplication {
    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(Dubb - oWithSpringbootApplication.class,
                "classpath*:/spring/**/*.xml");
        application.run(args);
    }
}

當(dāng)然蚁袭,規(guī)范 Dubbo 依賴以及服務(wù)的啟動(dòng)邏輯只是使用 SpringBoot 獲得的好處之一,最主要的石咬,我們提供了一種基于 SpringBoot 的標(biāo)準(zhǔn)化的 Dubbo 服務(wù)開發(fā)和發(fā)布實(shí)踐,這對(duì)于海量微服務(wù)的開發(fā)和運(yùn)維來說是很重要的卖哎。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鬼悠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子亏娜,更是在濱河造成了極大的恐慌焕窝,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件维贺,死亡現(xiàn)場(chǎng)離奇詭異它掂,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)溯泣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門虐秋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人垃沦,你說我怎么就攤上這事客给。” “怎么了肢簿?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵靶剑,是天一觀的道長。 經(jīng)常有香客問我池充,道長桩引,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任收夸,我火速辦了婚禮坑匠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘咱圆。我一直安慰自己笛辟,他們只是感情好功氨,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著手幢,像睡著了一般捷凄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上围来,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天跺涤,我揣著相機(jī)與錄音,去河邊找鬼监透。 笑死桶错,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的胀蛮。 我是一名探鬼主播院刁,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼粪狼!你這毒婦竟也來了退腥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤再榄,失蹤者是張志新(化名)和其女友劉穎狡刘,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體困鸥,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嗅蔬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了疾就。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片澜术。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖虐译,靈堂內(nèi)的尸體忽然破棺而出瘪板,到底是詐尸還是另有隱情,我是刑警寧澤漆诽,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布侮攀,位于F島的核電站,受9級(jí)特大地震影響厢拭,放射性物質(zhì)發(fā)生泄漏兰英。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一供鸠、第九天 我趴在偏房一處隱蔽的房頂上張望畦贸。 院中可真熱鬧,春花似錦、人聲如沸薄坏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽胶坠。三九已至君账,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沈善,已是汗流浹背乡数。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留闻牡,地道東北人净赴。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像罩润,于是被迫代替她去往敵國和親玖翅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

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