• 十、Spring Cloud 之旅 -- Sleuth + Zipkin 实现微服务跟踪


    什么是Sleuth:

    Sleuth是Spring Cloud提供的一个框架,用于追踪微服务的调用过程。当外部用户向集群发起请求时,这些请求将会调用多个微服务,每个微服务又会依赖其他微服务,此时如果出现异常情况,排查问题非常困难,因此我们需要知道到底哪个服务出了问题,哪个环节出了问题,以及Root Cause是什么。Sleuth就是Spring Cloud为解决这些问题精心打造的,它可以很方便的和ZipKin,ELK等数据分析、微服务跟踪系统进行整合。

    Sleuth借鉴了Google Dapper的设计,我们需要了解以下两个概念:

    1)Trace:表示整个跟踪过程,从用户发起请求到最终的响应。一次跟踪包含多个跨度,这些跨度一树状结构进行保存。

    2)Span:跨度,表示一次调用的过程,一次跟踪包含多次调用过程。例如:用户请求A服务,A服务有调用了B服务,那么此时将会产生两个跨度。

    除了上面讲的跟踪和跨度外,我们还需要了解以下Annotation(事件标识),它主要用于记录时间的存在,主要包括以下几个事件标识:

    cs: Client Sent,客户端发送了请求。

    sr: Server Received, 标识服务器接收到了请求,并开始处理。

    ss: Server Sent, 标识服务器完成请求的处理,并对客户端做出响应。

    cr: Client Received, 标识客户端接收到响应,意味着整个跨度的结束。

     

    代码演示 (Sleuth搭档Zipkin 实现微服务调用跟踪):

    项目构成如下:

    eureka-server:集群服务器

    first-service-provider: 第一个服务提供者

    second-service-provider: 第二个服务提供者,为了方便演示跨度

    first-service-invoker: 服务调用者

    zipkin-server: Zipkin服务器

    NOTE:需要源码的盆友请前往github:

    https://github.com/aharddreamer/chendong/tree/master/springcloud/sleuth-zipkin-CSDN

     

    eureka-server依旧只是作为集群服务器,所以不需要改什么代码。

     

    zipkin-server我们需要做以下配置:

    首先,POM中确保有这些依赖:

    1)Spring Cloud的POM导入进来

    <dependencyManagement>
    
       <dependencies>
    
          <dependency>
    
             <groupId>org.springframework.cloud</groupId>
    
             <artifactId>spring-cloud-dependencies</artifactId>
    
             <version>Dalston.SR1</version>
    
             <type>pom</type>
    
             <scope>import</scope>
    
          </dependency>
    
       </dependencies>
    
    </dependencyManagement>

    2)加入必要的dependency

    <dependency>
    
       <groupId>org.springframework.cloud</groupId>
    
       <artifactId>spring-cloud-starter-eureka</artifactId>
    
    </dependency>

    <dependency>
       <groupId>io.zipkin.java</groupId>
       <artifactId>zipkin-server</artifactId>
    </dependency>

    <dependency>
       <groupId>io.zipkin.java</groupId>
       <artifactId>zipkin-autoconfigure-ui</artifactId>
    </dependency>

     

    然后再application.properties或者application.yml文件中加入以下配置:

    spring.application.name=zipkin-server
    
    server.port=9411
    
    eureka.instance.hostname=localhost
    
    eureka.client.service-url.default-zone=http://localhost:8761/eureka/

     

    最后在启动类中加入必要的注解@EnableZipkinServer:

    OK了,zipkin服务器就这么搭起来了。

     

    first-service-provider我们要做这些改动:

    首先确保POM中有如下依赖:

    <dependencies>
    
    
    
       <dependency>
    
          <groupId>org.springframework.cloud</groupId>
    
          <artifactId>spring-cloud-starter-eureka</artifactId>
    
       </dependency>
    
    
    
       <dependency>
    
          <groupId>org.springframework.cloud</groupId>
    
          <artifactId>spring-cloud-starter-zipkin</artifactId>
    
       </dependency>
    
    
    
       <dependency>
    
          <groupId>org.springframework.cloud</groupId>
    
          <artifactId>spring-cloud-sleuth-zipkin</artifactId>
    
       </dependency>
    
    
    
    </dependencies>

     

    在application.properties中加入以下配置:

    spring.application.name=first-service-provider
    
    server.port=8080
    
    eureka.instance.hostname=localhost
    
    eureka.client.service-url.default-zone=http://localhost:8761/eureka/
    
    spring.zipkin.base-url=http://localhost:9411
    
    spring.sleuth.sampler.percentage=1.0

    最后两行是配置zipkin和sleuth,一个是zipkin服务器的URL,一个是设置追踪的百分比为1.0 也就是100%

     

    我们添加一个测试接口:/message 一会测试用。

     

    second-service-provider 中的代码改动:

    POM和first-service-provider中的一样。

    application.properties配置如下 (端口和app name不一样):

    spring.application.name=second-service-provider
    
    server.port=8081
    
    eureka.instance.hostname=localhost
    
    eureka.client.service-url.default-zone=http://localhost:8761/eureka/
    
    spring..base-url=http://localhost:9411
    
    spring.sleuth.sampler.percentage=1.0

     

    也加一个测试接口:/message2

     

    first-service-invoker 中的改动:

    这个是用户进来的入口,也是调用上面两个service provider的客户端。

    POM的依赖和service provider一样。

    application.properties也大致相似,配置如下 (端口,APP name不一样):

    server.port=9000
    
    spring.application.name=first-service-invoker
    
    eureka.instance.hostname=localhost
    
    eureka.client.service-url.default-zone=http://localhost:8761/eureka/
    
    spring.zipkin.base-url=http://localhost:9411
    
    spring.sleuth.sampler.percentage=1.0

     

    加一个测试接口:/test 待会要在浏览器调用test接口,然后test接口会去请求first-service-provider的message接口和second-service-provider的message2接口。然后把两个接口的数据返回给用户(浏览器)

    这是RestTemplate的配置(注意别漏掉注解哦 否则会有意想不到的惊喜)

     

    测试程序:

    好啦,所有配置就绪,依次按顺序启动

    eureka-server,

    zipkin-server,

    first-service-provider,

    second-service-provider,

    first-service-invoker

     

    启动成功之后,打开浏览器,访问:localhost:9411 即可看到zipkin的主界面了:

    我们再来访问first-service-invoker的test接口,看看sleuth+zipkin如何进行跟踪和跨度。

    http://localhost:9000/test

    可以看到 下面两条消息分别是两个service provider返回过来的,说明调用成功了。

     

    我们再去刷新一下localhost:9411 (zipkin server)

    咦,啥都诶有??别紧张,把时间区间调整一下,默认的区间太短 可能看不到。我们把时间区间调大一点,间隔一个小时或几分钟:

    这下就有了

    可以发现,有三个跨度,可以点击进去查看详细情况:

    点击第一个,可以看到Invoker接收了浏览器的请求,并且响应给浏览器的详细情况和时间。

    点击第二个(first-service-provider)可以看到他上面的请求详情,有四个动作,分别是Invoker发送请求,他接收请求,他发送请求,Invoker接收请求:

    点击第三个,和第二个类似,也是四个动作,就不贴图了。

     

    主界面上面还有一些过滤条件,可以帮助我们筛选有用的跟踪。右上角有个json图标,点击可以看到json格式的跟踪详情:

    [

        {

            "traceId":"e1b2de96f3839da0",

            "id":"e1b2de96f3839da0",

            "name":"http:/test",

            "timestamp":1554821937637000,

            "duration":1640589,

            "annotations":[

                {

                    "timestamp":1554821937637000,

                    "value":"sr",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                },

                {

                    "timestamp":1554821939270000,

                    "value":"ss",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                }

            ],

            "binaryAnnotations":[

                {

                    "key":"mvc.controller.class",

                    "value":"HelloController",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                },

                {

                    "key":"mvc.controller.method",

                    "value":"test",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                },

                {

                    "key":"spring.instance_id",

                    "value":"DESKTOP-2IO2BLG:first-service-invoker:9000",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                }

            ]

        },

        {

            "traceId":"e1b2de96f3839da0",

            "id":"468d0d24781a3ec6",

            "name":"http:/message",

            "parentId":"e1b2de96f3839da0",

            "timestamp":1554821937682000,

            "duration":789000,

            "annotations":[

                {

                    "timestamp":1554821937683000,

                    "value":"cs",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                },

                {

                    "timestamp":1554821938430000,

                    "value":"sr",

                    "endpoint":{

                        "serviceName":"first-service-provider",

                        "ipv4":"192.168.0.105",

                        "port":8080

                    }

                },

                {

                    "timestamp":1554821938446000,

                    "value":"ss",

                    "endpoint":{

                        "serviceName":"first-service-provider",

                        "ipv4":"192.168.0.105",

                        "port":8080

                    }

                },

                {

                    "timestamp":1554821938472000,

                    "value":"cr",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                }

            ],

            "binaryAnnotations":[

                {

                    "key":"http.host",

                    "value":"first-service-provider",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                },

                {

                    "key":"http.method",

                    "value":"GET",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                },

                {

                    "key":"http.path",

                    "value":"/message",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                },

                {

                    "key":"http.url",

                    "value":"http://first-service-provider/message",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                },

                {

                    "key":"mvc.controller.class",

                    "value":"FirstServiceProviderApplication",

                    "endpoint":{

                        "serviceName":"first-service-provider",

                        "ipv4":"192.168.0.105",

                        "port":8080

                    }

                },

                {

                    "key":"mvc.controller.method",

                    "value":"getMsg",

                    "endpoint":{

                        "serviceName":"first-service-provider",

                        "ipv4":"192.168.0.105",

                        "port":8080

                    }

                },

                {

                    "key":"spring.instance_id",

                    "value":"DESKTOP-2IO2BLG:first-service-invoker:9000",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                },

                {

                    "key":"spring.instance_id",

                    "value":"DESKTOP-2IO2BLG:first-service-provider:8080",

                    "endpoint":{

                        "serviceName":"first-service-provider",

                        "ipv4":"192.168.0.105",

                        "port":8080

                    }

                }

            ]

        },

        {

            "traceId":"e1b2de96f3839da0",

            "id":"84259e78200f60ea",

            "name":"http:/message2",

            "parentId":"e1b2de96f3839da0",

            "timestamp":1554821938853000,

            "duration":81000,

            "annotations":[

                {

                    "timestamp":1554821938853000,

                    "value":"cs",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                },

                {

                    "timestamp":1554821938930000,

                    "value":"sr",

                    "endpoint":{

                        "serviceName":"second-service-provider",

                        "ipv4":"192.168.0.105",

                        "port":8081

                    }

                },

                {

                    "timestamp":1554821938932000,

                    "value":"ss",

                    "endpoint":{

                        "serviceName":"second-service-provider",

                        "ipv4":"192.168.0.105",

                        "port":8081

                    }

                },

                {

                    "timestamp":1554821938934000,

                    "value":"cr",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                }

            ],

            "binaryAnnotations":[

                {

                    "key":"http.host",

                    "value":"second-service-provider",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                },

                {

                    "key":"http.method",

                    "value":"GET",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                },

                {

                    "key":"http.path",

                    "value":"/message2",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                },

                {

                    "key":"http.url",

                    "value":"http://second-service-provider/message2",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                },

                {

                    "key":"mvc.controller.class",

                    "value":"SecondServiceProviderApplication",

                    "endpoint":{

                        "serviceName":"second-service-provider",

                        "ipv4":"192.168.0.105",

                        "port":8081

                    }

                },

                {

                    "key":"mvc.controller.method",

                    "value":"getMsg",

                    "endpoint":{

                        "serviceName":"second-service-provider",

                        "ipv4":"192.168.0.105",

                        "port":8081

                    }

                },

                {

                    "key":"spring.instance_id",

                    "value":"DESKTOP-2IO2BLG:first-service-invoker:9000",

                    "endpoint":{

                        "serviceName":"first-service-invoker",

                        "ipv4":"192.168.0.105",

                        "port":9000

                    }

                },

                {

                    "key":"spring.instance_id",

                    "value":"DESKTOP-2IO2BLG:second-service-provider:8081",

                    "endpoint":{

                        "serviceName":"second-service-provider",

                        "ipv4":"192.168.0.105",

                        "port":8081

                    }

                }

            ]

        }

    ]

     

  • 相关阅读:
    hbase Compaction
    hadoop集群 动态添加或删除节点
    Hadoop节点迁移
    Spark程序运行常见错误解决方法以及优化
    用python执行sql来验证数据是否准时导入了目标库
    kylin2.3版本启用jdbc数据源(可以直接通过sql生成hive表,省去手动导数据到hive,并建hive表的麻烦)
    phoenix 二级索引使用实践
    jenkins任务失败,发送邮件通知
    Coolite学习
    MySql连接和授权命令
  • 原文地址:https://www.cnblogs.com/cnsec/p/13407170.html
Copyright © 2020-2023  润新知