Dubbo介紹

筆者初識Dubbo的時候微服,只知道它是一個RPC框架,那么什么是RPC呢猾普?

1. RPC是什么

維基百科是這么定義RPC的:

在分布式計算皮获,遠(yuǎn)程過程調(diào)?(英語:Remote Procedure Call舞骆,縮寫為 RPC)是?個計算機(jī)通信協(xié) 議。該協(xié)議允許運?于?臺計算機(jī)的程序調(diào)?另?個地址空間(通常為?個開放?絡(luò)的?臺計算機(jī))的?程序糊饱,?程序員就像調(diào)?本地程序?樣垂寥,?需額外地為這個交互作?編程(?需關(guān)注細(xì)節(jié))。RPC是 ?種服務(wù)器-客戶端(Client/Server)模式,經(jīng)典實現(xiàn)是?個通過發(fā)送請求-接受回應(yīng)進(jìn)?信息交互的系統(tǒng)滞项。如果涉及的軟件采??向?qū)ο缶幊滔凉椋敲催h(yuǎn)程過程調(diào)?亦可稱作遠(yuǎn)程調(diào)?或遠(yuǎn)程?法調(diào)?,例:Java RMI文判。

所以對于Java程序而言过椎,RPC就是遠(yuǎn)程方法調(diào)用。

1.1 相對于本地方法調(diào)用

遠(yuǎn)程?法調(diào)?和本地?法調(diào)?是相對的兩個概念戏仓,本地?法調(diào)?指的是進(jìn)程內(nèi)部的?法調(diào)?疚宇,?遠(yuǎn)程?法調(diào)?指的是兩個進(jìn)程內(nèi)的?法相互調(diào)?。

1.2 基于網(wǎng)絡(luò)傳輸

從上述表述中可以看到赏殃,遠(yuǎn)程方法調(diào)用指的是兩個進(jìn)程內(nèi)的方法調(diào)用敷待,如果要實現(xiàn)遠(yuǎn)程方法調(diào)用,基本就是通過網(wǎng)絡(luò)傳輸數(shù)據(jù)進(jìn)行調(diào)用仁热。

所以就有了

  • RPC over Http:基于Http協(xié)議來傳輸數(shù)據(jù)
  • PRC over Tcp:基于Tcp協(xié)議來傳輸數(shù)據(jù)

1.3 傳輸數(shù)據(jù)

對于所傳輸?shù)臄?shù)據(jù)榜揖,可以交由RPC的雙?來協(xié)商定義,但基本都會包括:

  • 調(diào)?的是哪個類或接?
  • 調(diào)?的是哪個?法抗蠢,?法名和?法參數(shù)類型(考慮?法重載)
  • 調(diào)??法的?參

2. 什么是Dubbo

2.1 定義

?前举哟,官?上是這么介紹的:Apache Dubbo 是?款?性能、輕量級的開源 Java 服務(wù)框架迅矛。

在?個?前妨猩,官?的介紹是:Apache Dubbo 是?款?性能、輕量級的開源 Java RPC框架秽褒。

Dubbo?開始的定位就是RPC壶硅,專注于兩個服務(wù)之間的調(diào)?。但隨著微服務(wù)的盛?震嫉,除開服務(wù)調(diào)?之外森瘪, Dubbo也在逐步的涉獵服務(wù)治理牡属、服務(wù)監(jiān)控票堵、服務(wù)?關(guān)等等,所以現(xiàn)在的Dubbo?標(biāo)已經(jīng)不?是RPC框架了逮栅,?是和Spring Cloud類似想成為?個服務(wù)框架悴势。

2.2 基本組成

Dubbo有以下幾個模塊:注冊中心、服務(wù)提供者措伐、容器特纤、服務(wù)消費者和監(jiān)控中心組成。

架構(gòu)圖

2.2.1 注冊中心(Registry)

使用過SpringCloud或者Zookeeper的同學(xué)應(yīng)該有印象侥加,對于一個分布式服務(wù)捧存,最重要的組成之一就是注冊中心,它可以管理系統(tǒng)的整個服務(wù),包括服務(wù)發(fā)現(xiàn)與服務(wù)注冊昔穴。

