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,坐下简单记录,有问题可以留言交流。

  • 相关阅读:
    Advanced Configuration Tricks
    Reviewing the Blog Module
    Editing and Deleting Data
    Making Use of Forms and Fieldsets
    Understanding the Router
    SQL Abstraction and Object Hydration
    Preparing for Different Databases
    Java学习理解路线图
    Openstack学习历程_1_视频
    CentOS安装Nginx负载
  • 原文地址:https://www.cnblogs.com/edi-kai/p/9779932.html
Copyright © 2011-2022 走看看