lagou 爪哇 2-1 tomcat / nginx 筆記

Tomcat 系統(tǒng)架構(gòu)與原理剖析

注意:瀏覽器訪問服務(wù)器使?的是Http協(xié)議巡揍,Http是應(yīng)?層協(xié)議官紫,?于定義數(shù)據(jù)通信的格式老充,具體的數(shù)據(jù)傳輸使?的是TCP/IP協(xié)議

Tomcat 系統(tǒng)總體架構(gòu)
Tomcat是?個Http服務(wù)器(能夠接收并且處理http請求胞谈,所以tomcat是?個http服務(wù)器)我們使?瀏覽器向某?個?站發(fā)起請求薇宠,發(fā)出的是Http請求,那么在遠(yuǎn)程统舀,Http服務(wù)器接收到這個請求之后匆骗,會調(diào)?具體的程序(Java類)進(jìn)?處理,往往不同的請求由不同的Java類完成處理誉简。

Tomcat 設(shè)計了兩個核?組件連接器(Connector)和容器(Container)來完成 Tomcat 的兩?核?功能绰筛。

連接器,負(fù)責(zé)對外交流: 處理Socket連接描融,負(fù)責(zé)?絡(luò)字節(jié)流與Request和Response對象的轉(zhuǎn)化铝噩;

容器,負(fù)責(zé)內(nèi)部處理:加載和管理Servlet,以及具體處理Request請求骏庸;

Tomcat 連接器組件 Coyote

Coyote 簡介
Coyote 是Tomcat 中連接器的組件名稱 , 是對外的接?毛甲。客戶端通過Coyote與服務(wù)器建?連接具被、發(fā)送請
求并接受響應(yīng) 玻募。
(1)Coyote 封裝了底層的?絡(luò)通信(Socket 請求及響應(yīng)處理)
(2)Coyote 使Catalina 容器(容器組件)與具體的請求協(xié)議及IO操作?式完全解耦
(3)Coyote 將Socket 輸?轉(zhuǎn)換封裝為 Request 對象,進(jìn)?步封裝后交由Catalina 容器進(jìn)?處理一姿,處
理請求完成后, Catalina 通過Coyote 提供的Response 對象將結(jié)果寫?輸出流
(4)Coyote 負(fù)責(zé)的是具體協(xié)議(應(yīng)?層)和IO(傳輸層)相關(guān)內(nèi)容

在 8.0 之前 七咧,Tomcat 默認(rèn)采?的I/O?式為 BIO,之后改為 NIO叮叹。 ?論 NIO艾栋、NIO2 還是 APR, 在性能??均優(yōu)于以往的BIO蛉顽。 如果采?APR蝗砾, 甚?可以達(dá)到 Apache HTTP Server 的影響性能。

Tomcat 服務(wù)器核?配置詳解

?寫實現(xiàn)迷你版 Tomcat

Tomcat 源碼構(gòu)建及核?流程源碼剖析

Tomcat 類加載機(jī)制剖析

Tomcat 對 Https 的?持及 Tomcat 性能優(yōu)化策略

nginx 相關(guān)

Nginx基礎(chǔ)回顧(Nginx是什么携冤?能做什么事情(應(yīng)?在什么場合)悼粮?常?命令是什么?)

正向代理
在瀏覽器中配置代理服務(wù)器的相關(guān)信息曾棕,通過代理服務(wù)器訪問?標(biāo)?站扣猫,代理服務(wù)器收
到?標(biāo)?站的響應(yīng)之后,會把響應(yīng)信息返回給我們??的瀏覽器客戶端

反向代理
瀏覽器客戶端發(fā)送請求到反向代理服務(wù)器(?如 Nginx)翘地,由反向代理服務(wù)器選擇原始
服務(wù)器提供服務(wù)獲取結(jié)果響應(yīng)苞笨,最終再返回給客戶端瀏覽器