2.2.2 服務(wù)提供者(Provider)

前面提到RPC框架需要在網(wǎng)絡(luò)傳輸數(shù)據(jù)镰官,這個數(shù)據(jù)在Java中可以表示為一個接口,而服務(wù)提供者的作用就是把這個接口提供出去吗货,并向注冊中心注冊自己泳唠,這樣才可以把服務(wù)暴露出去,供服務(wù)消費者調(diào)用宙搬。服務(wù)提供者和服務(wù)消費者雙方需要約定一個協(xié)議來處理服務(wù)消費者的請求笨腥。

2.2.3 容器(Container)

Dubbo的Container模塊,是一個獨立的容器勇垛,因為服務(wù)通常不需要Tomcat/JBoss等Web容器的特性脖母,沒必要用Web容器去加載服務(wù)。Dubbo內(nèi)置了jetty窥摄、spring來啟動服務(wù)镶奉,但是也提供了容器擴(kuò)展,用戶可以自定義容器啟動服務(wù)崭放,所以也可以使用Tomcat啟動服務(wù)哨苛,但是官方不推薦這么使用。

2.2.4 服務(wù)消費者(Consumer)

服務(wù)消費者需要向服務(wù)提供者發(fā)送請求币砂,來獲取最終數(shù)據(jù)建峭。

2.2.5 監(jiān)控中心

一個分布式服務(wù)要想穩(wěn)定運行,需要在全鏈路上監(jiān)控服務(wù)的運行狀態(tài)决摧,那種無監(jiān)控的服務(wù)實在是太可怕了亿蒸,筆者就遇到過無監(jiān)控的服務(wù),發(fā)現(xiàn)問題掌桩、排查問題的過程實在是太痛苦了边锁。

2.2.6 基本調(diào)用流程

  • 服務(wù)容器負(fù)責(zé)啟動,加載波岛,運行服務(wù)提供者茅坛。
  • 服務(wù)提供者在啟動時,向注冊中心注冊自己提供的服務(wù)则拷。
  • 服務(wù)消費者在啟動時贡蓖,向注冊中心訂閱自己所需的服務(wù)。
  • 注冊中心返回服務(wù)提供者地址列表給消費者煌茬,如果有變更斥铺,注冊中心將基于長連接推送變更數(shù)據(jù)給消費者。
  • 服務(wù)消費者坛善,從提供者地址列表中晾蜘,基于軟負(fù)載均衡算法邻眷,選一臺提供者進(jìn)行調(diào)用,如果調(diào)用失敗剔交,再選另一臺調(diào)用耗溜。
  • 服務(wù)消費者和提供者,在內(nèi)存中累計調(diào)用次數(shù)和調(diào)用時間省容,定時每分鐘發(fā)送一次統(tǒng)計數(shù)據(jù)到監(jiān)控中心抖拴。

3. 自己實現(xiàn)一個簡單的Dubbo

介紹了這么多,是時候展現(xiàn)真正的技術(shù)了腥椒,我們先自己實現(xiàn)一個簡單版本的Dubbo阿宅。

3.1 需求分析

首先進(jìn)行需求分析,我們設(shè)計一個框架笼蛛,希望框架有哪些模塊洒放、每個模塊的功能是什么,這里可以參考Dubbo的架構(gòu)來設(shè)計滨砍。

由于是簡易的版本往湿,我們只需要注冊中心、服務(wù)提供者惋戏、服務(wù)消費者以及容器這四個模塊领追。

3.2 模塊功能分析

3.2.1 注冊中心

  • 提供注冊服務(wù)功能
  • 提供獲取已注冊服務(wù)功能

3.2.2 服務(wù)提供者

  • 提供調(diào)用接口供服務(wù)消費者調(diào)用
  • 啟動時向注冊中心注冊服務(wù)

3.2.3 容器

  • 服務(wù)容器負(fù)責(zé)啟動,加載响逢,運行服務(wù)提供者

3.2.4 服務(wù)消費者

  • 啟動時向注冊中心訂閱服務(wù)
  • 調(diào)用服務(wù)提供者提供的接口绒窑,調(diào)用該接口

