Во многих случаях,trace
Он распространяется в различных приложениях, и наиболее часто используемый метод удаленного вызова —Http
.
В этом случае мы обычно добавляем дополнительныеHttp Header
Передайте информацию трассировки, а затем систематизируйте ее.
В этом разделе собраны текущие самые горячиеSpringBoot
сервер, а затемOkHttp3
Совершайте звонки, чтобы показать, как организована распределенная цепочка звонков.
Для большей сериализации обратите внимание на вкус Miss Sister. Для соответствующего кода этой статьи см.:
https://github.com/sayhiai/example-jaeger-opentracing-tutorial-003
Требуемые знания:
创建一个简单的SpringBoot应用
使用OkHttp3发起一个Post请求
了解OpenTracing的inject和extract函数
функция вставки и извлечения
Это две функции для межпроцессной трассировки, стремящиеся найти общий метод передачи трассировки. Это две мощные функции, которые предоставляют ряд абстракций, чтобы протокол OpenTracing не был связан с конкретной реализацией.
Carrier 携带trace信息的载体,下文中将自定义一个
inject 将额外的信息`注入`到相应的载体中
extract 将额外的信息从载体中`提取`出来
На самом деле, большая часть этого носителя реализуется Map (в частности, текстовой картой) или другими бинарными методами.
В этой статье мы используем текстовую карту, а нижний слой носителя — это информация заголовка http (которую также можно передать через параметры запроса).
Создайте серверную часть
maven-зависимости
Во-первых, импортируйте соответствующую конфигурацию весенней загрузки через bom.
spring-boot-dependencies 2.1.3.RELEASE
Затем введите другие зависимости
opentracing-util 0.32.0
jaeger-client 0.35.0
logback-classic 1.2.3
spring-boot-starter-web 2.1.3.RELEASE
okhttp 3.14.1
Приложение SpringBoot
Создайте приложение SpringBoot, укажите порт 8888 и инициализируйте порт по умолчанию.Tracer
.
@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan(basePackages = { "com.sayhiai.example.jaeger.totorial03.controller",
})
public class App extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
@Bean
public JaegerTracer getJaegerTracer() {
return JaegerTracerHelper.initTracer("LoveYou");
}
}
Создайте простую службу в каталоге контроллера/hello
, передать параметры через тело запроса.
Код ключа следующий:
@PostMapping("/hello")
@ResponseBody
public String hello(@RequestBody String name,HttpServletRequest request) {
Map<String, String> headers = new HashMap<>();
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String header = headerNames.nextElement();
headers.put(header, request.getHeader(header));
}
System.out.println(headers);
Tracer.SpanBuilder builder = null;
SpanContext parentSpanContext = tracer.extract(Format.Builtin.HTTP_HEADERS, new TextMapAdapter(headers));
if (null == parentSpanContext) {
builder = tracer.buildSpan("hello");
} else {
builder = tracer.buildSpan("hello").asChildOf(parentSpanContext);
}
Span span = builder.start();
Сначала получите информацию о заголовке и продолжитеextract
, если получитьSpanContext
Если он не пуст, это означает, что текущий запрос инициирован другим приложением. В этом случае мы берем источник запроса как источник текущего запросаparent
.
Используйте Curl, чтобы позвонить, чтобы убедиться, что служба запущена и работает.
curl -XPOST http://localhost:8888/hello -H "Content-Type:text/plain;charset=utf-8" -d "小姐姐味道"
Создать клиентский вызов OkHttp3
Создать перевозчика
OkHttp3 — это очень легкая библиотека классов, информацию о ее заголовке можно установить с помощью следующего кода.
Request.Builder builder;
builder.addHeader(key, value);
Выше мы упоминали, что собираемся создать пользовательскийCarrier
, здесь по наследствуTextMap
, чтобы реализовать один.
public class RequestBuilderCarrier implements io.opentracing.propagation.TextMap {
private final Request.Builder builder;
RequestBuilderCarrier(Request.Builder builder) {
this.builder = builder;
}
@Override
public Iterator<Map.Entry<String, String>> iterator() {
throw new UnsupportedOperationException("carrier is write-only");
}
@Override
public void put(String key, String value) {
builder.addHeader(key, value);
}
}
позвонить
Используйте OkHttp3, чтобы инициировать простой запрос Post.
public static void main(String[] args) {
Tracer tracer = JaegerTracerHelper.initTracer("Main");
String url = "http://localhost:8888/hello";
OkHttpClient client = new OkHttpClient();
Request.Builder request = new Request.Builder()
.url(url)
.post(RequestBody.create(MediaType.parse("text/plain;charset=utf-8"), "小姐姐味道"));
Span span = tracer.buildSpan("okHttpMainCall").start();
Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_CLIENT);
Tags.HTTP_METHOD.set(span, "POST");
Tags.HTTP_URL.set(span, url);
tracer.activateSpan(span);
tracer.inject(span.context(), Format.Builtin.HTTP_HEADERS, new RequestBuilderCarrier(request));
client.newCall(request.build()).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
System.out.println(response.body().string());
}
});
span.finish();
}
Обратите внимание, что в середине метода мы используем функцию ввода, чтобы прикрепить информацию о трассировке кRequestBuilderCarrier
передача дальше.
Эти две функции используют реализацию jaeger. Видеть:
io.jaegertracing.internal.propagation.TextMapCodec
Запустим метод Main и посмотрим на предысторию Jaeger.Вы видите, что наша распределенная трассировка сгенерирована.
End
В этой статье показан общий способ создания распределенной цепочки вызовов. По аналогии с этим методом легко написатьHttpClient
Клиентский компонент компонента.
Далее мы будем использовать специальный Aop Spring для инкапсуляции службы SpringCloud, вызываемой через интерфейс Feign. Вы обнаружите, что реализация сборщика на стороне клиента, подобного Sleuth, довольно проста.