負(fù)載均衡服務(wù)器
負(fù)載均衡,當(dāng)?個請求到來的時候(結(jié)合上圖)子眶,Nginx反向代理服務(wù)器根據(jù)請求去找到?個原始服務(wù)器來處理當(dāng)前請求,那么這叫做反向代理序芦。那么臭杰,如果?標(biāo)服務(wù)器有多臺(?如上圖中的tomcat1,tomcat2谚中,tomcat3...)渴杆,找哪?個?標(biāo)服務(wù)器來處理當(dāng)前請求呢,這樣?個尋找確定的過程就叫做負(fù)載均衡宪塔。
?活中也有很多這樣的例?磁奖,?如,我們?nèi)ャy?某筐,可以處理業(yè)務(wù)的窗?有多個比搭,那么我們會被分配到哪個窗?呢到底,這樣的?個過程就叫做負(fù)載均衡南誊。

Nginx 核?配置?件解讀
Nginx的核?配置?件 conf/nginx.conf 包含三塊內(nèi)容:全局塊身诺、events塊蜜托、http塊

全局塊
從配置?件開始到 events 塊之間的內(nèi)容,此處的配置影響nginx服務(wù)器整體的運?霉赡,?如worker進(jìn)
程的數(shù)量橄务、錯誤?志的位置等

event 模塊
events塊主要影響 nginx 服務(wù)器與?戶的?絡(luò)連接,?如 worker_connections 1024穴亏,標(biāo)識每個 workderprocess ?持的最?連接數(shù)為1024

http 模塊
http塊是配置最頻繁的部分济丘,虛擬主機(jī)的配置硼被,監(jiān)聽端?的配置,請求轉(zhuǎn)發(fā)、反向代理吉执、負(fù)載均衡等

Nginx應(yīng)?場景之反向代理

再部署?臺tomcat,保持默認(rèn)監(jiān)聽8081端?
修改nginx配置三痰,并重新加載

這?主要就是多l(xiāng)ocation的使?腰懂,這?的nginx中server/location就好?tomcat中的
Host/Context location 語法如下:

在nginx配置?件中,location主要有這?種形式(優(yōu)先級由高到低):

  1. 精確匹配 location = /lagou { }
  2. 匹配路徑的前綴 location ^~ /lagou { }
  3. 不區(qū)分??寫的正則匹配 location ~* /lagou { }
  4. 正則匹配 location ~ /lagou { }
  5. 普通路徑前綴匹配 location /lagou { }

Nginx應(yīng)?場景之負(fù)載均衡
第一步是定義 upstream, 起一個名字. 然后再使用 proxy_pass 即可.

Nginx負(fù)載均衡策略:

  1. 輪詢
    默認(rèn)策略隅津,每個請求按時間順序逐?分配到不同的服務(wù)器诬垂,如果某?個服務(wù)器下線,能?動剔除
location /abc {
 proxy_pass http://myServer/;
}

upstream myServer{
 server 111.229.248.243:8080;
 server 111.229.248.243:8082;
}
  1. 權(quán)重 weight
    weight代表權(quán)重伦仍,默認(rèn)每?個負(fù)載的服務(wù)器都為1结窘,權(quán)重越?那么被分配的請求越多(?于服務(wù)器性能不均衡的場景)
upstream myServer{
 server 111.229.248.243:8080 weight=1;
 server 111.229.248.243:8082 weight=2;
}
  1. ip_hash
    每個請求按照ip的hash結(jié)果分配,每?個客戶端的請求會固定分配到同?個?標(biāo)服務(wù)器處理充蓝,可以解決session問題
    第五部分 Nginx應(yīng)?場景之動靜分離
upstream myServer{
 ip_hash;
 server 111.229.248.243:8080;
 server 111.229.248.243:8082;
}

Nginx 應(yīng)?場景之動靜分離
動靜分離就是講動態(tài)資源和靜態(tài)資源的請求處理分配到不同的服務(wù)器上隧枫,?較經(jīng)典的組合就是
Nginx+Tomcat架構(gòu)(Nginx處理靜態(tài)資源請求,Tomcat處理動態(tài)資源請求)

Nginx 底層進(jìn)程機(jī)制剖析
Nginx啟動后谓苟,以daemon多進(jìn)程?式在后臺運?官脓,包括?個Master進(jìn)程和多個Worker進(jìn)程,Master 進(jìn)程是領(lǐng)導(dǎo)涝焙,是??卑笨,Worker進(jìn)程是?活的?弟。

master進(jìn)程
主要是管理worker進(jìn)程仑撞,?如:
接收外界信號向各worker進(jìn)程發(fā)送信號(./nginx -s reload)
監(jiān)控worker進(jìn)程的運?狀態(tài)赤兴,當(dāng)worker進(jìn)程異常退出后Master進(jìn)程會?動重新啟動新的worker進(jìn)程等

