jaegeropentracing的Java-client完整分布式追踪链

jaegeropentracing的Java-client完整分布式追踪链,在分布式系统中透传trace信息

之前文章记录了jaegeropentracing的Java-client追踪链在单系统中的调用示例,现在记录下在分布式系统是如何实现一个完整的调用链的.

这篇文章是基于我之前的两篇文章编写了,链接如下:

Spring整合CXF webservice restful 实例

jaegeropentracing的Java-client

下面是代码:

client端代码如下:

public static void main(String[] args) throws InterruptedException {

        Configuration conf = new Configuration("EK Demo Jaeger."); //配置全局configuration
        //发送sender configuration
        Configuration.SenderConfiguration senderConf = new Configuration.SenderConfiguration();

        senderConf.withAgentHost("192.168.1.111");
        senderConf.withAgentPort(5775);

        Sender sender = senderConf.getSender();
        log.info("[ sender ] : "+sender);

        conf.withReporter(
                new Configuration.ReporterConfiguration()
                        .withSender(senderConf)
                        .withFlushInterval(100)
                        .withLogSpans(false)
        );

        conf.withSampler(
                new Configuration.SamplerConfiguration()
                        .withType("const")
                        .withParam(1)
        );

        Tracer tracer = conf.getTracer();
        log.info(tracer.toString());
        GlobalTracer.register(tracer);

        Tracer.SpanBuilder spanBuilder = GlobalTracer.get().buildSpan("EK Demo P");
        Span parent = spanBuilder.start();
        parent.log(100, "before Controller Method is running......");
        log.info("before Controller Method is running......");

        Tracer.SpanBuilder childB = GlobalTracer.get().buildSpan("EK Demo child").asChildOf(parent);
        Span child = childB.start();
        JaegerSpanContext context = (JaegerSpanContext) child.context();
        child.log("......"+context.contextAsString());

        String url = "http://localhost:8080/jeeek/services/phopuService/getUserPost";
        HttpClient httpClient = HttpClients.createSystem();
        final HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Content-Type", "text/plain");
        StringEntity se = null;

        String weatherInfo = null;
        try {

            //透传context到服务端
            tracer.inject(parent.context(), Format.Builtin.TEXT_MAP, new TextMap() {
                @Override
                public Iterator<Map.Entry<String, String>> iterator() {
                    throw new UnsupportedOperationException("TextMapInjectAdapter should only be used with Tracer.inject()");
                }

                @Override
                public void put(String key, String value) {
                    log.info(key+",----------------------- "+value);
                    httpPost.setHeader(key, value);
                }
            });

            se = new StringEntity("101010500");
            se.setContentType("text/plain");
            httpPost.setEntity(se);
            HttpResponse response = null;

            response = httpClient.execute(httpPost);

            int status = response.getStatusLine().getStatusCode();
            log.info("[接口返回状态吗] : " + status);

            weatherInfo = getReturnStr(response);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        log.info("[接口返回信息] : " + weatherInfo);

        Thread.sleep(5000);
        child.finish();
        Thread.sleep(5000);
        parent.finish();
        log.info("after Controller Method is running.......");

        Thread.sleep(10000);
    }

服务端代码如下:

@POST
    @Produces(MediaType.APPLICATION_JSON) //指定返回数据的类型 json字符串
    //@Consumes(MediaType.TEXT_PLAIN) //指定请求数据的类型 文本字符串
    @Path("/getUserPost")
    public User getUserPost(String userId) {
        this.logger.info("Call getUserPost() method...." + userId);

        Configuration conf = new Configuration("EK Demo Jaeger."); //配置全局configuration
        //发送sender configuration
        Configuration.SenderConfiguration senderConf = new Configuration.SenderConfiguration();

        senderConf.withAgentHost("192.168.1.111");
        //senderConf.withAgentHost("192.168.3.22");
        senderConf.withAgentPort(5775);

        Sender sender = senderConf.getSender();
        logger.info("[ sender ] : "+sender);

        conf.withReporter(
                new Configuration.ReporterConfiguration()
                        .withSender(senderConf)
                        .withFlushInterval(100)
                        .withLogSpans(false)
        );

        conf.withSampler(
                new Configuration.SamplerConfiguration()
                        .withType("const")
                        .withParam(1)
        );

        Tracer tracer = conf.getTracer();
        logger.info(tracer.toString());
        if (!GlobalTracer.isRegistered())
            GlobalTracer.register(tracer);

        Tracer.SpanBuilder spanBuilder = tracer.buildSpan("server Span");

        /**
        * 由于此处只是一个restful接口,所以自己通过request获取头信息然后封装到map中,才作为参数传递
        * 在实际的RPC分布式系统中,可以直接调用 request.getAttachments() 来返回头信息的trace信息
        **/
        //获取客户端透传的traceId,然后绑定span到该trace对应的span上
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String traceId = request.getHeader("uber-trace-id");//此处可以根据实际遍历header来获取,header的key有可能会发生变化[不确定]
        Map<String, String> map = new HashMap<>();//将header信息放到map中
        map.put("uber-trace-id", traceId);
        logger.info("--------------------"+traceId);
        try {
            //new TextMapExtractAdapter(map)此处参数是个map,在分布式系统中直接调用request.getAttachments()
            SpanContext spanContext = tracer.extract(Format.Builtin.TEXT_MAP, new TextMapExtractAdapter(map));
            if (spanContext != null) {
                spanBuilder.asChildOf(spanContext);
            }
        } catch (Exception e) {
            spanBuilder.withTag("Error", "extract from request fail, error msg:" + e.getMessage());
        }

        User user = new User();
        user.setUserName("中文");
        user.setAge(26);
        user.setSex("m");

        Span span = spanBuilder.start();
        span.log("xxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
        span.finish();

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return user;
    }

在springMVC系统中手动获取request,需要配置web.xml,如下:

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

当然,这只是一个demo,坐下简单记录,有问题可以留言交流。

原文地址:https://www.cnblogs.com/edi-kai/p/9779932.html

时间: 2024-08-28 12:06:54

jaegeropentracing的Java-client完整分布式追踪链的相关文章

java微服务分布式调用链APM监控

几种分布式调用链监控组件的比较微服务架构下,服务按照不同的维度进行拆分,一次请求请求往往需要涉及到多个服务.互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发.可能使用不同的编程语言来实现.有可能布在了几千台服务器,横跨多个不同的数据中心.因此,就需要一些可以帮助理解系统行为.用于分析性能问题的工具,以便发生故障的时候,能够快速定位和解决问题. 分布式调用链监控组件在这样的环境下产生了.最出名的是谷歌公开的论文提到的 Dapper .开发Dapper是为了收集更多的复杂分

跟着小程学微服务-自己动手扩展分布式调用链

一.说在前面 微服务是当下最火的词语,现在很多公司都在推广微服务,当服务越来越多的时候,我们是否会纠结以下几个问题: 面对一笔超时的订单,究竟是哪一步处理时间超长呢? 数据由于并发莫名篡改,到底都谁有重大嫌疑呢? 处理遗漏了一笔订单,曾经是哪个环节出错把它落下了? 系统莫名的报错,究竟是哪一个服务报的错误? 每个服务那么多实例服务器,如何快速定位到是哪一个实例服务器报错的呢? 现在很多系统都要求可用性达到99.9%以上,那么我们除了增加系统健壮性减少故障的同时,我们又如何在真正发生故障的时候,快

OpenTracing:开放式分布式追踪规范

前言 想实现一个简单的追踪系统似乎是容易的,需要必要的调用链id,时间戳等:想实现一款易用不侵入代码的追踪系统就很麻烦了,需要接触CLR和IL相关知识:即使你费劲心力做出了那些,如果性能不够好,也没有人使用的. 追踪系统主要可以分两部分实现,客户端和服务端.大软件厂商基于各自的需求已经开发了APM,从头迈入这个圈子的个人拿什么去竞争?最后的结果基本都是凉凉了.合作共赢才是最好的. 从我学习分布式调用链开始,就打算了解客户端和服务端的通信规范,我选择了zipkin入门,基本了解了一些zipkin的

Kafka 0.9+Zookeeper3.4.6集群搭建、配置,新版Java Client的使用要点,高可用性测试,以及各种坑(二)

上一节中(点此传送),我们完成了Kafka集群的搭建,本节中我们将介绍0.9版本中的新API,以及Kafka集群高可用性的测试 1. 使用Kafka的Producer API来完成消息的推送 1) Kafka 0.9.0.1的java client依赖: <dependency>     <groupId>org.apache.kafka</groupId>     <artifactId>kafka-clients</artifactId>  

Apache SkyWalking 为.NET Core带来开箱即用的分布式追踪和应用性能监控

在大型网站系统设计中,随着分布式架构,特别是微服务架构的流行,我们将系统解耦成更小的单元,通过不断的添加新的.小的模块或者重用已经有的模块来构建复杂的系统.随着模块的不断增多,一次请求可能会涉及到十几个甚至几十个服务的协同处理,那么如何准确快速的定位到线上故障和性能瓶颈,便成为我们不得不面对的棘手问题. 为解决分布式架构中复杂的服务定位和性能问题,Google在论文<Dapper, a Large-Scale Distributed Systems Tracing Infrastructure>

千锋《Java高级教程+分布式+springcloud+微信支付》

课程目录:├─千锋Java高级教程-cas单点登录(完结-8集)│      01单点登录介绍│      02cas介绍│      03tomcat搭建https│      04cas server搭建│      05Cas 配置 jdbc 连接数据库│      06Cas 密码 MD5值│      07 Cas 整合shiro1│      07 Cas 整合shiro2│      ├─千锋Java高级教程-dubbo+zookeeper分布式系统架构基础(11集)│      

使用docker-compose 一键部署你的分布式调用链跟踪框架skywalking

原文:使用docker-compose 一键部署你的分布式调用链跟踪框架skywalking 一旦你的程序docker化之后,你会遇到各种问题,比如原来采用的本地记日志的方式就不再方便了,虽然你可以挂载到宿主机,但你使用 --scale 的话,会导致 记录日志异常,所以最好的方式还是要做日志中心化,另一个问题,原来一个请求在一个进程中的痉挛失败,你可以在日志中巡查出调用堆栈,但是docker化之后, 原来一个进程的东西会拆成几个微服务,这时候最好就要有一个分布式的调用链跟踪,类似于wcf中的sv

SkyWalking 分布式追踪系统

随着微服务架构的流行,一些微服务架构下的问题也会越来越突出,比如一个请求会涉及多个服务,而服务本身可能也会依赖其他服务,整个请求路径就构成了一个网状的调用链,而在整个调用链中一旦某个节点发生异常,整个调用链的稳定性就会受到影响,所以会深深的感受到 “银弹” 这个词是不存在的,每种架构都有其优缺点 . 目前主要的一些 APM 工具有: Cat.Zipkin.Pinpoint.SkyWalking, SkyWalking 它是一款优秀的国产 APM 工具,包括了分布式追踪.性能指标分析.应用和服务依

SkyWalking+Asp.Net Core 分布式追踪系统

SkyWalking 是一套(APM)分布式追踪系统,SkyWalking提供了很多数据存储列如:Mysql,H2,Elasticsearch7 等,我这里用的是Elasticsearch7 ,SkyWalking默认H2,H2是内存数据库,数据文件一旦损坏oapservice就启动不了,所以我这里用的是Elasticsearch7 . SkyWalking下载地址 Elasticsearch下载地址 SkyWalking 安装的环境要求 CentOS7 JDK8+ Elasticsearch7