本文概览:zuul也是基于servlet的,micrometer是基于servlet filter来收集指标的,所以可以通过micrometer可以收集网关zuul的请求指标,包括http状态为4xx、5xx的请求。
1 zuul流程
类似于MVC有一个DispatcherServerlet,zuul也有一个ZuulServerlet来映射所有的请求。对于java web都是基于serverlet来做的。
上面的流程对应的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
######### ZuulServlet.java ######### @Override public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException { try { init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse); // Marks this request as having passed through the "Zuul engine", as opposed to servlets // explicitly bound in web.xml, for which requests will not have the same data attached RequestContext context = RequestContext.getCurrentContext(); context.setZuulEngineRan(); try { preRoute(); } catch (ZuulException e) { error(e); postRoute(); return; } try { route(); } catch (ZuulException e) { error(e); postRoute(); return; } try { postRoute(); } catch (ZuulException e) { error(e); return; } } catch (Throwable e) { error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName())); } finally { RequestContext.getCurrentContext().unset(); } } |
spring cloud zuul starter是如何来初始化这个servlet的,如下代码:
2 使用Micrometer收集zuul指标
由上zuul是基于servlet的,micrometer是基于servlet filter来收集指标的,所以可以通过micrometer可以收集网关zuul的请求指标,包括http状态为4xx、5xx的请求。
2.1 收集那些指标
收集每个服务的流量、耗时、已经请求的http状态,即收集的服务维度信息,不是接口的信息。
2.2 引入Micrometer
gateway服务部署参考 :
1、maven配置
1 2 3 4 5 6 7 8 9 10 11 |
<dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-spring-legacy</artifactId> <version>1.0.4</version> </dependency> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-influx</artifactId> <version>1.0.4</version> </dependency> |
2、properties
1 2 3 4 5 6 7 8 9 10 |
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ server.port=8763 spring.application.name=gateway eureka.instance.status-page-url=http://localhost:${server.port}/swagger-ui.html management.security.enabled=false zuul.routes.service-prodvider1:/provider1/** ### influx配置 management.metrics.export.influx.uri = http://127.0.0.1:8086 management.metrics.export.influx.db=gateway |
3、启动gateway,通过访问http://localhost:8763/provider1/query 来收集指标数据,如下:
1 2 3 4 5 6 |
> select * from http_server_requests where time >1574727059812000000 name: http_server_requests time count exception mean method metric_type status sum upper uri ---- ----- --------- ---- ------ ----------- ------ --- ----- --- 1592736244867000000 22 None 90.69927 GET histogram 200 1995.383941 1690.46626 /provider1/** 1592736304862000000 0 None 0 GET histogram 200 0 1690.46626 /provider1/** |
2.3 改进Micrometer指标收集
上面的influxdb的uri中,我们希望获取的每个服务serviceId,此时可以通过如下来完成:
1、在前置zuulFilter中奖serviceId设置到request中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
@Component public class MicrommeterFilter extends ZuulFilter { // 前置过滤器 @Override public String filterType() { return FilterConstants.PRE_TYPE; } // 过滤器顺序,保证在PreDecorationFilter之后 @Override public int filterOrder() { return 30; } // 是否需要执行过滤器 @Override public boolean shouldFilter() { return true; } // 将serviceId信息保存到httpRequst中 @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); String serviceId = (String) ctx.get(SERVICE_ID_KEY); HttpServletRequest request = ctx.getRequest(); request.setAttribute(SERVICE_ID_KEY, serviceId); return null; } } |
2、 从request的attribute中获取serviceId,复写DefaultWebMvcTagsProvider
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
@Component @Primary public class ZuulTagProviders implements WebMvcTagsProvider { public Iterable<Tag> httpLongRequestTags(@Nullable HttpServletRequest request, @Nullable Object handler) { return Arrays.asList(WebMvcTags.method(request), WebMvcTags.uri(request, null)); } /** * 要手机哪些字段信息 * * @param request The HTTP request. * @param response The HTTP response. * @param ex The current exception, if any * @return A set of tags added to every Spring MVC HTTP request. */ public Iterable<Tag> httpRequestTags(@Nullable HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Object handler, @Nullable Throwable ex) { return Arrays.asList(WebMvcTags.method(request), getUriTag(request), WebMvcTags.exception(ex), WebMvcTags.status(response)); } private Tag getUriTag(HttpServletRequest request) { String serviceId = (String) request.getAttribute(SERVICE_ID_KEY); return Tag.of("uri", serviceId); } } |
3、启动gateway,通过访问http://localhost:8763/provider1/query 来收集指标数据,如下:
1 2 3 4 5 |
> select * from http_server_requests name: http_server_requests time count exception mean method metric_type status sum upper uri ---- ----- --------- ---- ------ ----------- ------ --- ----- --- 1592846243116000000 0 None 0 GET histogram 200 0 1063.062228 service-prodvider1 |