worker進(jìn)程
worker進(jìn)程具體處理?絡(luò)請求。多個worker進(jìn)程之間是對等的隧哮,他們同等競爭來?客戶端的請求桶良,各進(jìn)程互相之間是獨?的。?個請求沮翔,只可能在?個worker進(jìn)程中處理陨帆,?個worker進(jìn)程,不可能處理其它進(jìn)程的請求。worker進(jìn)程的個數(shù)是可以設(shè)置的歧譬,?般設(shè)置與機(jī)器cpu核數(shù)?致岸浑。

Nginx進(jìn)程模型示意圖如下


以 ./nginx -s reload 來說明nginx信號處理這部分
1)master進(jìn)程對配置?件進(jìn)?語法檢查
2)嘗試配置(?如修改了監(jiān)聽端?,那就嘗試分配新的監(jiān)聽端?)
3)嘗試成功則使?新的配置瑰步,新建worker進(jìn)程
4)新建成功矢洲,給舊的worker進(jìn)程發(fā)送關(guān)閉消息
5)舊的worker進(jìn)程收到信號會繼續(xù)服務(wù),直到把當(dāng)前進(jìn)程接收到的請求處理完畢后關(guān)閉
所以reload之后worker進(jìn)程pid是發(fā)?了變化的

worker進(jìn)程處理請求部分的說明
例如缩焦,我們監(jiān)聽9003端?读虏,?個請求到來時,如果有多個worker進(jìn)程袁滥,那么每個worker進(jìn)程都有可能處理這個鏈接盖桥。
master進(jìn)程創(chuàng)建之后,會建?好需要監(jiān)聽的的socket题翻,然后從master進(jìn)程再fork出多個worker進(jìn)程揩徊。所以,所有worker進(jìn)程的監(jiān)聽描述符listenfd在新連接到來時都變得可讀嵌赠。
nginx使?互斥鎖來保證只有?個workder進(jìn)程能夠處理請求塑荒,拿到互斥鎖的那個進(jìn)程注冊 listenfd 讀事件,在讀事件?調(diào)?accept接受該連接姜挺,然后解析齿税、處理、返回客戶端

nginx多進(jìn)程模型好處
每個worker進(jìn)程都是獨?的炊豪,不需要加鎖凌箕,節(jié)省開銷
每個worker進(jìn)程都是獨?的,互不影響词渤,?個異常結(jié)束牵舱,其他的照樣能提供服務(wù)
多進(jìn)程模型為reload熱部署機(jī)制提供了?撐

其他

URL 編碼和解碼問題
http://www.ruanyifeng.com/blog/2010/02/url_encoding.html

作業(yè)

作業(yè)?(編程題):

開發(fā)Minicat V4.0,在已有Minicat基礎(chǔ)上進(jìn)?步擴(kuò)展缺虐,模擬出webapps部署效果 磁盤上放置?個webapps?錄芜壁,webapps中可以有多個項?,?如demo1,demo2,demo3... 具體的項??如demo1中有serlvet(也即為:servlet是屬于具體某?個項?的servlet)志笼,這樣的話在 Minicat初始化配置加載,以及根據(jù)請求url查找對應(yīng)serlvet時都需要進(jìn)?步處理

0崖āH依!!重要

備注讀取項目磁盤統(tǒng)一路徑: ****appBase="/Users/webapps"韧掩,并且提交自己的webapps以及訪問路徑****

作業(yè)?(簡答題): 請詳細(xì)描述Tomcat體系結(jié)構(gòu)(圖?并茂)

作業(yè)具體要求參考以下鏈接文檔:
https://gitee.com/lagouedu/alltestfile/raw/master/tomcat/Tomcat%E4%BD%9C%E4%B8%9A%E5%A4%A7%E9%A2%98.pdf

作業(yè)資料說明:

1紊浩、提供資料:工程代碼和自己的webapps以及訪問路徑、功能演示和原理講解視頻,簡答題資料坊谁。
2费彼、講解內(nèi)容包含:題目分析、實現(xiàn)思路口芍、代碼講解箍铲。
3、效果視頻驗證:實現(xiàn)模擬tomcat多項目部署效果鬓椭,訪問多個項目獲得動態(tài)返回的內(nèi)容颠猴。

  1. 增加server.xml配置?件,server.xml保持基本結(jié)構(gòu)即可小染,如下
