本文概览: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 | 






