分布式服務開發(4) Dubbo + Zookeeper

dubbo是一個分布式服務框架,是阿里巴巴SOA服務化治理方案的核心框架。zookeeper是一個為分布式應用提供一致性服務的軟件,提供的功能包括:配置維護、域名服務、分布式同步、組服務等。zookeeper可以作為dubbo服務的注冊中心,兩者結合起來可以實現微服務中的 服務注冊、發現、負載均衡和健康檢查,容錯,動態配置管理的功能。我們先用springMVC將dubbo服務暴露成瀏覽器可訪問的http接口。

本例代碼已經上傳到GitHub,傳送門見下:
https://github.com/ArchitectRoad/BoliERP.git

重要的事情說前面。先總結Dubbo+Spring Boot使用過程中的要點、注意點吧。

  • Spring Boot的目的之一就是使開發人員可以擺脫繁雜的xml配置,所以Spring Boot整合Dubbo時,使用Annotation是推薦方式。使用Annotation集成Spring Boot + Dubbo時可以參照 https://github.com/JeffLi1993/springboot-learning-example
  • 為便于更好理解Dubbo的原理,在本例中仍然使用xml進行Dobbo provider和consumer的配置。Spring Boot + Dubbo聯合使用時,需要顯示在入口類中通過以下方式引用dubbo配置。
@ImportResource(classpath: dubbo-consumer.xml)
public class ProdWebApplication {
    ...
}
  • Service Provider打包為Jar,使用com.alibaba.dubbo.container.Main作為入口啟動Spring容器時,默認讀取classpath:META-INF/spring/目錄下的applicationContext.xml。關于如何生成Service Provider Jar,詳見prodService模塊的pom.xml中的build節點定義。
  • 解決Dubbo與Spring Boot的依賴包沖突,引入dubbo時exclude spring。
           <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>dubbo</artifactId>
                <version>${dubbo-version}</version>
                <exclusions>
                    <exclusion>
                        <artifactId>spring</artifactId>
                        <groupId>org.springframework</groupId>
                    </exclusion>
                </exclusions>
            </dependency>
  • 解決log4j與slf4j的版本沖突。Exclude zookeeper中的slf4j與log4j,exclude zkclient中的log4j。
           <dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
                <version>${zookeeper-version}</version>
                <!-- Solve conflict with Spring boot -->
                <exclusions>
                    <exclusion>
                        <groupId>org.slf4j</groupId>
                        <artifactId>slf4j-log4j12</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>org.slf4j</groupId>
                        <artifactId>slf4j-api</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>log4j</groupId>
                        <artifactId>log4j</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>com.github.sgroschupf</groupId>
                <artifactId>zkclient</artifactId>
                <version>${zkclient-version}</version>
                <exclusions>
                    <exclusion>
                        <groupId>log4j</groupId>
                        <artifactId>log4j</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
  • classpath 和 classpath* 區別:
classpath: 只會到你的class路徑中查找找文件。只加載找到的第一個文件。
classpath*: 不僅包含class路徑,還包括jar文件中(class路徑)進行查找。從多個jar文件中加載相同的文件。
用classpath*:需要遍歷所有的classpath,所以加載速度較慢。因此,在規劃的時候,應該盡可能規劃好資源文件所在的路徑,盡量避免使用classpath*。
**/ 表示的是任意目錄。

項目結構如下:

prodParentPom工程目錄
  • pordParentPom module
    定義所有模塊的parent pom,統一管理依賴版本。繼承spring-boot-starter-parent,并定義dubbo, zookeeper, zkclient版本。通過exclusion解決jar包沖突。
pom.xml
<?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.boli</groupId>
    <artifactId>prodParentPom</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
    </parent>

    <modules>
        <module>../prodApi</module>
        <module>../prodService</module>
        <module>../prodWebApp</module>
    </modules>

    <properties>
        <dubbo-version>2.5.3</dubbo-version>
        <zookeeper-version>3.4.9</zookeeper-version>
        <zkclient-version>0.1</zkclient-version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- dubbo dependency -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>dubbo</artifactId>
                <version>${dubbo-version}</version>
                <exclusions>
                    <exclusion>
                        <artifactId>spring</artifactId>
                        <groupId>org.springframework</groupId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
                <version>${zookeeper-version}</version>
                <!-- Solve conflict with Spring boot -->
                <exclusions>
                    <exclusion>
                        <groupId>org.slf4j</groupId>
                        <artifactId>slf4j-log4j12</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>org.slf4j</groupId>
                        <artifactId>slf4j-api</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>log4j</groupId>
                        <artifactId>log4j</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>com.github.sgroschupf</groupId>
                <artifactId>zkclient</artifactId>
                <version>${zkclient-version}</version>
                <exclusions>
                    <exclusion>
                        <groupId>log4j</groupId>
                        <artifactId>log4j</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>
  • prodApi module
    Api接口定義,以及Dubbo consumer定義。prodService模塊具體實現Api接口。prodWebApp模塊引用該模塊,根據Api接口定義,通過zookeeper發現并調用具體服務。


    prodApi工程目錄
