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