3.3 項目整體結(jié)構(gòu)

整個項目分三個包,consumer舔亭、provider以及framework些膨。

  • consumer:包含一個消費者啟動類Consumer
  • provider:包含提供的接口UserService、接口實現(xiàn)類UserServiceImpl以及提供方啟動類Provider
  • framework:包含protocol包钦铺、proxy包以及register包
    • protocol:協(xié)議層订雾,本次用Http協(xié)議,包含HttpClient(Http客戶端)矛洞、HttpServer(服務(wù))洼哎、HttpServerHandler(服務(wù)處理)、DispatcherServlet(轉(zhuǎn)發(fā))以及Invocation(傳輸實體)
    • proxy:包含一個代理工廠ProxyFactory
    • register:包含一個LocalRegister

3.4 調(diào)用流程

  • Provider類啟動缚甩,注冊本服務(wù)谱净,啟動容器
  • Consumer類啟動窑邦,通過動態(tài)代理擅威,調(diào)用暴露的接口
  • ProxyFactory通過HttpClient發(fā)送請求,調(diào)用服務(wù)提供方提供的接口
  • 服務(wù)提供方接到該接口請求冈钦,通過HttpServerHandler處理請求
  • HttpServerHandler解析請求參數(shù)郊丛,獲取傳輸實體Invocation
  • 通過傳輸實體中的參數(shù),用反射獲取UserServiceImpl的實例
  • 調(diào)用UserServiceImpl中的方法,獲得返回數(shù)據(jù)
  • 將返回數(shù)據(jù)寫到Response中厉熟,返回給服務(wù)消費者
  • 消費者接到返回數(shù)據(jù)导盅,呈現(xiàn)出來

3.5 具體實現(xiàn)

項目整體結(jié)構(gòu)

整體依賴文件

<?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>org.example</groupId>
    <artifactId>RPCDemo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.16.Final</version>
        </dependency>

        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>9.0.12</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.3.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.51</version>
        </dependency>


        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-client</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.13</version>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.13</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpmime</artifactId>
            <version>4.5.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.14</version>
        </dependency>
    </dependencies>

</project>

3.5.1 provider層

Provider類

package com.rpc.provider;

import com.rpc.framework.protocol.http.HttpServer;
import com.rpc.framework.register.LocalRegister;

public class Provider {

    public static void main(String[] args) {

        String interfaceName = UserService.class.getName();

        LocalRegister.register(interfaceName,UserServiceImpl.class);

        //啟動服務(wù)
        HttpServer httpServer = new HttpServer();
        httpServer.start("localhost",8080);
    }

}

接口UserService

package com.rpc.provider;

public interface UserService {

    String hello(String name);

}

實現(xiàn)類UserServiceImpl

package com.rpc.provider;

public class UserServiceImpl implements UserService {

    @Override
    public String hello(String name) {
        return "hello" + name;
    }
}

3.5.2 consumer層

Cousumer類

package com.rpc.consumer;

import com.rpc.framework.proxy.ProxyFactory;
import com.rpc.provider.UserService;

public class Consumer {

    public static void main(String[] args) {

        UserService userService = ProxyFactory.gerProxy(UserService.class);
        String result = userService.hello("PRC");
        System.out.println(result);

    }

}

3.5.3 framework層

3.5.3.1 protocol層

http層里的四個類

package com.rpc.framework.protocol.http;

import lombok.SneakyThrows;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class DispatcherServlet extends HttpServlet {

    @SneakyThrows
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        new HttpServerHandler().handler(req,resp);
    }
}
package com.rpc.framework.protocol.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.rpc.framework.protocol.Invocation;
import org.apache.http.HttpEntity;
import org.apache.http.ParseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

public class HttpClient {

