本文概览 :zuul也是基于servlet的,micrometer是基于servlet filter来收集指标的,所以可以通过micrometer可以收集网关zuul的请求指标,包括http状态为4xx、5xx的请求。
类似于MVC有一个DispatcherServerlet,zuul也有一个ZuulServerlet来映射所有的请求。对于java web都是基于serverlet来做的。
上面的流程对应的代码如下:
######### 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 的,如下代码:
由上zuul是基于servlet的,micrometer是基于servlet filter来收集指标的,所以可以通过micrometer可以收集网关zuul的请求指标,包括http状态为4xx、5xx的请求。
收集每个服务的流量、耗时、已经请求的http状态,即收集的服务维度信息,不是接口的信息。
gateway 服务部署参考 :
Spring Cloud GateWay-Netflix Zuul
1 、 maven 配置
<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
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 来收集指标数据,如下:
> 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/**
上面的 influxdb 的 uri 中,我们希望获取的每个服务 serviceId ,此时可以通过如下来完成:
1 、在前置 zuulFilter 中奖 serviceId 设置到 request 中
@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
@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 来收集指标数据,如下:
> 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