<?xml version="1.0" encoding="utf-8" ?>
<Server>
    <services>
        <!--監(jiān)聽端口號-->
        <Connector port="80"/>
        <Engine>
            <!--appBase 為部署目錄-->
            <Host name="localhost" appBase="C:/Users/hp/Desktop/第二階段模塊1/第二階段模塊1/code/myWebapps" />
        </Engine>
    </services>
</Server>
  1. 制作 demo1 和 demo2 目錄
    demo1/
index.html
edu/lagou/server/LagouServlet01.class
edu/lagou/server/LagouServlet02.class
web.xml

demo2/

index.html
edu/lagou/server/LagouServlet03.class
web.xml
  1. 在 Bootstrap 類中添加 loadAppBase 方法翘瓮,可得到 port 和 appBase的值.

簡易的 Mapper 類

public class Mapper {

    /**
     * 一級目錄 以及 對應(yīng)的動態(tài)資源
     */
    private Map<String, Map<String, HttpServlet>> content2Wrapper = new HashMap<>();

    /**
     * 一級目錄 以及 對應(yīng)的相對路徑
     */
    private Map<String, String> resourcesMap = new HashMap<>();

    public void putStaticResources(String key, String value) {
        resourcesMap.put("/" + key, value);
    }

    public void putServletMap(String key, Map<String, HttpServlet> value) {
        content2Wrapper.put("/" + key, value);
    }

    public Map<String, HttpServlet> getServletMap(String key) {
        return content2Wrapper.get(key);
    }

    public String getStaticPath(String key) {
        return resourcesMap.get(key);
    }
}

自定義的 ClassLoader 類: 用于加載特定目錄的 class

public class MyClassLoader extends ClassLoader {


    public MyClassLoader(String basePath) {
        this.basePath = basePath;
    }

    /**
     * @description 解析類文件獲得當(dāng)前解析后的類
     * @param fullClassName 檔期類的完全限定名, 例如 edu.lagou.server.my.Person
     * @return 使用類加載器后獲取的類
     * @throws Exception 解析錯誤
     */
    public Class<?> transClassFile(String fullClassName) throws Exception {
        byte[] classBytes = this.loadBinaryClassFile(fullClassName);
        //主要通過父類來解析當(dāng)前的class二進(jìn)制文件
        return super.defineClass(fullClassName, classBytes, 0, classBytes.length);
    }

    /**
     * @description 讀取并加載類文件獲得byte數(shù)組返回
     * @return byte[] 數(shù)組
     * @throws Exception 讀取失敗
     */
    private byte[] loadBinaryClassFile(String packageName) throws Exception {
        String relativePath = packageName.replaceAll("\\.", "/");
        String classFilePath = this.basePath + "/" +relativePath + ".class";// 設(shè)置當(dāng)前class文件的路徑
        File classFile = new File(classFilePath);
        if (!classFile.exists()) {
            throw new FileNotFoundException(classFile.getAbsolutePath() + "文件不存在裤翩。资盅。。踊赠。呵扛。。臼疫。择份。。烫堤。");
        }
        InputStream fis = null;
        ByteArrayOutputStream bos = null;// 內(nèi)存流
        byte[] bytes = new byte[(int) classFile.length()]; // 設(shè)置緩沖區(qū)

        byte[] readBytes = null;
        try {
            bos = new ByteArrayOutputStream();
            // 開始實例化流荣赶,并加載流
            fis = new FileInputStream(classFile);// 這里必須為文件的實際路徑
            while (( fis.read(bytes)) != -1) {
                bos.write(bytes);
            }
            readBytes = bos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                fis.close();
            }
            if (bos != null) {
                bos.close();
            }
        }
        return readBytes;
    }

    private final String basePath;
}

創(chuàng)建 loadServerXML 方法,將 server.xml 加載到內(nèi)存

