苍山做网站,修改wordpress版权连接,平台网站建设所需资质,广州海珠做网站前言
在4. 分布式链路追踪客户端工具包Starter设计一文中#xff0c;我们实现了基础的Starter包#xff0c;里面提供了我们自己定义的Servlet过滤器和RestTemplate拦截器#xff0c;其中Servlet过滤器叫做HoneyTracingFilter#xff0c;仅提供了提取SpanContext#xff0…前言
在4. 分布式链路追踪客户端工具包Starter设计一文中我们实现了基础的Starter包里面提供了我们自己定义的Servlet过滤器和RestTemplate拦截器其中Servlet过滤器叫做HoneyTracingFilter仅提供了提取SpanContext创建Span和开启Span的基础功能所以本文将围绕如何增强Servlet过滤器展开讨论。
相关版本依赖如下。
opentracing-api版本0.33.0 opentracing-spring-web版本4.1.0 jaeger-client版本1.8.1 Springboot版本2.7.6
github地址honey-tracing
正文
一. Opentracing提供的TracingFilter
其实最简单的增强方式就是使用TracingFilter来替换我们自己实现的HoneyTracingFilter下面给出TracingFilter的源码实现。
Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)throws IOException, ServletException {HttpServletRequest httpRequest (HttpServletRequest) servletRequest;HttpServletResponse httpResponse (HttpServletResponse) servletResponse;if (!isTraced(httpRequest, httpResponse)) {chain.doFilter(httpRequest, httpResponse);return;}if (servletRequest.getAttribute(SERVER_SPAN_CONTEXT) ! null) {chain.doFilter(servletRequest, servletResponse);} else {SpanContext extractedContext tracer.extract(Format.Builtin.HTTP_HEADERS,new HttpServletRequestExtractAdapter(httpRequest));final Span span tracer.buildSpan(httpRequest.getMethod()).asChildOf(extractedContext).withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER).start();httpRequest.setAttribute(SERVER_SPAN_CONTEXT, span.context());for (ServletFilterSpanDecorator spanDecorator: spanDecorators) {spanDecorator.onRequest(httpRequest, span);}try (Scope scope tracer.activateSpan(span)) {chain.doFilter(servletRequest, servletResponse);if (!httpRequest.isAsyncStarted()) {for (ServletFilterSpanDecorator spanDecorator : spanDecorators) {spanDecorator.onResponse(httpRequest, httpResponse, span);}}} catch (Throwable ex) {for (ServletFilterSpanDecorator spanDecorator : spanDecorators) {spanDecorator.onError(httpRequest, httpResponse, ex, span);}throw ex;} finally {if (httpRequest.isAsyncStarted()) {httpRequest.getAsyncContext().addListener(new AsyncListener() {Overridepublic void onComplete(AsyncEvent event) throws IOException {HttpServletRequest httpRequest (HttpServletRequest) event.getSuppliedRequest();HttpServletResponse httpResponse (HttpServletResponse) event.getSuppliedResponse();for (ServletFilterSpanDecorator spanDecorator: spanDecorators) {spanDecorator.onResponse(httpRequest,httpResponse,span);}span.finish();}Overridepublic void onTimeout(AsyncEvent event) throws IOException {HttpServletRequest httpRequest (HttpServletRequest) event.getSuppliedRequest();HttpServletResponse httpResponse (HttpServletResponse) event.getSuppliedResponse();for (ServletFilterSpanDecorator spanDecorator : spanDecorators) {spanDecorator.onTimeout(httpRequest,httpResponse,event.getAsyncContext().getTimeout(),span);}}Overridepublic void onError(AsyncEvent event) throws IOException {HttpServletRequest httpRequest (HttpServletRequest) event.getSuppliedRequest();HttpServletResponse httpResponse (HttpServletResponse) event.getSuppliedResponse();for (ServletFilterSpanDecorator spanDecorator: spanDecorators) {spanDecorator.onError(httpRequest,httpResponse,event.getThrowable(),span);}}Overridepublic void onStartAsync(AsyncEvent event) throws IOException {}});} else {span.finish();}}}
}
通过阅读TracingFilter源码我们可以得到如下几种扩展增强。
Servlet自身的urlPatterns机制。可以通过配置urlPatterns决定哪些请求需要打印链路信息TracingFilter的skipPattern机制。可以通过配置skipPattern决定哪些请求不需要打印链路信息装饰器ServletFilterSpanDecorator。可以提供ServletFilterSpanDecorator给到TracingFilter这样在收到请求返回响应和处理异常时均可以做一些扩展操作
二. urlPatterns和skipPattern设计
在第一节中得到的TracingFilter的几种增强其中第1和第2点的urlPatterns和skipPattern可以提供出来供用户配置本节对这部分进行实现。
首先是配置属性类里面需要加入urlPatterns和skipPattern的配置属性如下所示。
* 分布式链路追踪配置属性类。*/
ConfigurationProperties(honey.tracing)
public class HoneyTracingProperties {private boolean enabled;private HttpUrlProperties httpUrl new HttpUrlProperties();public boolean isEnabled() {return enabled;}public void setEnabled(boolean enabled) {this.enabled enabled;}public HttpUrlProperties getHttpUrl() {return httpUrl;}public void setHttpUrl(HttpUrlProperties httpUrl) {this.httpUrl httpUrl;}public static class HttpUrlProperties {* 按照/url1,/url2这样配置。*/private String urlPattern /*;* 按照/url1|/honey.*这样配置。*/private String skipPattern ;public String getUrlPattern() {return urlPattern;}public void setUrlPattern(String urlPattern) {this.urlPattern urlPattern;}public String getSkipPattern() {return skipPattern;}public void setSkipPattern(String skipPattern) {this.skipPattern skipPattern;}}}
然后注册过滤器的配置类HoneyTracingFilterConfig需要做如下修改。
* Servlet过滤器配置类。*/
Configuration
AutoConfigureAfter(HoneyTracingConfig.class)
public class HoneyTracingFilterConfig {Autowiredprivate HoneyTracingProperties honeyTracingProperties;Beanpublic FilterRegistrationBeanTracingFilter honeyTracingFilter(Tracer tracer) {String urlPattern honeyTracingProperties.getHttpUrl().getUrlPattern();String skipPatternStr honeyTracingProperties.getHttpUrl().getSkipPattern();Pattern skipPattern Pattern.compile(skipPatternStr);FilterRegistrationBeanTracingFilter registrationBean new FilterRegistrationBean();registrationBean.addUrlPatterns(urlPattern);registrationBean.setOrder(Integer.MIN_VALUE);registrationBean.setFilter(new TracingFilter(tracer, new ArrayList(), skipPattern));return registrationBean;}}
三. TracingFilter的装饰器设计
通过为TracingFilter注册ServletFilterSpanDecorator装饰器可以让我们在收到请求返回响应和处理异常时做一些扩展操作例如记录请求urlapi和返回码等下面实现一个装饰器HoneyServletFilterSpanDecorator其提供如下几个功能。
收到请求时记录
请求的host请求的api。
返回响应时记录
响应码。
处理异常时记录
响应码。
实现如下。
* {link TracingFilter}的装饰器。*/
public class HoneyServletFilterSpanDecorator implements ServletFilterSpanDecorator {Overridepublic void onRequest(HttpServletRequest httpServletRequest, Span span) {span.setTag(FIELD_HOST, getHostFromRequest(httpServletRequest));span.setTag(FIELD_API, httpServletRequest.getRequestURI());}Overridepublic void onResponse(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Span span) {span.setTag(FIELD_HTTP_CODE, httpServletResponse.getStatus());}Overridepublic void onError(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Throwable exception, Span span) {span.setTag(FIELD_HTTP_CODE, httpServletResponse.getStatus());}Overridepublic void onTimeout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, long timeout, Span span) {}private String getHostFromRequest(HttpServletRequest httpServletRequest) {return httpServletRequest.getScheme() :// httpServletRequest.getServerName() : httpServletRequest.getServerPort();}}
相关的常量字段记录在CommonConstants中如下所示。
public class CommonConstants {public static final double DEFAULT_SAMPLE_RATE 1.0;public static final String HONEY_TRACER_NAME HoneyTracer;public static final String HONEY_REST_TEMPLATE_NAME HoneyRestTemplate;public static final String FIELD_HOST host;public static final String FIELD_API api;public static final String FIELD_HTTP_CODE httpCode;}
在注册TracingFilter时需要将HoneyServletFilterSpanDecorator设置给TracingFilter对应的配置类HoneyTracingFilterConfig修改如下。
* Servlet过滤器配置类。*/
Configuration
AutoConfigureAfter(HoneyTracingConfig.class)
public class HoneyTracingFilterConfig {Autowiredprivate HoneyTracingProperties honeyTracingProperties;Beanpublic FilterRegistrationBeanTracingFilter honeyTracingFilter(Tracer tracer,ListServletFilterSpanDecorator decorators) {String urlPattern honeyTracingProperties.getHttpUrl().getUrlPattern();String skipPatternStr honeyTracingProperties.getHttpUrl().getSkipPattern();Pattern skipPattern Pattern.compile(skipPatternStr);FilterRegistrationBeanTracingFilter registrationBean new FilterRegistrationBean();registrationBean.addUrlPatterns(urlPattern);registrationBean.setOrder(Integer.MIN_VALUE);registrationBean.setFilter(new TracingFilter(tracer, decorators, skipPattern));return registrationBean;}Beanpublic ServletFilterSpanDecorator honeyServletFilterSpanDecorator() {return new HoneyServletFilterSpanDecorator();}}
至此我们就使用装饰器装饰了TracingFilter效果就是最终在TracingFilter调用到Span的finish() 方法时我们可以从Span的tags中拿到本次请求的hostapi和httpCode这些数据可以最终在打印链路日志时使用。
最后给出工程目录结构图。 总结
本文在4. 分布式链路追踪客户端工具包Starter设计的基础上使用TracingFilter替换了我们自己实现的HoneyTracingFilter并且基于urlPatternsskipPattern和装饰器进行了扩展增强。