IProdSvc.java
/*
* Copyright (c) 2017 architectroad@yeah.net. All Rights Reserved.
*/
package com.boli.service.intfc.prod;

import java.util.List;

/**
 * Product Service Interface
 * Author: Joey Zhu (architectroad@yeah.net)
 * Date: 2017/3/11.
 * Time: 11:01
 */
public interface IProdSvc {
    public List<String> getProdList();

    public String sayHello (String name);
}

prodApi.consumer.xml
<?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: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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!-- 消費者應用信息,用于提供依賴關系 -->
    <dubbo:application name="prodSvcConsumer" />
    <!-- 注冊地址,用于消費者尋找服務,, 此處可以配置多個zookeeper -->
    <dubbo:registry protocol="zookeeper" address="127.0.0.1:2181" />
    <!-- 超時設置 -->
    <dubbo:consumer timeout="5000" />

    <!-- 引用的服務 -->
    <dubbo:reference id="prodService" interface="com.boli.service.intfc.prod.IProdSvc" version="1.0.0" />

</beans>
pom.xml
<?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">
    <parent>
        <artifactId>prodParentPom</artifactId>
        <groupId>com.boli</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.boli</groupId>
    <artifactId>prodApi</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
        </dependency>

        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
        </dependency>
    </dependencies>

</project>
  • prodService module
prodService工程目錄
ProdSvcProvider.java

Service Provider入口類

/*
* Copyright (c) 2017 architectroad@yeah.net. All Rights Reserved.
*/
package com.boli;

import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Service Provider Entry Class
 *
 * Author: Joey Zhu (architectroad@yeah.net)
 * Date: 2017/3/13.
 * Time: 13:58
 */
public class ProdSvcProvider {
    public static void main(String[] args) throws Exception {
        //本地啟動spring容器,適用于開發階段調試
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                new String[] {"META-INF/spring/applicationContext.xml"});
        context.start();
        System.out.println("啟動成功");
        System.in.read(); // 按任意鍵退出

        //內置Tomcat方式啟動
//        SpringApplication.run(ProdSvcImpl.class, args);

        //Dubbo spring容器方式啟動
//        com.alibaba.dubbo.container.Main.main(args);
    }
}

prodService.provider.xml
<?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: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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

       <!-- 提供方應用信息,用于計算依賴關系 -->
       <dubbo:application name="prodSvcProvider" />

       <!-- 使用multicast廣播注冊中心暴露服務地址 -->
       <!--<dubbo:registry address="multicast://224.5.6.7:1234" /> -->

       <!-- 使用zookeeper注冊中心暴露服務地址,即zookeeper的所在服務器ip地址和端口號 -->
       <!-- check: 注冊中心不存在時是否報錯, subscribe: 是否向此注冊中心訂閱服務, register: 是否向此注冊中心注冊服務 -->
       <dubbo:registry address="zookeeper://127.0.0.1:2181" check="false" subscribe="false" register="true"/>

       <!-- 用dubbo協議在20880端口暴露服務 -->
       <dubbo:protocol name="dubbo" port="20880" />

       <!-- 具體的實現bean -->
       <bean id="prodService" class="com.boli.service.impl.prod.ProdSvcImpl"/>
       <!-- 如果使用掃描包方式引入bean,使用如下方式 -->
       <!-- dubbo:annotation package="com.boli.service.impl.*" / -->

       <!-- 聲明需要暴露的服務接口 -->
       <dubbo:service interface="com.boli.service.intfc.prod.IProdSvc" ref="prodService" version="1.0.0"/>

       <!-- 使用注解方式暴露接口 -->
       <!--dubbo:annotation package="com.boli.service.impl" /-->

       <!-- 加入spring注解掃描 -->
       <!--context:component-scan base-package="com.boli.service.impl"/-->

</beans>
applicationContext.xml
<?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: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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
       <!-- import dubbo providers -->
       <import resource="classpath:dubbo/prodService.provider.xml"></import>

</beans>
pom.xml

通過mvn package命令打包生成prodService-1.0-SNAPSHOT.jar時,指定com.alibaba.dubbo.container.Main作為入口類,并拷貝所有的依賴包到lib目錄中。打包完成后,使用java -jar prodService-1.0-SNAPSHOT.jar 命令即可運行并注冊服務到指定的服務注冊中心,比如zookeeper。

