You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by il...@apache.org on 2018/10/12 07:40:14 UTC

[incubator-dubbo-website] branch asf-site updated: add new blog 'how to use zipkin in dubbo'

This is an automated email from the ASF dual-hosted git repository.

iluo pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/incubator-dubbo-website.git


The following commit(s) were added to refs/heads/asf-site by this push:
     new a883745  add new blog 'how to use zipkin in dubbo'
a883745 is described below

commit a883745d33a497cd4cf7953a73b03a6a5b3e94e3
Author: beiwei30 <ia...@gmail.com>
AuthorDate: Fri Oct 12 15:39:34 2018 +0800

    add new blog 'how to use zipkin in dubbo'
---
 blog/zh-cn/use-zipkin-in-dubbo.md   | 604 ++++++++++++++++++++++++++++++++++++
 build/blog.js                       |   6 +-
 build/blogDetail.js                 |   6 +-
 build/community.js                  |   6 +-
 build/documentation.js              |   6 +-
 build/home.js                       |   6 +-
 img/blog/trace-sample.png           | Bin 0 -> 35537 bytes
 img/blog/zipkin-architecture.png    | Bin 0 -> 38500 bytes
 img/blog/zipkin-dubbo-project.png   | Bin 0 -> 147401 bytes
 img/blog/zipkin-span.png            | Bin 0 -> 363230 bytes
 img/blog/zipkin-trace.png           | Bin 0 -> 54776 bytes
 img/blog/zipkin-web-screenshot.png  | Bin 0 -> 356606 bytes
 site_config/blog.js                 |   7 +
 zh-cn/blog/index.html               |   2 +-
 zh-cn/blog/use-zipkin-in-dubbo.html | 538 ++++++++++++++++++++++++++++++++
 zh-cn/blog/use-zipkin-in-dubbo.json |   7 +
 16 files changed, 1172 insertions(+), 16 deletions(-)

