jaegeropentracing的Java-client完整分布式追踪链,在分布式系统中透传trace信息
下面是代码:
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,坐下简单记录,有问题可以留言交流。