<?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.boli</groupId>
    <artifactId>prodService</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <parent>
        <artifactId>prodParentPom</artifactId>
        <groupId>com.boli</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>com.boli</groupId>
            <artifactId>prodApi</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </dependency>
    </dependencies>

    <build>
        <resources>
            <resource>
                <!--生成的classes文件的路徑,此文件夾中包含運行時的所有文件,可以不配置-->
                <targetPath>${project.build.directory}/classes</targetPath>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
                <includes>
                    <include>**/*provider.xml</include>
                    <include>**/*.properties</include>
                </includes>
            </resource>
            <resource>
                <targetPath>${project.build.directory}/classes/META-INF/spring</targetPath>
                <directory>src/main/resources/META-INF/spring</directory>
                <filtering>true</filtering>
                <includes>
                    <include>applicationContext.xml</include>
                </includes>
            </resource>
        </resources>

        <!--下面的必須配置-->
        <plugins>
            <!-- 打包jar文件時,配置manifest文件,加入lib包的jar依賴 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <classesDirectory>target/classes/</classesDirectory>
                    <archive>
                        <manifest>
                            <mainClass>com.alibaba.dubbo.container.Main</mainClass>
                            <!-- 打包時 MANIFEST.MF文件不記錄時間戳版本 -->
                            <useUniqueVersions>false</useUniqueVersions>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                        </manifest>
                        <manifestEntries>
                            <Class-Path>.</Class-Path>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <type>jar</type>
                            <includeTypes>jar</includeTypes>
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
  • prodWebApp module
    Web Application。服務消費方。
prodWebApp
ProdController.java
/*
* Copyright (c) 2017 architectroad@yeah.net. All Rights Reserved.
*/
package com.boli.web;

import com.boli.service.intfc.prod.IProdSvc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

/**
 * Product Controller
 *
 * Author: Joey Zhu (architectroad@yeah.net)
 * Date: 2017/3/10.
 * Time: 18:46
 */
@Controller
public class ProdController {

    @Autowired
    IProdSvc prodService;

    @RequestMapping("/prodList")
    @ResponseBody
    private List<String> getProdList () {
        return prodService.getProdList();
    }
}


ProdWebApplication.java
/*
* Copyright (c) 2017 architectroad@yeah.net. All Rights Reserved.
*/
package com.boli;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportResource;

/**
 * Product Module Web Application
 * Author: Joey Zhu (architectroad@yeah.net)
 * Date: 2017/3/13.
 * Time: 12:16
 */

@EnableAutoConfiguration
@ImportResource({"classpath*:META-INF/spring/applicationContext.xml"})
@ComponentScan("com.boli.web")
public class ProdWebApplication {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(ProdWebApplication.class, args);
    }
}

applicationContext.xml
<?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: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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
       <!-- import dubbo consumers -->
       <import resource="classpath*:dubbo/*.consumer.xml"></import>
</beans>
pom.xml
<?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.boli</groupId>
    <artifactId>prodWebApp</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <parent>
        <artifactId>prodParentPom</artifactId>
        <groupId>com.boli</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>com.boli</groupId>
            <artifactId>prodApi</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

代碼已經上傳到GitHub,傳送門見下:
https://github.com/ArchitectRoad/BoliERP.git

本地測試步驟及測試結果:

  1. 先啟動ZooKeeper
joeys-MacBook-Pro:~ joey$ zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /Library/ZooKeeper/zookeeper-3.4.9/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
joeys-MacBook-Pro:~ joey$ 
  1. 啟動ProdSvcProvider


    啟動Provider

    從日志中可以看到服務注冊成功

INFO com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistry -  [DUBBO] Register: dubbo://192.168.0.109:20880/com.boli.service.intfc.prod.IProdSvc?anyhost=true&application=prodSvcProvider&dubbo=2.5.3&interface=com.boli.service.intfc.prod.IProdSvc&methods=sayHello,getProdList&pid=5836&revision=1.0.0&side=provider&timestamp=1490058278762&version=1.0.0, dubbo version: 2.5.3, current host: 127.0.0.1

3.啟動ProdWebApplication


啟動Consumer

從日志中可以看到服務訂閱成功

INFO 5872 --- [           main] c.a.d.r.zookeeper.ZookeeperRegistry      :  [DUBBO] Subscribe: consumer://192.168.0.109/com.boli.service.intfc.prod.IProdSvc?application=prodSvcConsumer&category=providers,configurators,routers&default.timeout=5000&dubbo=2.5.3&interface=com.boli.service.intfc.prod.IProdSvc&methods=sayHello,getProdList&pid=5872&revision=1.0.0&side=consumer&timestamp=1490058693542&version=1.0.0, dubbo version: 2.5.3, current host: 192.168.0.109

4.訪問應用
訪問本地接口,驗證web應用部署成功


測試本地接口

訪問遠程服務接口,驗證Dubbo遠程服務調用成功


訪問zk注冊服務
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內容