9.2.5 使用Zuul将关联ID添加到HTTP响应
如果读者检查使用Spring Cloud Sleuth进行服务调用所返回的HTTP响应,永远不会看到在调用中使用的跟踪ID在HTTP响应首部中返回。通过查阅Spring Cloud Sleuth的文档,就会得知Spring Cloud Sleuth团队认为返回的跟踪数据可能是一个潜在的安全问题(尽管他们没有明确列出理由)。
然而,我发现,在调试问题时,在HTTP响应中返回关联ID或跟踪ID是非常重要的。Spring Cloud Sleuth允许开发人员使用其跟踪ID和跨度ID“装饰”HTTP响应信息。然而,这种做法涉及编写3个类并注入两个定制的Spring bean。如果读者想采取这种方法,可以查阅Spring Cloud Sleuth文档。一个更简单的解决方案是编写一个将在HTTP响应中注入跟踪ID的Zuul后置过滤器。
在第6章介绍Zuul API网关时,我们看到了如何构建一个Zuul后置响应过滤器,将生成的用于服务的关联ID添加到调用者返回的HTTP响应中。我们现在要修改这个过滤器以添加Spring Cloud Sleuth首部。
要创建Zuul响应过滤器,需要将JAR依赖项spring-cloud-starter-sleuth添加到Zuul服务器的pom.xml文件中。spring-cloud-starter-sleuth依赖项用于告诉Spring Cloud Sleuth,希望Zuul参与Spring Cloud跟踪。在本章稍后介绍Zipkin时,读者会看到Zuul服务将成为所有服务调用中的第一个调用。
对于第9章,这个文件可以在zuulsvr/pom.xml中找到。代码清单9-1展示了这些依赖项。
代码清单9-1 将Spring Cloud Sleuth添加到Zuul
<dependency>
<groupId>org.springframework.cloud</groupId>
⇽--- 向Zuul添加spring-cloud-starter-sleuth会让在Zuul中调用的每个服务生成一个跟踪ID
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
添加完新的依赖项,实际的Zuul后置过滤器就很容易实现了。代码清单9-2展示了用于构建Zuul过滤器的源代码。该代码在zuulsvr/src/main/java/com/thoughtmechanix/zuulsvr/filters/ ResponseFilter.java中。
代码清单9-2 通过Zuul后置过滤器添加Spring Cloud Sleuth的跟踪ID
@Component
public class ResponseFilter extends ZuulFilter{
private static final int FILTER_ORDER=1;
private static final boolean SHOULD_FILTER=true;
private static final Logger logger = LoggerFactory.getLogger(ResponseFilter.class);
⇽--- Tracer类是访问跟踪ID和跨度ID信息的入口点
@Autowired
Tracer tracer;
@Override
public String filterType() {
return "post";
}
@Override
public int filterOrder() {
return FILTER_ORDER;
}
@Override
public boolean shouldFilter() {
return SHOULD_FILTER;
}
⇽--- 添加新HTTP响应首部tmx-correlation-id,它包含Spring Cloud Sleuth的跟踪ID
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
ctx.getResponse().addHeader("tmx-correlation-id", tracer.getCurrentSpan().traceIdString());
return null;
}
}
因为Zuul现在已经启用了Spring Cloud Sleuth,所以可以通过自动装配Tracer类到ResponseFilter从ResponseFilter中访问跟踪信息。Tracer类可用于访问正在执行的当前Spring Cloud Sleuth跟踪信息。tracer.getCurrentSpan().traceIdString()方法以字符串的形式检索当前正在进行的事务的跟踪ID。
将跟踪ID添加到通过Zuul的传出HTTP响应是很简单的。这一步骤通过调用以下代码来完成:
RequestContext ctx = RequestContext.getCurrentContext(); ctx.getResponse().addHeader("tmx-correlation-id", ➥ tracer.getCurrentSpan().traceIdString());
有了这段代码,如果通过Zuul网关调用了一个EagleEye微服务,那么应该会得到一个名为tmx-correlation-id的HTTP响应首部。图9-10展示了调用GET http://localhost:5555/api/licensing/v1/organizations/e254f8c-c442-4ebe-a82a- e2fc1d1ff7-8a/licenses/f3831f8c-c338-4ebe-a82a-e2fc1d1ff78a的结果。
图9-10 随着Spring Cloud Sleuth的跟踪ID的返回,可以轻松地向Papertrail查询日志