    public static SSLContext createSSL() {
        try {
            return new SSLContextBuilder().loadTrustMaterial(null, (certificate, authType) -> true).build();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 構(gòu)建httpclient客戶端,設(shè)置SSL證書揍瑟,并設(shè)置請求失敗的重試次數(shù)
     */
    private static final CloseableHttpClient httpclient = HttpClients
            .custom().setSSLContext(createSSL())
            .setRetryHandler(new HttpRequestRetryHandler() {
                @Override
                public boolean retryRequest(IOException e, int retryCount, HttpContext httpContext) {
                    if (retryCount <= 3) {
                        return true;
                    }
                    return false;
                }
            }).build();

    /**
     * 發(fā)送HttpPost請求白翻,參數(shù)為map
     *
     * @param url
     * @param invocation
     * @return
     */
    public static String sendPost(String url, Invocation invocation) {

        String jsonString = JSON.toJSONString(invocation);

        StringEntity entity = new StringEntity(jsonString, Charset.forName("UTF-8"));
        /*entity.setContentEncoding("UTF-8");
        entity.setContentType("application/json;charset=UTF-8");*/

        HttpPost httppost = new HttpPost(url);
        /*
            設(shè)置請求頭 請求體
         */
        httppost.setHeader("Content-Type", "application/json;charset=UTF-8");
        httppost.setHeader("Accept", "application/json");
        httppost.setEntity(entity);

        CloseableHttpResponse response = null;

        try {
            response = httpclient.execute(httppost);
        } catch (IOException e) {
            e.printStackTrace();
        }

        HttpEntity httpEntity = response.getEntity();
        String result = null;
        try {
            result = EntityUtils.toString(httpEntity);
        } catch (ParseException | IOException e) {
            e.printStackTrace();
        }
        return result;

    }


}
package com.rpc.framework.protocol.http;

import org.apache.catalina.*;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.startup.Tomcat;

/**
 * 封裝Tomcat啟動服務(wù)
 *
 */
public class HttpServer {

    public void start(String hostName, Integer port){
        Tomcat tomcat = new Tomcat();

        Server server = tomcat.getServer();
        Service service = server.findService("Tomcat");

        Connector connector = new Connector();
        connector.setPort(port);

        Engine engine = new StandardEngine();
        engine.setDefaultHost(hostName);

        Host host = new StandardHost();
        host.setName(hostName);

        String contextPath = "";
        Context context = new StandardContext();
        context.setPath(contextPath);
        context.addLifecycleListener(new Tomcat.FixContextListener());

        host.addChild(context);
        engine.addChild(host);

        service.setContainer(engine);
        service.addConnector(connector);

        tomcat.addServlet(contextPath,"dispatcher", new DispatcherServlet());
        context.addServletMappingDecoded("/*", "dispatcher");

        try {
            tomcat.start();
            tomcat.getServer().await();
        } catch (LifecycleException e) {
            e.printStackTrace();
        }

    }

}
package com.rpc.framework.protocol.http;

import com.alibaba.fastjson.JSONObject;
import com.rpc.framework.protocol.Invocation;
import com.rpc.framework.register.LocalRegister;
import com.rpc.provider.UserService;
import com.rpc.provider.UserServiceImpl;
import org.apache.commons.io.IOUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class HttpServerHandler {

    public void handler(HttpServletRequest req, HttpServletResponse resp) throws IOException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
        //處理請求
        Invocation invocation = JSONObject.parseObject(req.getInputStream(), Invocation.class);

        Class aClass = LocalRegister.get(invocation.getInterfaceName());

        try {
            Method method = aClass.getMethod(invocation.getMethodName(),invocation.getParamTypes());
            String result = (String) method.invoke(aClass.newInstance(), invocation.getParams());
            IOUtils.write(result,resp.getOutputStream());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

    }

}

傳輸實體類

package com.rpc.framework.protocol;

import java.io.Serializable;

public class Invocation implements Serializable {

    private String interfaceName;
    private String methodName;
    private Class[] paramTypes;
    private Object[] params;

    public Invocation(String interfaceName, String methodName, Class[] paramTypes, Object[] params) {
        this.interfaceName = interfaceName;
        this.methodName = methodName;
        this.paramTypes = paramTypes;
        this.params = params;
    }

    public String getInterfaceName() {
        return interfaceName;
    }

    public void setInterfaceName(String interfaceName) {
        this.interfaceName = interfaceName;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public Class[] getParamTypes() {
        return paramTypes;
    }

    public void setParamTypes(Class[] paramTypes) {
        this.paramTypes = paramTypes;
    }

    public Object[] getParams() {
        return params;
    }

    public void setParams(Object[] params) {
        this.params = params;
    }
}

3.5.3.2 proxy層

ProxyFactory類

package com.rpc.framework.proxy;

import com.rpc.framework.protocol.Invocation;
import com.rpc.framework.protocol.http.HttpClient;

import java.lang.reflect.Proxy;

public class ProxyFactory {

    public static <T> T gerProxy(final Class interfaceClass){
        return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass},
                (proxy, method, args) -> {
                    Invocation invocation = new Invocation(interfaceClass.getName(),
                                                           method.getName(),
                                                            method.getParameterTypes(),args);
                    //發(fā)送請求
                    String result = HttpClient.sendPost("http://localhost:8080", invocation);
                    return result;
                });
    }

}

3.5.3.3 register層

LocalRegister類

package com.rpc.framework.register;

import java.util.HashMap;
import java.util.Map;

public class LocalRegister {