private void loadServerXML() {
        InputStream inputStream = Bootstrap.class.getClassLoader().getResourceAsStream("server.xml");
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(inputStream);
            Element rootElement = document.getRootElement();
            Node portNode = rootElement.selectSingleNode("/Server/services/Connector/@port");
            this.port = Integer.parseInt(portNode.getStringValue());
            System.out.println("配置 port = " + this.port);

            Node appBaseNode = rootElement.selectSingleNode("/Server/services/Engine/Host/@appBase");
            this.appBase = appBaseNode.getStringValue();
            System.out.println("配置 appBase = " + this.appBase);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

加載 appBase 目錄下各項目 以及 對應(yīng)的 url-pattern和HttpServlet 動態(tài)資源 和 靜態(tài)資源

    private void loadAppBaseServlet() {
        File file = new File(this.appBase);
        for (File f : Objects.requireNonNull(file.listFiles())) {
            if (f.isDirectory()) {
                // 解析 web.xml 并加載對應(yīng)的 HttpServlet 類
                String webXmlFileName = f.getAbsolutePath() + "/" + "web.xml";
                File webXmlFile = new File(webXmlFileName);
                // 如果連 web.xml 不存在 則跳過該目錄鸽斟。
                if (webXmlFile.exists()) {
                    String fileName = f.getName();
                    System.out.println(fileName);
                    System.out.println("--------------");
                    System.out.println("...加載該目錄" + f.getPath());
                    System.out.println(webXmlFileName);
                    // 加載對應(yīng)的 各項目父路徑 和 對應(yīng)的 url-patten與servlet動態(tài)資源的對應(yīng)關(guān)系, 例如 /demo1 -> (/lagou -> LagouServlet對象)
                    try {
                        InputStream inputStream = new FileInputStream(webXmlFile);
                        Map<String, HttpServlet> stringHttpServletMap = this.loadServletFromInputStream(inputStream,
                                new MyClassLoader(f.getAbsolutePath()));
                        this.mapper.putServletMap(fileName, stringHttpServletMap);

                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                    // 加載對應(yīng)的 各項目父路徑 和 對應(yīng)靜態(tài)資源父目錄的對應(yīng)關(guān)系, 例如 /demo1 -> appBase/demo1
                    this.mapper.putStaticResources(fileName, f.getAbsolutePath());
                } else {
                    System.out.println("...跳過該目錄" + f.getPath());
                }
            }
        }
    }

RequestProcessor 的 run 方法

// url
            String url = request.getUrl();
            // 截取兩端/index.html    / + index.html
            // /demo1/lagou
            String[] split = url.split("/");
            String part1;
            String part2;
            if (split.length == 2) {
                part1 = "/" + split[0];
                part2 = "/" + split[1];
            } else {
                part1 = "/" + split[1];
                part2 = "/" + split[2];
            }
            Map<String, HttpServlet> stringHttpServletMap = this.mapper.getServletMap(part1);
            if (stringHttpServletMap != null) {
                HttpServlet httpServlet = stringHttpServletMap.get(part2);
                // process static resources
                if (null == httpServlet) {
                    String filePath = this.mapper.getStaticPath(part1);
                    response.outputHtml(filePath, part2);
                } else {
                    httpServlet.service(request, response);
                }
            } else {
                // 404
                response.outputHtml("NOT FOUND");
            }

思路:Mapper類—>Host->Context->Wrapper->Servlet

開始測試

正面案例
http://localhost/index.html
http://localhost/lagou

http://localhost/demo1/index.html
http://localhost/demo1/lagou001
http://localhost/demo1/lagou002

http://localhost/demo2/index.html
http://localhost/demo2/lagou333

反面案例
http://localhost/demo1/abc.html
http://localhost/demo2/lagou003

其中遇到的問題

StaticResourceUtil#getAbsolutePath
如果包含特殊字符拔创,需要進(jìn)行一次 URL 解碼工作

        String resourcePath = StaticResourceUtil.class.getResource("/").getPath();
        System.out.println(resourcePath);
        // 如果包含特殊字符,需要進(jìn)行一次 URL 解碼工作
        try {
            resourcePath = java.net.URLDecoder.decode(resourcePath, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

作業(yè)2 解答

Tomcat 連接器組件 Coyote
Coyote 是Tomcat 中連接器的組件名稱 , 是對外的接?富蓄∈T铮客戶端通過Coyote與服務(wù)器建?連接、發(fā)送請
求并接受響應(yīng) 立倍。
(1)Coyote 封裝了底層的?絡(luò)通信(Socket 請求及響應(yīng)處理)
(2)Coyote 使Catalina 容器(容器組件)與具體的請求協(xié)議及IO操作?式完全解耦
(3)Coyote 將Socket 輸?轉(zhuǎn)換封裝為 Request 對象灭红,進(jìn)?步封裝后交由Catalina 容器進(jìn)?處理,處
理請求完成后, Catalina 通過Coyote 提供的Response 對象將結(jié)果寫?輸出流
Coyote 負(fù)責(zé)的是具體協(xié)議(應(yīng)?層)和IO

即一個由 Server->Service->Engine->Host->Context 組成的結(jié)構(gòu)口注,從里層向外層分別是:
?Server:服務(wù)器Tomcat的頂級元素变擒,它包含了所有東西。
?Service:一組 Engine(引擎) 的集合寝志,包括線程池 Executor 和連接器 Connector 的定義娇斑。
?Engine(引擎):一個 Engine代表一個完整的 Servlet 引擎策添,它接收來自Connector的請求,并決定傳給哪個Host來處理毫缆。
?Container(容器):Host唯竹、Context、Engine和Wraper都繼承自Container接口苦丁,它們都是容器浸颓。
?Connector(連接器):將Service和Container連接起來,注冊到一個Service芬骄,把來自客戶端的請求轉(zhuǎn)發(fā)到Container猾愿。
?Host:即虛擬主機(jī),所謂的”一個虛擬主機(jī)”可簡單理解為”一個網(wǎng)站”账阻。
?Context(上下文 ): 即 Web 應(yīng)用程序蒂秘,一個 Context 即對于一個 Web 應(yīng)用程序。Context容器直接管理Servlet的運行淘太,Servlet會被其給包裝成一個StandardWrapper類去運行姻僧。
?Wrapper負(fù)責(zé)管理一個Servlet的裝載、初始化蒲牧、執(zhí)行以及資源回收撇贺,它是最底層容器。

Container包含以下結(jié)構(gòu)
?Engine
表示整個Catalina的Servlet引擎冰抢,?來管理多個虛擬站點松嘶,?個Service最多只能有?個Engine, 但是?個引擎可包含多個Host
?Host
代表?個虛擬主機(jī)挎扰,或者說?個站點翠订,可以給Tomcat配置多個虛擬主機(jī)地址,??個虛擬主機(jī)下可 包含多個Context
?Context
表示?個Web應(yīng)?程序遵倦, ?個Web應(yīng)?可包含多個Wrapper
?Wrapper
表示?個Servlet尽超,Wrapper

具體請求流程
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市梧躺,隨后出現(xiàn)的幾起案子似谁,更是在濱河造成了極大的恐慌,老刑警劉巖掠哥,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件巩踏,死亡現(xiàn)場離奇詭異,居然都是意外死亡续搀,警方通過查閱死者的電腦和手機(jī)塞琼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來目代,“玉大人屈梁,你說我怎么就攤上這事¢涣耍” “怎么了在讶?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長霜大。 經(jīng)常有香客問我构哺,道長,這世上最難降的妖魔是什么战坤? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任曙强,我火速辦了婚禮,結(jié)果婚禮上途茫,老公的妹妹穿的比我還像新娘碟嘴。我一直安慰自己,他們只是感情好囊卜,可當(dāng)我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布娜扇。 她就那樣靜靜地躺著,像睡著了一般栅组。 火紅的嫁衣襯著肌膚如雪雀瓢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天玉掸,我揣著相機(jī)與錄音刃麸,去河邊找鬼。 笑死司浪,一個胖子當(dāng)著我的面吹牛泊业,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播断傲,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼脱吱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了认罩?” 一聲冷哼從身側(cè)響起箱蝠,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎垦垂,沒想到半個月后宦搬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡劫拗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年间校,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片页慷。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡憔足,死狀恐怖胁附,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情滓彰,我是刑警寧澤控妻,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站揭绑,受9級特大地震影響弓候,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜他匪,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一菇存、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧邦蜜,春花似錦依鸥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至井辆,卻和暖如春关筒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背杯缺。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工蒸播, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人萍肆。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓袍榆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親塘揣。 傳聞我的和親對象是個殘疾皇子包雀,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,037評論 2 355