1. 程式人生 > >jaegeropentracing的Java-client完整分布式追蹤鏈

jaegeropentracing的Java-client完整分布式追蹤鏈

ans cli thp sta XML agent client tst ati

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,坐下簡單記錄,有問題可以留言交流。

jaegeropentracing的Java-client完整分布式追蹤鏈