转载

Spring Cloud Zuul使用Micrometer收集指标

本文概览 :zuul也是基于servlet的,micrometer是基于servlet filter来收集指标的,所以可以通过micrometer可以收集网关zuul的请求指标,包括http状态为4xx、5xx的请求。

1 zuul流程

类似于MVC有一个DispatcherServerlet,zuul也有一个ZuulServerlet来映射所有的请求。对于java web都是基于serverlet来做的。

Spring Cloud Zuul使用Micrometer收集指标

上面的流程对应的代码如下:

    #########
    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 的,如下代码:

Spring Cloud Zuul使用Micrometer收集指标

2 使用 Micrometer收集zuul指标

由上zuul是基于servlet的,micrometer是基于servlet filter来收集指标的,所以可以通过micrometer可以收集网关zuul的请求指标,包括http状态为4xx、5xx的请求。

2.1 收集那些指标

收集每个服务的流量、耗时、已经请求的http状态,即收集的服务维度信息,不是接口的信息。

2.2  引入 Micrometer

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/**

2.3  改进 Micrometer 指标收集

上面的 influxdburi 中,我们希望获取的每个服务 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
原文  http://www.heartthinkdo.com/?p=3043
正文到此结束
Loading...