    private static Map<String, Class> map = new HashMap<>();

    public static void register(String interfaceName, Class implClass){
        map.put(interfaceName, implClass);
    }

    public static Class get(String interfaceName){
        return map.get(interfaceName);
    }

}

3.6 驗證

啟動Provider類,再啟動Consumer類

輸出

helloPRC

大功告成>钇B蒜伞!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末底循,一起剝皮案震驚了整個濱河市巢株,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌熙涤,老刑警劉巖阁苞,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異祠挫,居然都是意外死亡那槽,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門等舔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來倦炒,“玉大人,你說我怎么就攤上這事软瞎》昊剑” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵涤浇,是天一觀的道長鳖藕。 經(jīng)常有香客問我,道長只锭,這世上最難降的妖魔是什么著恩? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮蜻展,結(jié)果婚禮上喉誊,老公的妹妹穿的比我還像新娘。我一直安慰自己纵顾,他們只是感情好伍茄,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著施逾,像睡著了一般敷矫。 火紅的嫁衣襯著肌膚如雪例获。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天曹仗,我揣著相機(jī)與錄音榨汤,去河邊找鬼。 笑死怎茫,一個胖子當(dāng)著我的面吹牛收壕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播轨蛤,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼啼器,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了俱萍?” 一聲冷哼從身側(cè)響起端壳,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎枪蘑,沒想到半個月后损谦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡岳颇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年照捡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片话侧。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡栗精,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瞻鹏,到底是詐尸還是另有隱情悲立,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布新博,位于F島的核電站薪夕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏赫悄。R本人自食惡果不足惜原献,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望埂淮。 院中可真熱鬧姑隅,春花似錦、人聲如沸倔撞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽误窖。三九已至叮盘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間霹俺,已是汗流浹背柔吼。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留丙唧,地道東北人愈魏。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像想际,于是被迫代替她去往敵國和親培漏。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

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

  • 一胡本、系統(tǒng)架構(gòu)演變首先說一下系統(tǒng)應(yīng)用的發(fā)展演化過程牌柄。也是我整個工作過程中經(jīng)歷的過程。1.單機(jī)應(yīng)用特點:當(dāng)網(wǎng)站流量很小...
    微子Lee閱讀 2,191評論 0 7
  • 一.介紹 官網(wǎng) 分布式服務(wù)架構(gòu) 當(dāng)垂直應(yīng)用越來越多侧甫,應(yīng)用之間交互不可避免珊佣,將核心業(yè)務(wù)抽取出來,作為獨立的服務(wù)披粟,逐漸...
    源來是你啊閱讀 294評論 0 0
  • 內(nèi)容簡介此篇文章是介紹Dubbo以及它的簡單使用咒锻,會列舉運用spring boot + dubbo搭建項目運用du...
    Little_Dragon_閱讀 837評論 0 3
  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友守屉。感恩相遇惑艇!感恩不離不棄。 中午開了第一次的黨會拇泛,身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,551評論 0 11
  • 彩排完滨巴,天已黑
    劉凱書法閱讀 4,187評論 1 3