diff --git a/blog/zh-cn/use-zipkin-in-dubbo.md b/blog/zh-cn/use-zipkin-in-dubbo.md
new file mode 100644
index 0000000..58b8acf
--- /dev/null
+++ b/blog/zh-cn/use-zipkin-in-dubbo.md
@@ -0,0 +1,604 @@
+---
+title: 在 Dubbo 中使用 Zipkin
+keywords: zipkin,dubbo,trace,span,dapper
+description: 如何在 Dubbo 中使用 Zipkin 进行全链路追踪
+---
+
+# 在 Dubbo 中使用 Zipkin
+
+随着业务的发展,应用的规模不断的扩大,传统的应用架构无法满足诉求,服务化架构改造势在必行,以 Dubbo 为代表的分布式服务框架成为了服务化改造架构中的基石。随着微服务理念逐渐被大众接受,应用进一步向更细粒度拆分,并且,不同的应用由不同的开发团队独立负责,整个分布式系统变得十分复杂。没有人能够清晰及时的知道当前系统整体的依赖关系。当出现问题时,也无法及时知道具体是链路上的哪个环节出了问题。
+
+在这个背景下,Google 发表了 [Dapper](https://ai.google/research/pubs/pub36356) 的论文,描述了如何通过一个分布式追踪系统解决上述问题。基于该论文,各大互联网公司实现并部署了自己的分布式追踪系统,其中比较出名的有阿里巴巴的 EagleEye。本文中提到的 Zipkin 是 Twitter 公司开源的分布式追踪系统。下面会详细介绍如何在 Dubbo 中使用 Zipkin 来实现分布式追踪。
+
+## Zipkin 简介
+
+Zipkin 是基于 [Dapper](https://ai.google/research/pubs/pub36356) 论文实现,由 Twitter 开源的分布式追踪系统,通过收集分布式服务执行时间的信息来达到追踪服务调用链路、以及分析服务执行延迟等目的。
+
+### Zipkin 架构
+
+![Zipkin architecture](../../img/blog/zipkin-architecture.png)
+
+Collector 收集器、Storage 存储、API、UI 用户界面等几部分构成了 Zipkin Server 部分,对应于 GitHub 上 [openzipkin/zipkin](https://github.com/openzipkin/zipkin) 这个项目。而收集应用中调用的耗时信息并将其上报的组件与应用共生,并拥有各个语言的实现版本,其中 Java 的实现是 GitHub 上 [openzipkin/brave](https://github.com/openzipkin/brave)。除了 Java 客户端实现之外,openzipkin 还提供了许多其他语言的实现,其中包括了 go、php、JavaScript、.net、ruby 等,具体列表可以参阅 Zipkin 的 [Exiting instrumentations](https://zipkin.io/pages/existing_instrumentations)。
+
+### Zipkin 的工作过程
+
+当用户发起一次调用时,Zipkin 的客户端会在入口处为整条调用链路生成一个全局唯一的 trace id,并为这条链路中的每一次分布式调用生成一个 span id。span 与 span 之间可以有父子嵌套关系,代表分布式调用中的上下游关系。span 和 span 之间可以是兄弟关系,代表当前调用下的两次子调用。一个 trace 由一组 span 组成,可以看成是由 trace 为根节点,span 为若干个子节点的一棵树。
+
+![Related image](../../img/blog/trace-sample.png)
+
+Span 由调用边界来分隔,在 Zipkin 中,调用边界由以下四个 annotation 来表示:
+
+* cs - Clent Sent 客户端发送了请求
+* sr - Server Receive 服务端接受到请求
+* ss - Server Send 服务端处理完毕,向客户端发送回应
+* cr - Client Receive 客户端收到结果
+
+显然,通过这四个 annotation 上的时间戳,可以轻易的知道一次完整的调用在不同阶段的耗时,比如:
+
+* sr - cs 代表了请求在网络上的耗时
+* ss - sr 代表了服务端处理请求的耗时
+* cr - ss 代表了回应在网络上的耗时
+* cr - cs 代表了一次调用的整体耗时
+
+Zipkin 会将 trace 相关的信息在调用链路上传递,并在每个调用边界结束时异步的把当前调用的耗时信息上报给 Zipkin Server。Zipkin Server 在收到 trace 信息后,将其存储起来,Zipkin 支持的存储类型有 inMemory、MySql、Cassandra、以及 ElasticsSearch 几种方式。随后 Zipkin 的 Web UI 会通过 API 访问的方式从存储中将 trace 信息提取出来分析并展示,如下图所示:
+
+![Web interface screenshot](../../img/blog/zipkin-web-screenshot.png)
+
+
+
+## 在 Dubbo 中使用
+
+由于 [Brave](https://github.com/openzipkin/brave) 对 Dubbo 已经主动做了支持,在 Dubbo 中集成基于 Zipkin 的链路追踪变的十分简单。下面会按照 Brave 中关于 [Dubbo RPC 支持的指引](https://github.com/openzipkin/brave/blob/master/instrumentation/dubbo-rpc/README.md)来说明如何在 Dubbo 中使用 Zipkin。
+
+### 安装 Zipkin Server
+
+按照 [Zipkin 官方文档中的快速开始](https://github.com/openzipkin/zipkin/tree/master/zipkin-server#quick-start) 来安装 Zipkin,如下所示:
+
+```bash
+$ curl -sSL https://zipkin.io/quickstart.sh | bash -s
+$ java -jar zipkin.jar
+```
+
+按照这种方式安装的 Zipkin Server 使用的存储类型是 inMemory 的。当服务器停机之后,所有收集到的 trace 信息会丢失,不适用于生产系统。如果在生产系统中使用,需要配置另外的存储类型。Zipkin 支持 MySql、Cassandra、和 ElasticSearch。推荐使用 Cassandra 和 ElasticSearch,相关的配置请自行查阅[官方文档](https://github.com/openzipkin/zipkin/tree/master/zipkin-server)。
+
+本文为了演示方便,使用的存储是 inMemory 类型。成功启动之后,可以在终端看到如下的提示:
+
+```bash
+$ java -jar zipkin.jar
+Picked up JAVA_TOOL_OPTIONS: -Djava.awt.headless=true
+                                    ********
+                                  **        **
+                                 *            *
+                                **            **
+                                **            **
+                                 **          **
+                                  **        **
+                                    ********
+                                      ****
+                                      ****
+        ****                          ****
+     ******                           ****                                 ***
+  ****************************************************************************
+    *******                           ****                                 ***
+        ****                          ****
+                                       **
+                                       **
+
+
+             *****      **     *****     ** **       **     **   **
+               **       **     **  *     ***         **     **** **
+              **        **     *****     ****        **     **  ***
+             ******     **     **        **  **      **     **   **
+
+:: Powered by Spring Boot ::         (v2.0.5.RELEASE)
+
+...
+
+o.s.b.w.e.u.UndertowServletWebServer     : Undertow started on port(s) 9411 (http) with context path ''
+2018-10-10 18:40:31.605  INFO 21072 --- [           main] z.s.ZipkinServer                         : Started ZipkinServer in 6.835 seconds (JVM running for 8.35)
+```
+
+然后在浏览器中访问 http://localhost:9411 验证 WEB 界面。
+
+### 配置 Maven 依赖
+
+#### 引入 Brave 依赖
+
+新建一个新的 Java 工程,并在 pom.xml 中引入 Brave 相关的依赖如下:
+
+```xml
+    <properties>
+        <brave.version>5.4.2</brave.version>
+        <zipkin-reporter.version>2.7.9</zipkin-reporter.version>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <!-- 引入 zipkin brave 的 BOM 文件 -->
+            <dependency>
+                <groupId>io.zipkin.brave</groupId>
+                <artifactId>brave-bom</artifactId>
+                <version>${brave.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+			
+            <!-- 引入 zipkin repoter 的 BOM 文件 -->
+            <dependency>
+                <groupId>io.zipkin.reporter2</groupId>
+                <artifactId>zipkin-reporter-bom</artifactId>
+                <version>${zipkin-reporter.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <!-- 1. brave 对 dubbo 的集成 -->
+        <dependency>
+            <groupId>io.zipkin.brave</groupId>
+            <artifactId>brave-instrumentation-dubbo-rpc</artifactId>
+        </dependency>
+
+        <!-- 2. brave 的 spring bean 支持 -->
+        <dependency>
+            <groupId>io.zipkin.brave</groupId>
+            <artifactId>brave-spring-beans</artifactId>
+        </dependency>
+
+        <!-- 3. 在 SLF4J 的 MDC (Mapped Diagnostic Context) 中支持 traceId 和 spanId -->
+        <dependency>
+            <groupId>io.zipkin.brave</groupId>
+            <artifactId>brave-context-slf4j</artifactId>
+        </dependency>
+
+        <!-- 4. 使用 okhttp3 作为 reporter -->
+        <dependency>
+            <groupId>io.zipkin.reporter2</groupId>
+            <artifactId>zipkin-sender-okhttp3</artifactId>
+        </dependency>
+    </dependencies>
+```
+
+其中:
+
+1. 引入 brave-instrumentation-dubbo-rpc,brave 对 dubbo 的支持:https://github.com/openzipkin/brave/blob/master/instrumentation/dubbo-rpc/README.md
+2. 引入 brave-spring-beans,brave 对 spring bean 的支持:https://github.com/openzipkin/brave/blob/master/spring-beans/README.md
+3. 引入 brave-context-slf4j,brave 对 SLF4J 的支持,可以在 MDC 中使用 traceId 和 spanId:https://github.com/openzipkin/brave/blob/master/context/slf4j/README.md
+4. 引入 zipkin-sender-okhttp3,使用 okhttp3 上报数据:https://github.com/openzipkin/zipkin-reporter-java
+
+#### 引入 Dubbo 相关依赖
+
+Dubbo 相关的依赖是 Dubbo 本身以及 Zookeeper 客户端,在下面的例子中,我们将会使用独立的 Zookeeper Server 作为服务发现。
+
+```xml
+    <dependencies>
+        <!-- 1. Zookeeper 客户端依赖 -->
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-framework</artifactId>
+            <version>2.12.0</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>io.netty</groupId>
+                    <artifactId>netty</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <!-- 2. Dubbo 依赖 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo</artifactId>
+            <version>2.6.2</version>
+        </dependency>
+    </dependencies>
+```
+
+其中:
+
+1. Dubbo 这里依赖独立的 Zookeeper Server 做服务发现,这里使用的客户端是 Curator
+2. 引入 Dubbo 框架的依赖,原则上 2.6 的任何版本都是工作的,这里使用的是 2.6.2 版本
+
+### 实现
+
+我们这里构造的场景是一个有两个节点的服务依赖链,也就是,当一个 Dubbo 客户端调用服务 A 时,服务 A 将会继续调用服务 B。在这个例子中,服务 A 是 greeting service,它所依赖的下游服务服务 B 是 hello service。
+
+#### 定义服务接口
+
+为此需要事先定义两个服务接口 GreetingService 以及 HelloService
+
+1. com.alibaba.dubbo.samples.api.GreetingService
+
+    ```java
+    package com.alibaba.dubbo.samples.api;
+
+    public interface GreetingService {
+        String greeting(String message);
+    }
+    ```
+
+2. com.alibaba.dubbo.samples.api.HelloService
+
+   ```java
+   package com.alibaba.dubbo.samples.api;
+   
+   public interface HelloService {
+       String hello(String message);
+   }
+   ```
+
+#### 实现服务接口
+
+为了区分对待,所有和 HelloService 相关的实现代码都放在 hello 子包下,同理 GreetingService 相关的放在 greeting 子包下。
+
+1. 实现 com.alibaba.dubbo.samples.api.HelloService
+
+    ```java
+    package com.alibaba.dubbo.samples.service.hello;
+
+    import com.alibaba.dubbo.samples.api.HelloService;
+
+    import java.util.Random;
+
+    public class HelloServiceImpl implements HelloService {
+        @Override
+        public String hello(String message) {
+            try {
+                // 通过 sleep 模拟业务逻辑处理时间
+                Thread.sleep(new Random(System.currentTimeMillis()).nextInt(1000));
+            } catch (InterruptedException e) {
+                // no op
+            }
+            return "hello, " + message;
+        }
+    }
+    ```
+
+2. 实现 com.alibaba.dubbo.samples.api.GreetingService
+
+   ```java
+   package com.alibaba.dubbo.samples.service.greeting;
+   
+   import com.alibaba.dubbo.samples.api.GreetingService;
+   import com.alibaba.dubbo.samples.api.HelloService;
+   
+   import java.util.Random;
+   
+   public class GreetingServiceImpl implements GreetingService {
+   	// 下游依赖服务,运行时靠 spring 容器注入 HelloService 的服务代理
+       private HelloService helloService;
+   
+       public void setHelloService(HelloService helloService) {
+           this.helloService = helloService;
+       }
+   
+       @Override
+       public String greeting(String message) {
+           try {
+               // 通过 sleep 模拟业务逻辑处理时间
+               Thread.sleep(new Random(System.currentTimeMillis()).nextInt(1000));
+           } catch (InterruptedException e) {
+               // no op
+           }
+           return "greeting, " + helloService.hello(message);
+       }
+   }
+   ```
+
+   这里需要注意的是,GreetingServiceImpl 的实现中声明了一个类型是 HelloService 的成员变量,并在 greeting 方法中,执行完自己逻辑之后又调用了 HelloService 上的 hello 方法。这里的 helloService 的实现将会在运行态由外部注入,注入的不是 HelloServiceImpl 的实现,而是 HelloService 的远程调用代理。通过这样的方式,完成了在一个 Dubbo 服务中继续调用另一个远程 Dubbo 服务的目的。从链路追踪的角度来说,客户端调用 GreetingService 是一个 span,GreetingService 调用 HelloService 是另一个 span,并且两者有父子关系,同属于一个 trace,也就是属于同一条调用链路。
+
+   另外,在 GreetingServiceImpl 和 HelloServiceImpl 的实现中,通过 Thread.sleep 来模拟了处理业务逻辑的耗时,以便在 Zipkin UI 上更好的展示。
+
+#### 配置
+
+为了专注在展示如何使用 Zipkin 这一点上,本文在配置和编程模型上没有采用更多的高级技术,而是使用了最传统的 Spring XML 的配置方式,帮助读者理解。更高级的通过 annotation 甚至 spring boot 的方式,读者可以自行查阅 Dubbo 和 Zipkin 相关的文档。
+
+1. 暴露 HelloService 服务
+
+   在 resouces/spring/hello-service.xml 中增加以下的配置来将 HelloServiceImpl 暴露成一个 Dubbo 服务:
+
+   * 使用了本地启动的 Zookeeper Server 作为注册中心,地址为默认值 zookeeper://127.0.0.1:2181
+   * 用 Dubbo 原生服务在端口 20880 上暴露服务
+   * 将 HelloServiceImpl 注册成 id 是 `helloService` 的 Spring Bean,这样就可以在后续的 `<dubbo:service>` 中引用到这个实现类
+   * 通过 `<dubbo:service>` 将 HelloServiceImpl 暴露成 Dubbo 服务
+
+   ```xml
+       <!-- 定义 HelloService 的应用名 -->
+       <dubbo:application name="hello-service-provider"/>
+   
+       <!-- 指定注册中心地址 -->
+       <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
+   
+       <!-- 使用 Dubbo 原生协议在 20880 端口上暴露服务 -->
+       <dubbo:protocol name="dubbo" port="20880"/>
+   
+       <!-- 将 HelloServiceImpl 的实现声明成一个 spring bean -->
+       <bean id="helloService" class="com.alibaba.dubbo.samples.service.hello.HelloServiceImpl"/>
+   
+       <!-- 将 HelloServiceImpl 声明成一个 Dubbo 服务 -->
+       <dubbo:service interface="com.alibaba.dubbo.samples.api.HelloService" ref="helloService"/>
+   ```
+
+2. 增加 Zipkin 相关的配置
+
+   在 resources/spring/hello-service.xml 中增加 Zipkin 相关的配置:
+
+   * 修改 dubbo 服务暴露的配置,添加 Zipkin 的 tracing filter 到 Dubbo 的 filter chain 中
+   * 按照 https://github.com/openzipkin/brave/blob/master/spring-beans/README.md 来配置 Zipkin 的 sender 和 tracing 的 spring bean
+
+   ```xml
+       <!-- 1. 修改 dubbo 服务暴露配置,在 filter chain 中增加 zipkin 的 tracing 过滤器 -->
+       <dubbo:service interface="com.alibaba.dubbo.samples.api.HelloService" ref="helloService" filter="tracing"/>
+   
+       <!-- 2. zipkin 相关的配置 -->
+       <!-- 使用 OKHttp 来发送 trace 信息到 Zipkin Server。这里的 Zipkin Server 启动在本地 -->
+       <bean id="sender" class="zipkin2.reporter.beans.OkHttpSenderFactoryBean">
+           <property name="endpoint" value="http://localhost:9411/api/v2/spans"/>
+       </bean>
+   
+       <bean id="tracing" class="brave.spring.beans.TracingFactoryBean">
+           <property name="localServiceName" value="hello-service"/>
+           <property name="spanReporter">
+               <bean class="zipkin2.reporter.beans.AsyncReporterFactoryBean">
+                   <property name="sender" ref="sender"/>
+                   <!-- wait up to half a second for any in-flight spans on close -->
+                   <property name="closeTimeout" value="500"/>
+               </bean>
+           </property>
+           <property name="currentTraceContext">
+               <bean class="brave.spring.beans.CurrentTraceContextFactoryBean">
+                   <property name="scopeDecorators">
+                       <bean class="brave.context.slf4j.MDCScopeDecorator" factory-method="create"/>
+                   </property>
+               </bean>
+           </property>
+       </bean>
+   ```
+
+3. 增加 HelloService 的启动类
+
+   在 com.alibaba.dubbo.samples.service.hello.Application 中通过 ClassPathXmlApplicationContext 读取 刚才配置的 spring/hello-service.xml 来初始化一个 spring context 并启动
+
+   ```java
+   package com.alibaba.dubbo.samples.service.hello;
+   
+   import org.springframework.context.support.ClassPathXmlApplicationContext;
+   
+   import java.io.IOException;
+   
+   public class Application {
+       public static void main(String[] args) throws IOException {
+           ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/hello-service.xml");
+           context.start();
+   
+           System.out.println("Hello service started");
+           // press any key to exit
+           System.in.read();
+       }
+   }
+   ```
+
+4. 暴露 GreetingService 服务,并使用 Zipkin
+
+   在 resources/spring/greeting-service.xml 中配置 GreetingService。相关步骤与 HelloService 类似,不再赘述,重点关注如何在 GreetingService 中配置下游服务的依赖。完整的 XML 配置如下:
+
+   ```xml
+   <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
+          xmlns="http://www.springframework.org/schema/beans"
+          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+          http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
+   
+       <!-- 1. 定义 GreetingService 的应用名 -->
+       <dubbo:application name="greeting-service-provider"/>
+   
+       <!-- 2. 指定注册中心地址 -->
+       <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
+   
+        <!-- 3. 使用 Dubbo 原生协议在 20881 端口上暴露服务 -->
+       <dubbo:protocol name="dubbo" port="20881"/>
+       
+       <!-- 4. 声明 HelloService 的远程代理,并在 Dubbo 的 filter chain 中增加 tracing filter -->
+       <dubbo:reference id="helloService" check="false" interface="com.alibaba.dubbo.samples.api.HelloService" filter="tracing"/>
+       
+       <!-- 5. 将 GreetingServiceImpl 的实现声明成一个 spring bean,并将 HelloService 的远程代理装配进去 -->
+       <bean id="greetingService" class="com.alibaba.dubbo.samples.service.greeting.GreetingServiceImpl">
+           <property name="helloService" ref="helloService"/>
+       </bean>
+   
+       <!-- 6. 将 GreetingServiceImpl 声明成一个 Dubbo 服务,并在 Dubbo 的 filter chain 中增加 tracing filter -->
+       <dubbo:service interface="com.alibaba.dubbo.samples.api.GreetingService" ref="greetingService" filter="tracing"/>
+   
+       <!-- 7. zipkin 相关的配置 -->
+       <bean id="sender" class="zipkin2.reporter.beans.OkHttpSenderFactoryBean">
+           <property name="endpoint" value="http://localhost:9411/api/v2/spans"/>
+       </bean>
+   
+       <bean id="tracing" class="brave.spring.beans.TracingFactoryBean">
+           <property name="localServiceName" value="greeting-service"/>
+           <property name="spanReporter">
+               <bean class="zipkin2.reporter.beans.AsyncReporterFactoryBean">
+                   <property name="sender" ref="sender"/>
+                   <!-- wait up to half a second for any in-flight spans on close -->
+                   <property name="closeTimeout" value="500"/>
+               </bean>
+           </property>
+           <property name="currentTraceContext">
+               <bean class="brave.spring.beans.CurrentTraceContextFactoryBean">
+                   <property name="scopeDecorators">
+                       <bean class="brave.context.slf4j.MDCScopeDecorator" factory-method="create"/>
+                   </property>
+               </bean>
+           </property>
+       </bean>
+   </beans>
+   ```
+
+   这里的配置与上面的 HelloService 类似,需要重点关注的有两点:
+
+   * 第 3 步中注意服务需要暴露在不同的端口上,否则会和 HelloService 冲突,本例中选择的是 20881 这个端口
+
+   * 通过第 4 步先声明 HelloService 的远程代理,然后在第 5 步中将其组装给 GreetingService 来完成服务上下游依赖的声明
+
+
+   增加 GreeeingService 的启动类,与 HelloService 类似,通过 spring/greeting-service.xml 的配置来初始化一个新的 spring context 来完成。
+
+   ```java
+   package com.alibaba.dubbo.samples.service.greeting;
+   
+   import org.springframework.context.support.ClassPathXmlApplicationContext;
+   
+   import java.io.IOException;
+   
+   public class Application {
+       public static void main(String[] args) throws IOException {
+           ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/greeting-service.xml");
+           context.start();
+   
+           System.out.println("Greeting service started");
+           // press any key to exit
+           System.in.read();
+       }
+   }
+   ```
+
+5. 实现客户端
+
+   通过 resources/spring/client.xml 初始化一个 spring context,从其中获取 GreetingService 的远程代理,发起远程调用。
+
+   ```java
+   package com.alibaba.dubbo.samples.client;
+   
+   import com.alibaba.dubbo.samples.api.GreetingService;
+   import org.springframework.context.support.ClassPathXmlApplicationContext;
+   
+   public class Application {
+   
+       public static void main(String[] args) {
+           ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/client.xml");
+           context.start();
+           // 获取远程代理并发起调用
+           GreetingService greetingService = (GreetingService) context.getBean("greetingService");
+           System.out.println(greetingService.greeting("world"));
+       }
+   }
+   ```
+
+   resource/spring/client.xml 中的配置与 Dubbo 服务的配置类似,主要是配置远程代理,以及配置 Zipkin
+
+   ```xml
+   <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
+          xmlns="http://www.springframework.org/schema/beans"
+          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+          http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
+   
+      <!-- 1. 定义 dubbo 客户端的应用名 -->
+       <dubbo:application name="dubbo-client"/>
+   
+       <!-- 2. 指定注册中心地址 -->
+       <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
+   
+       <!-- 3. 声明 GreetingService 的远程代理,并在 Dubbo 的 filter chain 中增加 tracing filter -->
+       <dubbo:reference id="greetingService" check="false" interface="com.alibaba.dubbo.samples.api.GreetingService" filter="tracing"/>
+   
+       <!-- 4. zipkin 相关的配置 -->
+       <bean id="sender" class="zipkin2.reporter.beans.OkHttpSenderFactoryBean">
+           <property name="endpoint" value="http://localhost:9411/api/v2/spans"/>
+       </bean>
+   
+       <bean id="tracing" class="brave.spring.beans.TracingFactoryBean">
+           <property name="localServiceName" value="client"/>
+           <property name="spanReporter">
+               <bean class="zipkin2.reporter.beans.AsyncReporterFactoryBean">
+                   <property name="sender" ref="sender"/>
+                   <!-- wait up to half a second for any in-flight spans on close -->
+                   <property name="closeTimeout" value="500"/>
+               </bean>
+           </property>
+           <property name="currentTraceContext">
+               <bean class="brave.spring.beans.CurrentTraceContextFactoryBean">
+                   <property name="scopeDecorators">
+                       <bean class="brave.context.slf4j.MDCScopeDecorator" factory-method="create"/>
+                   </property>
+               </bean>
+           </property>
+       </bean>
+   </beans>
+   ```
+
+完成之后的工程的目录结构如下:
+
+![zipkin dubob project structure](../../img/blog/zipkin-dubbo-project.png)
+
+### 运行
+
+现在让我们把整个链路运行起来,看看 Zipkin 链路追踪的效果。
+
+#### 启动 Zookeeper Server
+
+执行以下命令在本地启动一个 Zookeeper Server,如果没有安装,请自行从 [ZooKeeper 官网](https://zookeeper.apache.org) 下载:
+
+```bash
+$ zkServer start
+```
+
+#### 启动 Zipkin Server
+
+执行以下命令在本地启动一个 Zipkin Server:
+
+```bash
+$ curl -sSL https://zipkin.io/quickstart.sh | bash -s
+$ java -jar zipkin.jar
+```
+
+#### 启动 HelloService
+
+使用下面的命令启动 HelloService,当然也可以直接在 IDE 中启动:
+
+```bash
+$ mvn exec:java -Dexec.mainClass=com.alibaba.dubbo.samples.service.hello.Application
+```
+
+启动成功后应该可以在终端上看到 “Hello service started” 的字样。
+
+#### 启动 GreetingService
+
+使用下面的命令启动 GreetingService,当然也可以直接在 IDE 中启动:
+
+```bash
+$ mvn exec:java -Dexec.mainClass=com.alibaba.dubbo.samples.service.greeting.Application
+```
+
+启动成功后应该可以在终端上看到 “Greeting service started” 的字样。
+
+#### 运行 Dubbo 客户端
+
+使用下面的命令运行 Dubbo 客户端向 GreetingService 发起远程调用,当然也可以直接在 IDE 中运行:
+
+```bash
+$ mvn exec:java -Dexec.mainClass=com.alibaba.dubbo.samples.client.Application
+```
+
+执行成功后,客户端会在终端上输出 “greeting, hello, world”。
+
+#### 链路追踪
+
+打开浏览器访问 "http://localhost:9411" 并通过 "Find Traces" 按钮来搜索,可以找到刚刚调用的链路追踪,效果如下图所示:
+
+![zipkin trace](../../img/blog/zipkin-trace.png)
+
+还可以进一步的选择每一个 span 来查看本次调用边界内的详情,比如,hello-service 这个 span 的详情如下:
+
+![zipkin span](../../img/blog/zipkin-span.png)
+
+
+
+## 总结
+
+本文介绍了链路追踪的基本概念以及 Zipkin 的基本用法,然后用 Dubbo 构建了一条最简单的调用链路,并引入了 Zipkin 做全链路追踪。由于 Zipkin 对 Dubbo 做了很好的支持,整个集成的过程还是十分简单明了的。
+
+Zipkin 对 Dubbo 的支持是构建在 Dubbo 的 filter 扩展机制上的,有兴趣的读者可以通过 https://github.com/openzipkin/brave/blob/master/instrumentation/dubbo-rpc/src/main/java/brave/dubbo/rpc/TracingFilter.java 了解其实现细节。
+
+本文中涉及的例子可以从 https://github.com/dubbo/dubbo-samples 中的 "dubbo-samples-zipkin" 子模块中获取。另外,spring-cloud-sleth 2.0 中开始 [正式支持 Dubbo](https://cloud.spring.io/spring-cloud-static/spring-cloud-sleuth/2.0.0.RC2/single/spring-cloud-sleuth.html#_dubbo_rpc_support),相关的文章和例子后续计划提供。
diff --git a/build/blog.js b/build/blog.js
index 2fea418..a3bc799 100644
--- a/build/blog.js
+++ b/build/blog.js
@@ -1,6 +1,6 @@
-!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=77) [...]
-  Copyright (c) 2017 Jed Watson.
+!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=79) [...]
+  Copyright (c) 2016 Jed Watson.
   Licensed under the MIT License (MIT), see
   http://jedwatson.github.io/classnames
 */
-!function(){"use strict";function n(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var o=typeof r;if("string"===o||"number"===o)e.push(r);else if(Array.isArray(r)&&r.length){var a=n.apply(null,r);a&&e.push(a)}else if("object"===o)for(var u in r)i.call(r,u)&&r[u]&&e.push(u)}}return e.join(" ")}var i={}.hasOwnProperty;void 0!==e&&e.exports?(n.default=n,e.exports=n):(r=[],void 0!==(o=function(){return n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";funct [...]
\ No newline at end of file
+!function(){"use strict";function n(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var o=typeof r;if("string"===o||"number"===o)e.push(r);else if(Array.isArray(r))e.push(n.apply(null,r));else if("object"===o)for(var a in r)i.call(r,a)&&r[a]&&e.push(a)}}return e.join(" ")}var i={}.hasOwnProperty;void 0!==e&&e.exports?e.exports=n:(r=[],void 0!==(o=function(){return n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";function r(e,t,r){var o=r.configurable,u= [...]
\ No newline at end of file
diff --git a/build/blogDetail.js b/build/blogDetail.js
index 4906fdd..06767ea 100644
--- a/build/blogDetail.js
+++ b/build/blogDetail.js
@@ -1,6 +1,6 @@
-!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=78) [...]
-  Copyright (c) 2017 Jed Watson.
+!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=80) [...]
+  Copyright (c) 2016 Jed Watson.
   Licensed under the MIT License (MIT), see
   http://jedwatson.github.io/classnames
 */
-!function(){"use strict";function n(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var o=typeof r;if("string"===o||"number"===o)e.push(r);else if(Array.isArray(r)&&r.length){var a=n.apply(null,r);a&&e.push(a)}else if("object"===o)for(var u in r)i.call(r,u)&&r[u]&&e.push(u)}}return e.join(" ")}var i={}.hasOwnProperty;void 0!==e&&e.exports?(n.default=n,e.exports=n):(r=[],void 0!==(o=function(){return n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";funct [...]
\ No newline at end of file
+!function(){"use strict";function n(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var o=typeof r;if("string"===o||"number"===o)e.push(r);else if(Array.isArray(r))e.push(n.apply(null,r));else if("object"===o)for(var a in r)i.call(r,a)&&r[a]&&e.push(a)}}return e.join(" ")}var i={}.hasOwnProperty;void 0!==e&&e.exports?e.exports=n:(r=[],void 0!==(o=function(){return n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";function r(e,t,r){var o=r.configurable,u= [...]
\ No newline at end of file
diff --git a/build/community.js b/build/community.js
index f14b68b..b4a10f4 100644
--- a/build/community.js
+++ b/build/community.js
@@ -1,6 +1,6 @@
-!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=79) [...]
-  Copyright (c) 2017 Jed Watson.
+!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=81) [...]
+  Copyright (c) 2016 Jed Watson.
   Licensed under the MIT License (MIT), see
   http://jedwatson.github.io/classnames
 */
-!function(){"use strict";function n(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var o=typeof r;if("string"===o||"number"===o)e.push(r);else if(Array.isArray(r)&&r.length){var a=n.apply(null,r);a&&e.push(a)}else if("object"===o)for(var l in r)i.call(r,l)&&r[l]&&e.push(l)}}return e.join(" ")}var i={}.hasOwnProperty;void 0!==e&&e.exports?(n.default=n,e.exports=n):(r=[],void 0!==(o=function(){return n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";funct [...]
\ No newline at end of file
+!function(){"use strict";function n(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var o=typeof r;if("string"===o||"number"===o)e.push(r);else if(Array.isArray(r))e.push(n.apply(null,r));else if("object"===o)for(var a in r)i.call(r,a)&&r[a]&&e.push(a)}}return e.join(" ")}var i={}.hasOwnProperty;void 0!==e&&e.exports?e.exports=n:(r=[],void 0!==(o=function(){return n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";function r(e,t,r){var o=r.configurable,l= [...]
\ No newline at end of file
diff --git a/build/documentation.js b/build/documentation.js
index 8b41778..a4b40e4 100644
--- a/build/documentation.js
+++ b/build/documentation.js
@@ -1,6 +1,6 @@
-!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=80) [...]
-  Copyright (c) 2017 Jed Watson.
+!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=82) [...]
+  Copyright (c) 2016 Jed Watson.
   Licensed under the MIT License (MIT), see
   http://jedwatson.github.io/classnames
 */
-!function(){"use strict";function n(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var o=typeof r;if("string"===o||"number"===o)e.push(r);else if(Array.isArray(r)&&r.length){var l=n.apply(null,r);l&&e.push(l)}else if("object"===o)for(var a in r)i.call(r,a)&&r[a]&&e.push(a)}}return e.join(" ")}var i={}.hasOwnProperty;void 0!==e&&e.exports?(n.default=n,e.exports=n):(r=[],void 0!==(o=function(){return n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";funct [...]
\ No newline at end of file
+!function(){"use strict";function n(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var o=typeof r;if("string"===o||"number"===o)e.push(r);else if(Array.isArray(r))e.push(n.apply(null,r));else if("object"===o)for(var l in r)i.call(r,l)&&r[l]&&e.push(l)}}return e.join(" ")}var i={}.hasOwnProperty;void 0!==e&&e.exports?e.exports=n:(r=[],void 0!==(o=function(){return n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";function r(e,t,r){var o=r.configurable,a= [...]
\ No newline at end of file
diff --git a/build/home.js b/build/home.js
index 04b514a..990eba6 100644
--- a/build/home.js
+++ b/build/home.js
@@ -1,6 +1,6 @@
-!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=81) [...]
-  Copyright (c) 2017 Jed Watson.
+!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=83) [...]
+  Copyright (c) 2016 Jed Watson.
   Licensed under the MIT License (MIT), see
   http://jedwatson.github.io/classnames
 */
-!function(){"use strict";function n(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var o=typeof r;if("string"===o||"number"===o)e.push(r);else if(Array.isArray(r)&&r.length){var i=n.apply(null,r);i&&e.push(i)}else if("object"===o)for(var u in r)a.call(r,u)&&r[u]&&e.push(u)}}return e.join(" ")}var a={}.hasOwnProperty;void 0!==e&&e.exports?(n.default=n,e.exports=n):(r=[],void 0!==(o=function(){return n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";funct [...]
\ No newline at end of file
+!function(){"use strict";function n(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var o=typeof r;if("string"===o||"number"===o)e.push(r);else if(Array.isArray(r))e.push(n.apply(null,r));else if("object"===o)for(var i in r)a.call(r,i)&&r[i]&&e.push(i)}}return e.join(" ")}var a={}.hasOwnProperty;void 0!==e&&e.exports?e.exports=n:(r=[],void 0!==(o=function(){return n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";function r(e,t,r){var o=r.configurable,u= [...]
\ No newline at end of file
diff --git a/img/blog/trace-sample.png b/img/blog/trace-sample.png
new file mode 100644
index 0000000..5e49b93
Binary files /dev/null and b/img/blog/trace-sample.png differ
diff --git a/img/blog/zipkin-architecture.png b/img/blog/zipkin-architecture.png
new file mode 100644
index 0000000..1d80b0d
Binary files /dev/null and b/img/blog/zipkin-architecture.png differ
diff --git a/img/blog/zipkin-dubbo-project.png b/img/blog/zipkin-dubbo-project.png
new file mode 100644
index 0000000..63b79da
Binary files /dev/null and b/img/blog/zipkin-dubbo-project.png differ
diff --git a/img/blog/zipkin-span.png b/img/blog/zipkin-span.png
new file mode 100644
index 0000000..3a3f6f5
Binary files /dev/null and b/img/blog/zipkin-span.png differ
diff --git a/img/blog/zipkin-trace.png b/img/blog/zipkin-trace.png
new file mode 100644
index 0000000..1deb4d5
Binary files /dev/null and b/img/blog/zipkin-trace.png differ
diff --git a/img/blog/zipkin-web-screenshot.png b/img/blog/zipkin-web-screenshot.png
new file mode 100644
index 0000000..7a34242
Binary files /dev/null and b/img/blog/zipkin-web-screenshot.png differ
diff --git a/site_config/blog.js b/site_config/blog.js
index c79dc0c..a522e84 100644
--- a/site_config/blog.js
+++ b/site_config/blog.js
@@ -156,6 +156,13 @@ export default {
     barText: '博客',
     postsTitle: '所有文章',
     list: [
+        {
+            title: '在 Dubbo 中使用 Zipkin',
+            author:'@beiwei30',
+            dateStr: 'Oct 12th, 2018',
+            desc: '本文介绍如何使用 Zipkin 在 Dubbo 中进行全链路追踪',
+            link: '/zh-cn/blog/use-zipkin-in-dubbo.html',
+        },
 		{
             title: 'Dubbo在Service Mesh下的思考和方案',
             author: '@JeffLv',
diff --git a/zh-cn/blog/index.html b/zh-cn/blog/index.html
index f02fc99..d40972b 100644
--- a/zh-cn/blog/index.html
+++ b/zh-cn/blog/index.html
@@ -12,7 +12,7 @@
 	<link rel="stylesheet" href="/build/blog.css" />
 </head>
 <body>
-	<div id="root"><div class="blog-list-page" data-reactroot="" data-reactid="1" data-react-checksum="-896549980"><header class="header-container header-container-normal" data-reactid="2"><div class="header-body" data-reactid="3"><a href="/zh-cn/index.html" data-reactid="4"><img class="logo" src="/img/dubbo_colorful.png" data-reactid="5"/></a><div class="search search-normal" data-reactid="6"><span class="icon-search" data-reactid="7"></span></div><span class="language-switch language-swit [...]
+	<div id="root"><div class="blog-list-page" data-reactroot="" data-reactid="1" data-react-checksum="1763107681"><header class="header-container header-container-normal" data-reactid="2"><div class="header-body" data-reactid="3"><a href="/zh-cn/index.html" data-reactid="4"><img class="logo" src="/img/dubbo_colorful.png" data-reactid="5"/></a><div class="search search-normal" data-reactid="6"><span class="icon-search" data-reactid="7"></span></div><span class="language-switch language-swit [...]
 	<script src="https://f.alicdn.com/react/15.4.1/react-with-addons.min.js"></script>
 	<script src="https://f.alicdn.com/react/15.4.1/react-dom.min.js"></script>
 	<script>
diff --git a/zh-cn/blog/use-zipkin-in-dubbo.html b/zh-cn/blog/use-zipkin-in-dubbo.html
new file mode 100644
index 0000000..7852650
--- /dev/null
+++ b/zh-cn/blog/use-zipkin-in-dubbo.html
@@ -0,0 +1,538 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+	<meta charset="UTF-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
+	<meta name="keywords" content="zipkin,dubbo,trace,span,dapper" />
+	<meta name="description" content="如何在 Dubbo 中使用 Zipkin 进行全链路追踪" />
+	<!-- 网页标签标题 -->
+	<title>在 Dubbo 中使用 Zipkin</title>
+	<link rel="shortcut icon" href="/img/dubbo.ico"/>
+	<link rel="stylesheet" href="/build/blogDetail.css" />
+</head>
+<body>
+	<div id="root"><div class="blog-detail-page" data-reactroot="" data-reactid="1" data-react-checksum="1656807911"><header class="header-container header-container-normal" data-reactid="2"><div class="header-body" data-reactid="3"><a href="/zh-cn/index.html" data-reactid="4"><img class="logo" src="/img/dubbo_colorful.png" data-reactid="5"/></a><div class="search search-normal" data-reactid="6"><span class="icon-search" data-reactid="7"></span></div><span class="language-switch language-sw [...]
+<p>随着业务的发展,应用的规模不断的扩大,传统的应用架构无法满足诉求,服务化架构改造势在必行,以 Dubbo 为代表的分布式服务框架成为了服务化改造架构中的基石。随着微服务理念逐渐被大众接受,应用进一步向更细粒度拆分,并且,不同的应用由不同的开发团队独立负责,整个分布式系统变得十分复杂。没有人能够清晰及时的知道当前系统整体的依赖关系。当出现问题时,也无法及时知道具体是链路上的哪个环节出了问题。</p>
+<p>在这个背景下,Google 发表了 <a href="https://ai.google/research/pubs/pub36356">Dapper</a> 的论文,描述了如何通过一个分布式追踪系统解决上述问题。基于该论文,各大互联网公司实现并部署了自己的分布式追踪系统,其中比较出名的有阿里巴巴的 EagleEye。本文中提到的 Zipkin 是 Twitter 公司开源的分布式追踪系统。下面会详细介绍如何在 Dubbo 中使用 Zipkin 来实现分布式追踪。</p>
+<h2>Zipkin 简介</h2>
+<p>Zipkin 是基于 <a href="https://ai.google/research/pubs/pub36356">Dapper</a> 论文实现,由 Twitter 开源的分布式追踪系统,通过收集分布式服务执行时间的信息来达到追踪服务调用链路、以及分析服务执行延迟等目的。</p>
+<h3>Zipkin 架构</h3>
+<p><img src="../../img/blog/zipkin-architecture.png" alt="Zipkin architecture"></p>
+<p>Collector 收集器、Storage 存储、API、UI 用户界面等几部分构成了 Zipkin Server 部分,对应于 GitHub 上 <a href="https://github.com/openzipkin/zipkin">openzipkin/zipkin</a> 这个项目。而收集应用中调用的耗时信息并将其上报的组件与应用共生,并拥有各个语言的实现版本,其中 Java 的实现是 GitHub 上 <a href="https://github.com/openzipkin/brave">openzipkin/brave</a>。除了 Java 客户端实现之外,openzipkin 还提供了许多其他语言的实现,其中包括了 go、php、JavaScript、.net、ruby 等,具体列表可以参阅 Zipkin 的 <a href="https://zipkin.io/pages/existing_instrumentations">Exiting instrumentations</a>。</p>
+<h3>Zipkin 的工作过程</h3>
+<p>当用户发起一次调用时,Zipkin 的客户端会在入口处为整条调用链路生成一个全局唯一的 trace id,并为这条链路中的每一次分布式调用生成一个 span id。span 与 span 之间可以有父子嵌套关系,代表分布式调用中的上下游关系。span 和 span 之间可以是兄弟关系,代表当前调用下的两次子调用。一个 trace 由一组 span 组成,可以看成是由 trace 为根节点,span 为若干个子节点的一棵树。</p>
+<p><img src="../../img/blog/trace-sample.png" alt="Related image"></p>
+<p>Span 由调用边界来分隔,在 Zipkin 中,调用边界由以下四个 annotation 来表示:</p>
+<ul>
+<li>cs - Clent Sent 客户端发送了请求</li>
+<li>sr - Server Receive 服务端接受到请求</li>
+<li>ss - Server Send 服务端处理完毕,向客户端发送回应</li>
+<li>cr - Client Receive 客户端收到结果</li>
+</ul>
+<p>显然,通过这四个 annotation 上的时间戳,可以轻易的知道一次完整的调用在不同阶段的耗时,比如:</p>
+<ul>
+<li>sr - cs 代表了请求在网络上的耗时</li>
+<li>ss - sr 代表了服务端处理请求的耗时</li>
+<li>cr - ss 代表了回应在网络上的耗时</li>
+<li>cr - cs 代表了一次调用的整体耗时</li>
+</ul>
+<p>Zipkin 会将 trace 相关的信息在调用链路上传递,并在每个调用边界结束时异步的把当前调用的耗时信息上报给 Zipkin Server。Zipkin Server 在收到 trace 信息后,将其存储起来,Zipkin 支持的存储类型有 inMemory、MySql、Cassandra、以及 ElasticsSearch 几种方式。随后 Zipkin 的 Web UI 会通过 API 访问的方式从存储中将 trace 信息提取出来分析并展示,如下图所示:</p>
+<p><img src="../../img/blog/zipkin-web-screenshot.png" alt="Web interface screenshot"></p>
+<h2>在 Dubbo 中使用</h2>
+<p>由于 <a href="https://github.com/openzipkin/brave">Brave</a> 对 Dubbo 已经主动做了支持,在 Dubbo 中集成基于 Zipkin 的链路追踪变的十分简单。下面会按照 Brave 中关于 <a href="https://github.com/openzipkin/brave/blob/master/instrumentation/dubbo-rpc/README.md">Dubbo RPC 支持的指引</a>来说明如何在 Dubbo 中使用 Zipkin。</p>
+<h3>安装 Zipkin Server</h3>
+<p>按照 <a href="https://github.com/openzipkin/zipkin/tree/master/zipkin-server#quick-start">Zipkin 官方文档中的快速开始</a> 来安装 Zipkin,如下所示:</p>
+<pre><code class="language-bash">$ curl -sSL https://zipkin.io/quickstart.sh | bash -s
+$ java -jar zipkin.jar
+</code></pre>
+<p>按照这种方式安装的 Zipkin Server 使用的存储类型是 inMemory 的。当服务器停机之后,所有收集到的 trace 信息会丢失,不适用于生产系统。如果在生产系统中使用,需要配置另外的存储类型。Zipkin 支持 MySql、Cassandra、和 ElasticSearch。推荐使用 Cassandra 和 ElasticSearch,相关的配置请自行查阅<a href="https://github.com/openzipkin/zipkin/tree/master/zipkin-server">官方文档</a>。</p>
+<p>本文为了演示方便,使用的存储是 inMemory 类型。成功启动之后,可以在终端看到如下的提示:</p>
+<pre><code class="language-bash">$ java -jar zipkin.jar
+Picked up JAVA_TOOL_OPTIONS: -Djava.awt.headless=<span class="hljs-literal">true</span>
+                                    ********
+                                  **        **
+                                 *            *
+                                **            **
+                                **            **
+                                 **          **
+                                  **        **
+                                    ********
+                                      ****
+                                      ****
+        ****                          ****
+     ******                           ****                                 ***
+  ****************************************************************************
+    *******                           ****                                 ***
+        ****                          ****
+                                       **
+                                       **
+
+
+             *****      **     *****     ** **       **     **   **
+               **       **     **  *     ***         **     **** **
+              **        **     *****     ****        **     **  ***
+             ******     **     **        **  **      **     **   **
+
+:: Powered by Spring Boot ::         (v2.0.5.RELEASE)
+
+...
+
+o.s.b.w.e.u.UndertowServletWebServer     : Undertow started on port(s) 9411 (http) with context path <span class="hljs-string">''</span>
+2018-10-10 18:40:31.605  INFO 21072 --- [           main] z.s.ZipkinServer                         : Started ZipkinServer <span class="hljs-keyword">in</span> 6.835 seconds (JVM running <span class="hljs-keyword">for</span> 8.35)
+</code></pre>
+<p>然后在浏览器中访问 <a href="http://localhost:9411">http://localhost:9411</a> 验证 WEB 界面。</p>
+<h3>配置 Maven 依赖</h3>
+<h4>引入 Brave 依赖</h4>
+<p>新建一个新的 Java 工程,并在 pom.xml 中引入 Brave 相关的依赖如下:</p>
+<pre><code class="language-xml">    <span class="hljs-tag">&lt;<span class="hljs-name">properties</span>&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">brave.version</span>&gt;</span>5.4.2<span class="hljs-tag">&lt;/<span class="hljs-name">brave.version</span>&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">zipkin-reporter.version</span>&gt;</span>2.7.9<span class="hljs-tag">&lt;/<span class="hljs-name">zipkin-reporter.version</span>&gt;</span>
+    <span class="hljs-tag">&lt;/<span class="hljs-name">properties</span>&gt;</span>
+
+    <span class="hljs-tag">&lt;<span class="hljs-name">dependencyManagement</span>&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span>
+            <span class="hljs-comment">&lt;!-- 引入 zipkin brave 的 BOM 文件 --&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>io.zipkin.brave<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>brave-bom<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${brave.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">type</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">type</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>import<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span>
+            <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
+			
+            <span class="hljs-comment">&lt;!-- 引入 zipkin repoter 的 BOM 文件 --&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>io.zipkin.reporter2<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>zipkin-reporter-bom<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${zipkin-reporter.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">type</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">type</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>import<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span>
+            <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
+        <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span>
+    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencyManagement</span>&gt;</span>
+
+    <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span>
+        <span class="hljs-comment">&lt;!-- 1. brave 对 dubbo 的集成 --&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>io.zipkin.brave<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>brave-instrumentation-dubbo-rpc<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
+        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
+
+        <span class="hljs-comment">&lt;!-- 2. brave 的 spring bean 支持 --&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>io.zipkin.brave<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>brave-spring-beans<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
+        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
+
+        <span class="hljs-comment">&lt;!-- 3. 在 SLF4J 的 MDC (Mapped Diagnostic Context) 中支持 traceId 和 spanId --&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>io.zipkin.brave<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>brave-context-slf4j<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
+        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
+
+        <span class="hljs-comment">&lt;!-- 4. 使用 okhttp3 作为 reporter --&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>io.zipkin.reporter2<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>zipkin-sender-okhttp3<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
+        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
+    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span>
+</code></pre>
+<p>其中:</p>
+<ol>
+<li>引入 brave-instrumentation-dubbo-rpc,brave 对 dubbo 的支持:<a href="https://github.com/openzipkin/brave/blob/master/instrumentation/dubbo-rpc/README.md">https://github.com/openzipkin/brave/blob/master/instrumentation/dubbo-rpc/README.md</a></li>
+<li>引入 brave-spring-beans,brave 对 spring bean 的支持:<a href="https://github.com/openzipkin/brave/blob/master/spring-beans/README.md">https://github.com/openzipkin/brave/blob/master/spring-beans/README.md</a></li>
+<li>引入 brave-context-slf4j,brave 对 SLF4J 的支持,可以在 MDC 中使用 traceId 和 spanId:<a href="https://github.com/openzipkin/brave/blob/master/context/slf4j/README.md">https://github.com/openzipkin/brave/blob/master/context/slf4j/README.md</a></li>
+<li>引入 zipkin-sender-okhttp3,使用 okhttp3 上报数据:<a href="https://github.com/openzipkin/zipkin-reporter-java">https://github.com/openzipkin/zipkin-reporter-java</a></li>
+</ol>
+<h4>引入 Dubbo 相关依赖</h4>
+<p>Dubbo 相关的依赖是 Dubbo 本身以及 Zookeeper 客户端,在下面的例子中,我们将会使用独立的 Zookeeper Server 作为服务发现。</p>
+<pre><code class="language-xml">    <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span>
+        <span class="hljs-comment">&lt;!-- 1. Zookeeper 客户端依赖 --&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.curator<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>curator-framework<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.12.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">exclusions</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">exclusion</span>&gt;</span>
+                    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>io.netty<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
+                    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>netty<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
+                <span class="hljs-tag">&lt;/<span class="hljs-name">exclusion</span>&gt;</span>
+            <span class="hljs-tag">&lt;/<span class="hljs-name">exclusions</span>&gt;</span>
+        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
+        <span class="hljs-comment">&lt;!-- 2. Dubbo 依赖 --&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.alibaba<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>dubbo<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.6.2<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
+        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
+    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span>
+</code></pre>
+<p>其中:</p>
+<ol>
+<li>Dubbo 这里依赖独立的 Zookeeper Server 做服务发现,这里使用的客户端是 Curator</li>
+<li>引入 Dubbo 框架的依赖,原则上 2.6 的任何版本都是工作的,这里使用的是 2.6.2 版本</li>
+</ol>
+<h3>实现</h3>
+<p>我们这里构造的场景是一个有两个节点的服务依赖链,也就是,当一个 Dubbo 客户端调用服务 A 时,服务 A 将会继续调用服务 B。在这个例子中,服务 A 是 greeting service,它所依赖的下游服务服务 B 是 hello service。</p>
+<h4>定义服务接口</h4>
+<p>为此需要事先定义两个服务接口 GreetingService 以及 HelloService</p>
+<ol>
+<li>
+<p>com.alibaba.dubbo.samples.api.GreetingService</p>
+<pre><code class="language-java"><span class="hljs-keyword">package</span> com.alibaba.dubbo.samples.api;
+
+<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">GreetingService</span> </span>{
+    <span class="hljs-function">String <span class="hljs-title">greeting</span><span class="hljs-params">(String message)</span></span>;
+}
+</code></pre>
+</li>
+<li>
+<p>com.alibaba.dubbo.samples.api.HelloService</p>
+<pre><code class="language-java"><span class="hljs-keyword">package</span> com.alibaba.dubbo.samples.api;
+
+<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">HelloService</span> </span>{
+    <span class="hljs-function">String <span class="hljs-title">hello</span><span class="hljs-params">(String message)</span></span>;
+}
+</code></pre>
+</li>
+</ol>
+<h4>实现服务接口</h4>
+<p>为了区分对待,所有和 HelloService 相关的实现代码都放在 hello 子包下,同理 GreetingService 相关的放在 greeting 子包下。</p>
+<ol>
+<li>
+<p>实现 com.alibaba.dubbo.samples.api.HelloService</p>
+<pre><code class="language-java"><span class="hljs-keyword">package</span> com.alibaba.dubbo.samples.service.hello;
+
+<span class="hljs-keyword">import</span> com.alibaba.dubbo.samples.api.HelloService;
+
+<span class="hljs-keyword">import</span> java.util.Random;
+
+<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HelloServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">HelloService</span> </span>{
+    <span class="hljs-meta">@Override</span>
+    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">hello</span><span class="hljs-params">(String message)</span> </span>{
+        <span class="hljs-keyword">try</span> {
+            <span class="hljs-comment">// 通过 sleep 模拟业务逻辑处理时间</span>
+            Thread.sleep(<span class="hljs-keyword">new</span> Random(System.currentTimeMillis()).nextInt(<span class="hljs-number">1000</span>));
+        } <span class="hljs-keyword">catch</span> (InterruptedException e) {
+            <span class="hljs-comment">// no op</span>
+        }
+        <span class="hljs-keyword">return</span> <span class="hljs-string">"hello, "</span> + message;
+    }
+}
+</code></pre>
+</li>
+<li>
+<p>实现 com.alibaba.dubbo.samples.api.GreetingService</p>
+<pre><code class="language-java"><span class="hljs-keyword">package</span> com.alibaba.dubbo.samples.service.greeting;
+
+<span class="hljs-keyword">import</span> com.alibaba.dubbo.samples.api.GreetingService;
+<span class="hljs-keyword">import</span> com.alibaba.dubbo.samples.api.HelloService;
+
+<span class="hljs-keyword">import</span> java.util.Random;
+
+<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GreetingServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">GreetingService</span> </span>{
+	<span class="hljs-comment">// 下游依赖服务,运行时靠 spring 容器注入 HelloService 的服务代理</span>
+    <span class="hljs-keyword">private</span> HelloService helloService;
+
+    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setHelloService</span><span class="hljs-params">(HelloService helloService)</span> </span>{
+        <span class="hljs-keyword">this</span>.helloService = helloService;
+    }
+
+    <span class="hljs-meta">@Override</span>
+    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">greeting</span><span class="hljs-params">(String message)</span> </span>{
+        <span class="hljs-keyword">try</span> {
+            <span class="hljs-comment">// 通过 sleep 模拟业务逻辑处理时间</span>
+            Thread.sleep(<span class="hljs-keyword">new</span> Random(System.currentTimeMillis()).nextInt(<span class="hljs-number">1000</span>));
+        } <span class="hljs-keyword">catch</span> (InterruptedException e) {
+            <span class="hljs-comment">// no op</span>
+        }
+        <span class="hljs-keyword">return</span> <span class="hljs-string">"greeting, "</span> + helloService.hello(message);
+    }
+}
+</code></pre>
+<p>这里需要注意的是,GreetingServiceImpl 的实现中声明了一个类型是 HelloService 的成员变量,并在 greeting 方法中,执行完自己逻辑之后又调用了 HelloService 上的 hello 方法。这里的 helloService 的实现将会在运行态由外部注入,注入的不是 HelloServiceImpl 的实现,而是 HelloService 的远程调用代理。通过这样的方式,完成了在一个 Dubbo 服务中继续调用另一个远程 Dubbo 服务的目的。从链路追踪的角度来说,客户端调用 GreetingService 是一个 span,GreetingService 调用 HelloService 是另一个 span,并且两者有父子关系,同属于一个 trace,也就是属于同一条调用链路。</p>
+<p>另外,在 GreetingServiceImpl 和 HelloServiceImpl 的实现中,通过 Thread.sleep 来模拟了处理业务逻辑的耗时,以便在 Zipkin UI 上更好的展示。</p>
+</li>
+</ol>
+<h4>配置</h4>
+<p>为了专注在展示如何使用 Zipkin 这一点上,本文在配置和编程模型上没有采用更多的高级技术,而是使用了最传统的 Spring XML 的配置方式,帮助读者理解。更高级的通过 annotation 甚至 spring boot 的方式,读者可以自行查阅 Dubbo 和 Zipkin 相关的文档。</p>
+<ol>
+<li>
+<p>暴露 HelloService 服务</p>
+<p>在 resouces/spring/hello-service.xml 中增加以下的配置来将 HelloServiceImpl 暴露成一个 Dubbo 服务:</p>
+<ul>
+<li>使用了本地启动的 Zookeeper Server 作为注册中心,地址为默认值 zookeeper://127.0.0.1:2181</li>
+<li>用 Dubbo 原生服务在端口 20880 上暴露服务</li>
+<li>将 HelloServiceImpl 注册成 id 是 <code>helloService</code> 的 Spring Bean,这样就可以在后续的 <code>&lt;dubbo:service&gt;</code> 中引用到这个实现类</li>
+<li>通过 <code>&lt;dubbo:service&gt;</code> 将 HelloServiceImpl 暴露成 Dubbo 服务</li>
+</ul>
+<pre><code class="language-xml">    <span class="hljs-comment">&lt;!-- 定义 HelloService 的应用名 --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">dubbo:application</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"hello-service-provider"</span>/&gt;</span>
+
+    <span class="hljs-comment">&lt;!-- 指定注册中心地址 --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">dubbo:registry</span> <span class="hljs-attr">address</span>=<span class="hljs-string">"zookeeper://127.0.0.1:2181"</span>/&gt;</span>
+
+    <span class="hljs-comment">&lt;!-- 使用 Dubbo 原生协议在 20880 端口上暴露服务 --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">dubbo:protocol</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"dubbo"</span> <span class="hljs-attr">port</span>=<span class="hljs-string">"20880"</span>/&gt;</span>
+
+    <span class="hljs-comment">&lt;!-- 将 HelloServiceImpl 的实现声明成一个 spring bean --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"helloService"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"com.alibaba.dubbo.samples.service.hello.HelloServiceImpl"</span>/&gt;</span>
+
+    <span class="hljs-comment">&lt;!-- 将 HelloServiceImpl 声明成一个 Dubbo 服务 --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">dubbo:service</span> <span class="hljs-attr">interface</span>=<span class="hljs-string">"com.alibaba.dubbo.samples.api.HelloService"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"helloService"</span>/&gt;</span>
+</code></pre>
+</li>
+<li>
+<p>增加 Zipkin 相关的配置</p>
+<p>在 resources/spring/hello-service.xml 中增加 Zipkin 相关的配置:</p>
+<ul>
+<li>修改 dubbo 服务暴露的配置,添加 Zipkin 的 tracing filter 到 Dubbo 的 filter chain 中</li>
+<li>按照 <a href="https://github.com/openzipkin/brave/blob/master/spring-beans/README.md">https://github.com/openzipkin/brave/blob/master/spring-beans/README.md</a> 来配置 Zipkin 的 sender 和 tracing 的 spring bean</li>
+</ul>
+<pre><code class="language-xml">    <span class="hljs-comment">&lt;!-- 1. 修改 dubbo 服务暴露配置,在 filter chain 中增加 zipkin 的 tracing 过滤器 --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">dubbo:service</span> <span class="hljs-attr">interface</span>=<span class="hljs-string">"com.alibaba.dubbo.samples.api.HelloService"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"helloService"</span> <span class="hljs-attr">filter</span>=<span class="hljs-string">"tracing"</span>/&gt;</span>
+
+    <span class="hljs-comment">&lt;!-- 2. zipkin 相关的配置 --&gt;</span>
+    <span class="hljs-comment">&lt;!-- 使用 OKHttp 来发送 trace 信息到 Zipkin Server。这里的 Zipkin Server 启动在本地 --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"sender"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"zipkin2.reporter.beans.OkHttpSenderFactoryBean"</span>&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"endpoint"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"http://localhost:9411/api/v2/spans"</span>/&gt;</span>
+    <span class="hljs-tag">&lt;/<span class="hljs-name">bean</span>&gt;</span>
+
+    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"tracing"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"brave.spring.beans.TracingFactoryBean"</span>&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"localServiceName"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"hello-service"</span>/&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"spanReporter"</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"zipkin2.reporter.beans.AsyncReporterFactoryBean"</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"sender"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"sender"</span>/&gt;</span>
+                <span class="hljs-comment">&lt;!-- wait up to half a second for any in-flight spans on close --&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"closeTimeout"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"500"</span>/&gt;</span>
+            <span class="hljs-tag">&lt;/<span class="hljs-name">bean</span>&gt;</span>
+        <span class="hljs-tag">&lt;/<span class="hljs-name">property</span>&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"currentTraceContext"</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"brave.spring.beans.CurrentTraceContextFactoryBean"</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"scopeDecorators"</span>&gt;</span>
+                    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"brave.context.slf4j.MDCScopeDecorator"</span> <span class="hljs-attr">factory-method</span>=<span class="hljs-string">"create"</span>/&gt;</span>
+                <span class="hljs-tag">&lt;/<span class="hljs-name">property</span>&gt;</span>
+            <span class="hljs-tag">&lt;/<span class="hljs-name">bean</span>&gt;</span>
+        <span class="hljs-tag">&lt;/<span class="hljs-name">property</span>&gt;</span>
+    <span class="hljs-tag">&lt;/<span class="hljs-name">bean</span>&gt;</span>
+</code></pre>
+</li>
+<li>
+<p>增加 HelloService 的启动类</p>
+<p>在 com.alibaba.dubbo.samples.service.hello.Application 中通过 ClassPathXmlApplicationContext 读取 刚才配置的 spring/hello-service.xml 来初始化一个 spring context 并启动</p>
+<pre><code class="language-java"><span class="hljs-keyword">package</span> com.alibaba.dubbo.samples.service.hello;
+
+<span class="hljs-keyword">import</span> org.springframework.context.support.ClassPathXmlApplicationContext;
+
+<span class="hljs-keyword">import</span> java.io.IOException;
+
+<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Application</span> </span>{
+    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> IOException </span>{
+        ClassPathXmlApplicationContext context = <span class="hljs-keyword">new</span> ClassPathXmlApplicationContext(<span class="hljs-string">"spring/hello-service.xml"</span>);
+        context.start();
+
+        System.out.println(<span class="hljs-string">"Hello service started"</span>);
+        <span class="hljs-comment">// press any key to exit</span>
+        System.in.read();
+    }
+}
+</code></pre>
+</li>
+<li>
+<p>暴露 GreetingService 服务,并使用 Zipkin</p>
+<p>在 resources/spring/greeting-service.xml 中配置 GreetingService。相关步骤与 HelloService 类似,不再赘述,重点关注如何在 GreetingService 中配置下游服务的依赖。完整的 XML 配置如下:</p>
+<pre><code class="language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">beans</span> <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">"http://www.w3.org/2001/XMLSchema-instance"</span>
+       <span class="hljs-attr">xmlns:dubbo</span>=<span class="hljs-string">"http://dubbo.apache.org/schema/dubbo"</span>
+       <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.springframework.org/schema/beans"</span>
+       <span class="hljs-attr">xsi:schemaLocation</span>=<span class="hljs-string">"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"</span>&gt;</span>
+
+    <span class="hljs-comment">&lt;!-- 1. 定义 GreetingService 的应用名 --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">dubbo:application</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"greeting-service-provider"</span>/&gt;</span>
+
+    <span class="hljs-comment">&lt;!-- 2. 指定注册中心地址 --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">dubbo:registry</span> <span class="hljs-attr">address</span>=<span class="hljs-string">"zookeeper://127.0.0.1:2181"</span>/&gt;</span>
+
+     <span class="hljs-comment">&lt;!-- 3. 使用 Dubbo 原生协议在 20881 端口上暴露服务 --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">dubbo:protocol</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"dubbo"</span> <span class="hljs-attr">port</span>=<span class="hljs-string">"20881"</span>/&gt;</span>
+    
+    <span class="hljs-comment">&lt;!-- 4. 声明 HelloService 的远程代理,并在 Dubbo 的 filter chain 中增加 tracing filter --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">dubbo:reference</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"helloService"</span> <span class="hljs-attr">check</span>=<span class="hljs-string">"false"</span> <span class="hljs-attr">interface</span>=<span class="hljs-string">"com.alibaba.dubbo.samples.api.HelloService"</span> <span class="hljs-attr">filter</span>=<span class="hljs-string">"tracing"</span>/&gt;</span>
+    
+    <span class="hljs-comment">&lt;!-- 5. 将 GreetingServiceImpl 的实现声明成一个 spring bean,并将 HelloService 的远程代理装配进去 --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"greetingService"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"com.alibaba.dubbo.samples.service.greeting.GreetingServiceImpl"</span>&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"helloService"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"helloService"</span>/&gt;</span>
+    <span class="hljs-tag">&lt;/<span class="hljs-name">bean</span>&gt;</span>
+
+    <span class="hljs-comment">&lt;!-- 6. 将 GreetingServiceImpl 声明成一个 Dubbo 服务,并在 Dubbo 的 filter chain 中增加 tracing filter --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">dubbo:service</span> <span class="hljs-attr">interface</span>=<span class="hljs-string">"com.alibaba.dubbo.samples.api.GreetingService"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"greetingService"</span> <span class="hljs-attr">filter</span>=<span class="hljs-string">"tracing"</span>/&gt;</span>
+
+    <span class="hljs-comment">&lt;!-- 7. zipkin 相关的配置 --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"sender"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"zipkin2.reporter.beans.OkHttpSenderFactoryBean"</span>&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"endpoint"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"http://localhost:9411/api/v2/spans"</span>/&gt;</span>
+    <span class="hljs-tag">&lt;/<span class="hljs-name">bean</span>&gt;</span>
+
+    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"tracing"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"brave.spring.beans.TracingFactoryBean"</span>&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"localServiceName"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"greeting-service"</span>/&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"spanReporter"</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"zipkin2.reporter.beans.AsyncReporterFactoryBean"</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"sender"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"sender"</span>/&gt;</span>
+                <span class="hljs-comment">&lt;!-- wait up to half a second for any in-flight spans on close --&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"closeTimeout"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"500"</span>/&gt;</span>
+            <span class="hljs-tag">&lt;/<span class="hljs-name">bean</span>&gt;</span>
+        <span class="hljs-tag">&lt;/<span class="hljs-name">property</span>&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"currentTraceContext"</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"brave.spring.beans.CurrentTraceContextFactoryBean"</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"scopeDecorators"</span>&gt;</span>
+                    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"brave.context.slf4j.MDCScopeDecorator"</span> <span class="hljs-attr">factory-method</span>=<span class="hljs-string">"create"</span>/&gt;</span>
+                <span class="hljs-tag">&lt;/<span class="hljs-name">property</span>&gt;</span>
+            <span class="hljs-tag">&lt;/<span class="hljs-name">bean</span>&gt;</span>
+        <span class="hljs-tag">&lt;/<span class="hljs-name">property</span>&gt;</span>
+    <span class="hljs-tag">&lt;/<span class="hljs-name">bean</span>&gt;</span>
+<span class="hljs-tag">&lt;/<span class="hljs-name">beans</span>&gt;</span>
+</code></pre>
+<p>这里的配置与上面的 HelloService 类似,需要重点关注的有两点:</p>
+<ul>
+<li>
+<p>第 3 步中注意服务需要暴露在不同的端口上,否则会和 HelloService 冲突,本例中选择的是 20881 这个端口</p>
+</li>
+<li>
+<p>通过第 4 步先声明 HelloService 的远程代理,然后在第 5 步中将其组装给 GreetingService 来完成服务上下游依赖的声明</p>
+</li>
+</ul>
+<p>增加 GreeeingService 的启动类,与 HelloService 类似,通过 spring/greeting-service.xml 的配置来初始化一个新的 spring context 来完成。</p>
+<pre><code class="language-java"><span class="hljs-keyword">package</span> com.alibaba.dubbo.samples.service.greeting;
+
+<span class="hljs-keyword">import</span> org.springframework.context.support.ClassPathXmlApplicationContext;
+
+<span class="hljs-keyword">import</span> java.io.IOException;
+
+<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Application</span> </span>{
+    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> IOException </span>{
+        ClassPathXmlApplicationContext context = <span class="hljs-keyword">new</span> ClassPathXmlApplicationContext(<span class="hljs-string">"spring/greeting-service.xml"</span>);
+        context.start();
+
+        System.out.println(<span class="hljs-string">"Greeting service started"</span>);
+        <span class="hljs-comment">// press any key to exit</span>
+        System.in.read();
+    }
+}
+</code></pre>
+</li>
+<li>
+<p>实现客户端</p>
+<p>通过 resources/spring/client.xml 初始化一个 spring context,从其中获取 GreetingService 的远程代理,发起远程调用。</p>
+<pre><code class="language-java"><span class="hljs-keyword">package</span> com.alibaba.dubbo.samples.client;
+
+<span class="hljs-keyword">import</span> com.alibaba.dubbo.samples.api.GreetingService;
+<span class="hljs-keyword">import</span> org.springframework.context.support.ClassPathXmlApplicationContext;
+
+<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Application</span> </span>{
+
+    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
+        ClassPathXmlApplicationContext context = <span class="hljs-keyword">new</span> ClassPathXmlApplicationContext(<span class="hljs-string">"spring/client.xml"</span>);
+        context.start();
+        <span class="hljs-comment">// 获取远程代理并发起调用</span>
+        GreetingService greetingService = (GreetingService) context.getBean(<span class="hljs-string">"greetingService"</span>);
+        System.out.println(greetingService.greeting(<span class="hljs-string">"world"</span>));
+    }
+}
+</code></pre>
+<p>resource/spring/client.xml 中的配置与 Dubbo 服务的配置类似,主要是配置远程代理,以及配置 Zipkin</p>
+<pre><code class="language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">beans</span> <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">"http://www.w3.org/2001/XMLSchema-instance"</span>
+       <span class="hljs-attr">xmlns:dubbo</span>=<span class="hljs-string">"http://dubbo.apache.org/schema/dubbo"</span>
+       <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.springframework.org/schema/beans"</span>
+       <span class="hljs-attr">xsi:schemaLocation</span>=<span class="hljs-string">"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"</span>&gt;</span>
+
+   <span class="hljs-comment">&lt;!-- 1. 定义 dubbo 客户端的应用名 --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">dubbo:application</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"dubbo-client"</span>/&gt;</span>
+
+    <span class="hljs-comment">&lt;!-- 2. 指定注册中心地址 --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">dubbo:registry</span> <span class="hljs-attr">address</span>=<span class="hljs-string">"zookeeper://127.0.0.1:2181"</span>/&gt;</span>
+
+    <span class="hljs-comment">&lt;!-- 3. 声明 GreetingService 的远程代理,并在 Dubbo 的 filter chain 中增加 tracing filter --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">dubbo:reference</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"greetingService"</span> <span class="hljs-attr">check</span>=<span class="hljs-string">"false"</span> <span class="hljs-attr">interface</span>=<span class="hljs-string">"com.alibaba.dubbo.samples.api.GreetingService"</span> <span class="hljs-attr">filter</span>=<span class="hljs-string">"tracing"</span>/&gt;</span>
+
+    <span class="hljs-comment">&lt;!-- 4. zipkin 相关的配置 --&gt;</span>
+    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"sender"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"zipkin2.reporter.beans.OkHttpSenderFactoryBean"</span>&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"endpoint"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"http://localhost:9411/api/v2/spans"</span>/&gt;</span>
+    <span class="hljs-tag">&lt;/<span class="hljs-name">bean</span>&gt;</span>
+
+    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"tracing"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"brave.spring.beans.TracingFactoryBean"</span>&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"localServiceName"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"client"</span>/&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"spanReporter"</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"zipkin2.reporter.beans.AsyncReporterFactoryBean"</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"sender"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"sender"</span>/&gt;</span>
+                <span class="hljs-comment">&lt;!-- wait up to half a second for any in-flight spans on close --&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"closeTimeout"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"500"</span>/&gt;</span>
+            <span class="hljs-tag">&lt;/<span class="hljs-name">bean</span>&gt;</span>
+        <span class="hljs-tag">&lt;/<span class="hljs-name">property</span>&gt;</span>
+        <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"currentTraceContext"</span>&gt;</span>
+            <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"brave.spring.beans.CurrentTraceContextFactoryBean"</span>&gt;</span>
+                <span class="hljs-tag">&lt;<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"scopeDecorators"</span>&gt;</span>
+                    <span class="hljs-tag">&lt;<span class="hljs-name">bean</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"brave.context.slf4j.MDCScopeDecorator"</span> <span class="hljs-attr">factory-method</span>=<span class="hljs-string">"create"</span>/&gt;</span>
+                <span class="hljs-tag">&lt;/<span class="hljs-name">property</span>&gt;</span>
+            <span class="hljs-tag">&lt;/<span class="hljs-name">bean</span>&gt;</span>
+        <span class="hljs-tag">&lt;/<span class="hljs-name">property</span>&gt;</span>
+    <span class="hljs-tag">&lt;/<span class="hljs-name">bean</span>&gt;</span>
+<span class="hljs-tag">&lt;/<span class="hljs-name">beans</span>&gt;</span>
+</code></pre>
+</li>
+</ol>
+<p>完成之后的工程的目录结构如下:</p>
+<p><img src="../../img/blog/zipkin-dubbo-project.png" alt="zipkin dubob project structure"></p>
+<h3>运行</h3>
+<p>现在让我们把整个链路运行起来,看看 Zipkin 链路追踪的效果。</p>
+<h4>启动 Zookeeper Server</h4>
+<p>执行以下命令在本地启动一个 Zookeeper Server,如果没有安装,请自行从 <a href="https://zookeeper.apache.org">ZooKeeper 官网</a> 下载:</p>
+<pre><code class="language-bash">$ zkServer start
+</code></pre>
+<h4>启动 Zipkin Server</h4>
+<p>执行以下命令在本地启动一个 Zipkin Server:</p>
+<pre><code class="language-bash">$ curl -sSL https://zipkin.io/quickstart.sh | bash -s
+$ java -jar zipkin.jar
+</code></pre>
+<h4>启动 HelloService</h4>
+<p>使用下面的命令启动 HelloService,当然也可以直接在 IDE 中启动:</p>
+<pre><code class="language-bash">$ mvn <span class="hljs-built_in">exec</span>:java -Dexec.mainClass=com.alibaba.dubbo.samples.service.hello.Application
+</code></pre>
+<p>启动成功后应该可以在终端上看到 “Hello service started” 的字样。</p>
+<h4>启动 GreetingService</h4>
+<p>使用下面的命令启动 GreetingService,当然也可以直接在 IDE 中启动:</p>
+<pre><code class="language-bash">$ mvn <span class="hljs-built_in">exec</span>:java -Dexec.mainClass=com.alibaba.dubbo.samples.service.greeting.Application
+</code></pre>
+<p>启动成功后应该可以在终端上看到 “Greeting service started” 的字样。</p>
+<h4>运行 Dubbo 客户端</h4>
+<p>使用下面的命令运行 Dubbo 客户端向 GreetingService 发起远程调用,当然也可以直接在 IDE 中运行:</p>
+<pre><code class="language-bash">$ mvn <span class="hljs-built_in">exec</span>:java -Dexec.mainClass=com.alibaba.dubbo.samples.client.Application
+</code></pre>
+<p>执行成功后,客户端会在终端上输出 “greeting, hello, world”。</p>
+<h4>链路追踪</h4>
+<p>打开浏览器访问 &quot;<a href="http://localhost:9411">http://localhost:9411</a>&quot; 并通过 &quot;Find Traces&quot; 按钮来搜索,可以找到刚刚调用的链路追踪,效果如下图所示:</p>
+<p><img src="../../img/blog/zipkin-trace.png" alt="zipkin trace"></p>
+<p>还可以进一步的选择每一个 span 来查看本次调用边界内的详情,比如,hello-service 这个 span 的详情如下:</p>
+<p><img src="../../img/blog/zipkin-span.png" alt="zipkin span"></p>
+<h2>总结</h2>
+<p>本文介绍了链路追踪的基本概念以及 Zipkin 的基本用法,然后用 Dubbo 构建了一条最简单的调用链路,并引入了 Zipkin 做全链路追踪。由于 Zipkin 对 Dubbo 做了很好的支持,整个集成的过程还是十分简单明了的。</p>
+<p>Zipkin 对 Dubbo 的支持是构建在 Dubbo 的 filter 扩展机制上的,有兴趣的读者可以通过 <a href="https://github.com/openzipkin/brave/blob/master/instrumentation/dubbo-rpc/src/main/java/brave/dubbo/rpc/TracingFilter.java">https://github.com/openzipkin/brave/blob/master/instrumentation/dubbo-rpc/src/main/java/brave/dubbo/rpc/TracingFilter.java</a> 了解其实现细节。</p>
+<p>本文中涉及的例子可以从 <a href="https://github.com/dubbo/dubbo-samples">https://github.com/dubbo/dubbo-samples</a> 中的 &quot;dubbo-samples-zipkin&quot; 子模块中获取。另外,spring-cloud-sleth 2.0 中开始 <a href="https://cloud.spring.io/spring-cloud-static/spring-cloud-sleuth/2.0.0.RC2/single/spring-cloud-sleuth.html#_dubbo_rpc_support">正式支持 Dubbo</a>,相关的文章和例子后续计划提供。</p>
+</section><footer class="footer-container" data-reactid="21"><div class="footer-body" data-reactid="22"><img src="/img/dubbo_gray.png" data-reactid="23"/><img class="apache" src="/img/apache_logo.png" data-reactid="24"/><div class="cols-container" data-reactid="25"><div class="col col-12" data-reactid="26"><h3 data-reactid="27">Disclaimer</h3><p data-reactid="28">Apache Dubbo is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Incubator. Incubatio [...]
+	<script src="https://f.alicdn.com/react/15.4.1/react-with-addons.min.js"></script>
+	<script src="https://f.alicdn.com/react/15.4.1/react-dom.min.js"></script>
+	<script>
+		window.rootPath = '';
+  </script>
+  <script src="/build/blogDetail.js"></script>
+  <!-- Global site tag (gtag.js) - Google Analytics -->
+	<script async src="https://www.googletagmanager.com/gtag/js?id=UA-112489517-1"></script>
+	<script>
+		window.dataLayer = window.dataLayer || [];
+		function gtag(){dataLayer.push(arguments);}
+		gtag('js', new Date());
+
+		gtag('config', 'UA-112489517-1');
+	</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/zh-cn/blog/use-zipkin-in-dubbo.json b/zh-cn/blog/use-zipkin-in-dubbo.json
new file mode 100644
index 0000000..17f168b
--- /dev/null
+++ b/zh-cn/blog/use-zipkin-in-dubbo.json
@@ -0,0 +1,7 @@
+{
+  "filename": "use-zipkin-in-dubbo.md",
+  "__html": "<h1>在 Dubbo 中使用 Zipkin</h1>\n<p>随着业务的发展,应用的规模不断的扩大,传统的应用架构无法满足诉求,服务化架构改造势在必行,以 Dubbo 为代表的分布式服务框架成为了服务化改造架构中的基石。随着微服务理念逐渐被大众接受,应用进一步向更细粒度拆分,并且,不同的应用由不同的开发团队独立负责,整个分布式系统变得十分复杂。没有人能够清晰及时的知道当前系统整体的依赖关系。当出现问题时,也无法及时知道具体是链路上的哪个环节出了问题。</p>\n<p>在这个背景下,Google 发表了 <a href=\"https://ai.google/research/pubs/pub36356\">Dapper</a> 的论文,描述了如何通过一个分布式追踪系统解决上述问题。基于该论文,各大互联网公司实现并部署了自己的分布式追踪系统,其中比较出名的有阿里巴巴的 EagleEye。本文中提到的 Zipkin 是 Twitter
  公司开源的分布式追踪系统。下面会详细介绍如何在 Dubbo 中使用 Zipkin 来实现分布式追踪。</p>\n [...]
+  "title": "在 Dubbo 中使用 Zipkin",
+  "keywords": "zipkin,dubbo,trace,span,dapper",
+  "description": "如何在 Dubbo 中使用 Zipkin 进行全链路追踪"
+}
\ No newline at end of file