zoukankan      html  css  js  c++  java
  • 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,坐下简单记录,有问题可以留言交流。

  • 相关阅读:
    2018年度总结
    SQL特殊comment语法
    mysql 主从复制change master to
    mysql 主从复制参数slave_net_timeout
    show master status, show slave status中的Executed_Gtid_Set
    mysql重复start slave、stop slave测试
    golang database sql DSN (Data Source Name)中的timeout, readTimeout
    mysql show master status为空值
    Linux 建立 TCP 连接的超时时间分析(解惑)
    golang 原子操作函数
  • 原文地址:https://www.cnblogs.com/edi-kai/p/9779932.html
Copyright © 2011-2022 走看看