我正在迁移Thorntail(2.4.0.final)到Quarkus(1.11.1.final)。在测试阶段,我们注意到分布式跟踪不起作用。跟踪工作(单个组件跟踪),但是uber-trace-id没有与rest请求头一起传递,因此下一个微服务(rest请求的接收者)将在没有span信息的情况下从零生成跟踪。
在Thorntail中,它只是通过ClientBuilder上的配置来完成的
import org.eclipse.microprofile.opentracing.ClientTracingRegistrar;
import javax.ws.rs.client.ClientBuilder;
...
ClientBuilder clientBuilder = ClientBuilder.newBuilder();
...
ClientTracingRegistrar.configure(clientBuilder);
比较两者,我注意到有Thorntail可用的ClientTracingRegistrarProvider
public class ResteasyClientTracingRegistrarProvider implements ClientTracingRegistrarProvider {
public ResteasyClientTracingRegistrarProvider() {
}
public ClientBuilder configure(ClientBuilder clientBuilder) {
return this.configure(clientBuilder, Executors.newFixedThreadPool(10));
}
public ClientBuilder configure(ClientBuilder clientBuilder, ExecutorService executorService) {
ResteasyClientBuilder resteasyClientBuilder = (ResteasyClientBuilder)clientBuilder;
Tracer tracer = (Tracer)CDI.current().select(Tracer.class, new Annotation[0]).get();
return (ClientBuilder)resteasyClientBuilder.executorService(new TracedExecutorService(executorService, tracer)).register((new Builder(tracer)).withTraceSerialization(false).build());
}
}
附加信息:我们正在使用jaxrs API(javax.ws.rs)构建rest客户端,并使用依赖项构建应用程序:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-opentracing</artifactId>
</dependency>
提前感谢所有的建议和帮助。
通常的解决办法是这样的:我们有用于rest请求的预处理器和后处理器,它们通过org.jboss.logging.mdc将uber-trace-id存储在线程本地中
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>3.4.1.Final</version>
</dependency>
然后在rest客户端中,我们只使用这个线程本地值。
代码如下所示:预匹配是读取并存储ubraTraceId(如果存在于传入请求头中)
import java.nio.charset.StandardCharsets;
import javax.annotation.Priority;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.ext.Provider;
...
@Provider
@PreMatching
@Priority(1)
public class PreMatchingTraceIdRequestFilter implements ContainerRequestFilter {
...
@Override
public void filter(ContainerRequestContext containerRequestContext) {
// Remove uberTraceID from the logging context which can contain a previous request.
// Additionally done in ClearLoggingContextWriterInterceptor
LoggingUtil.clearContext();
String jaegerUberTraceID = decode(containerRequestContext.getHeaderString(HTTP_HEADER_UBER_TRACE_ID));
if (nonNull(jaegerUberTraceID)) {
LoggingUtil.setUberTraceId(jaegerUberTraceID);
//here some logging
}
// else case handled by the PostMatchingTraceIdRequestFilter later in the jax-rs request processing chain.
}
private static String decode(String headerString) {
return StringHelper.decode(String.valueOf(headerString), StandardCharsets.UTF_8.name());
}
}
import io.jaegertracing.internal.JaegerSpanContext;
import io.opentracing.Tracer;
import javax.annotation.Priority;
import javax.inject.Inject;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.ext.Provider;
import static java.util.Objects.nonNull;
@Provider
// IMPORTANT: don't give this filter a higher priority!
// Cannot be invoked earlier because the Jaeger Client has to initialize the span for this request first.
// Tests revealed that the span is not initialized yet if this filter is given a higher priority!
@Priority(Priorities.USER)
public class PostMatchingTraceIdRequestFilter implements ContainerRequestFilter {
private Tracer tracer;
@Inject
public void setTracer(Tracer tracer) {
this.tracer = tracer;
}
@Override
public void filter(ContainerRequestContext containerRequestContext) {
String jaegerUberTraceId = getJaegerUberTraceID();
if (nonNull(jaegerUberTraceId)) {
LoggingUtil.setUberTraceId(jaegerUberTraceId);
// here some logging
}
// No else since an missing active span on Tracer can happen more often than you think:
// using @Traced(false) for example suppresses the generation of a new span
}
private String getJaegerUberTraceID() {
String uberTraceId = null;
if (nonNull(tracer) && nonNull(tracer.activeSpan())) {
JaegerSpanContext spanContext = (JaegerSpanContext) tracer.activeSpan().context();
uberTraceId =
new StringBuilder()
.append(spanContext.getTraceId())
.append(UBER_TRACE_ID_SEPARATOR)
.append(decode(spanContext.getSpanId()))
.append(UBER_TRACE_ID_SEPARATOR)
.append(decode(spanContext.getParentId()))
.append(UBER_TRACE_ID_SEPARATOR)
.append(spanContext.getFlags())
.toString();
}
return uberTraceId;
}
private static String decode(long longValue) {
return Long.toHexString(longValue);
}
}
public static void clearContext() {
MDC.clear();
}
public static void setUberTraceId(String uberTraceId) {
MDC.put(MDC_UBER_TRACE_ID, StringUtils.defaultIfEmpty(uberTraceId, StringUtils.EMPTY));
}
public static String getUberTraceId() {
return (String) MDC.get(MDC_UBER_TRACE_ID);
}
public static String getUberTraceIdAndRemoveFromContext() {
final String traceId = getUberTraceId();
clearContext();
return traceId;
}
import javax.ws.rs.client.ClientBuilder;
import org.eclipse.microprofile.opentracing.ClientTracingRegistrar;
...
protected void addUberTraceIdHeader(Invocation.Builder builder) {
String uberTraceId = LoggingUtil.getUberTraceId();
if (isNotBlank(uberTraceId)) {
builder.header(TraceExtractor.HTTP_HEADER_UBER_TRACE_ID, uberTraceId);
} else {
throw new IllegalStateException("Lack of uber trace id");
}
}
我使用Quarkus Rest客户端与一个外部服务通信,该服务使用两个cookies来验证所有请求。这两个cookies是从身份验证API和每个后续API调用中返回的。有没有办法自动处理这些cookies?目前,我从身份验证API的响应对象获取cookies,并使用@CookieParam在每个请求中手动发送它们。
目标 这次我们学习轮廓的层次,即轮廓中的父子关系。 理论 在前几篇关于轮廓的文章中,我们已经讨论了与OpenCV提供的轮廓相关的几个函数。但是当我们使用cv.findcontour()函数在图像中找到轮廓时,我们已经传递了一个参数,轮廓检索模式。我们通常通过了cv.RETR_LIST或cv.RETR_TREE,效果很好。但这到底意味着什么呢? 另外,在输出中,我们得到了三个数组,第一个是图像,第二
对如何实现这一点有什么想法吗?我有一个编程解决方案,但更喜欢一个仅通过注释的解决方案
我想用一个用Kotlin编写并使用Vert的现有项目测试Quarkus和Docker的本机映像。x个竖线。 你能给我举一个关于如何使用Quarkus部署Verticle的例子吗? 我的依赖项是和。 我在Vert. x扩展测试中找到了一些例子,但是我找不到如何在服务器启动时部署我的Verticle。
主要内容:1. outline-style,2. outline-width,3. outline-color,4. outline,5. outline-offset轮廓(outline)是绘制于元素周围的一条线,位于边框的外围(紧贴着边框),主要用来突出显示某个元素,如下图所示: 图:轮廓(outline) 轮廓和边框看起来非常相似,但它们之间也并非没有区别,例如: 元素上下左右四个方向上边框的样式、宽度、颜色可以单独设置,而轮廓在元素四个方向的宽度、样式、颜色都是相同的,不能单独设置; 边
我有2个URL,其中1个特定于Dev,另一个特定于Prod。我也在使用Spring profiling,其中我有一个单独的文件用于Dev和Prod application-Dev。性能和应用-prod。属性和我的应用。对于Dev env,属性文件如下所示 spring.profiles.active=dev 现在在我的java代码中,我想有一个属性,它将根据我使用的Spring配置文件绑定到适当的