背景
最近由于生产用户数上増,需要对项目的网络连接池进行优化,故而需要知道gateway的一些连接池情况和负载情况,需要进行监控和统计,本文通过metrics进行统计
Gateway
使用的web容器
通过获取ConfigurableWebServerFactory
类可以知道当前springboot项目使用的是哪个容器,当前我们gateway使用的是webflux,也就是NettyReactiveWebServerFactory
ConfigurableWebServerFactory webServerFactory = applicationContext.getBean(ConfigurableWebServerFactory.class);
String type = webServerFactory.getClass().getSimpleName();
启动加载顺序
webflux使用的是响应式reactor,底层的连接池是用的reactor.netty.http.client.HttpClient
,在项目启动时会通过rg.springframework.cloud.gateway.configHttpClientFactory
创建我们的HttpClient实例,通过配置类生成对应的ConnectionProvider
@Override
protected HttpClient createInstance() {
// configure pool resources
ConnectionProvider connectionProvider = buildConnectionProvider(properties);
HttpClient httpClient = HttpClient.create(connectionProvider)
// TODO: move customizations to HttpClientCustomizers
.httpResponseDecoder(this::httpResponseDecoder);
if (serverProperties.getHttp2().isEnabled()) {
httpClient = httpClient.protocol(HttpProtocol.HTTP11, HttpProtocol.H2);
}
if (properties.getConnectTimeout() != null) {
httpClient = httpClient.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, properties.getConnectTimeout());
}
httpClient = configureProxy(httpClient);
httpClient = configureSsl(httpClient);
if (properties.isWiretap()) {
httpClient = httpClient.wiretap(true);
}
if (properties.isCompression()) {
httpClient = httpClient.compress(true);
}
httpClient = applyCustomizers(httpClient);
return httpClient;
}
可以看到会注入HttpClientProperties
,该配置类就对应了如下的配置
spring:
cloud:
gateway:
metrics:
tags:
path:
enabled: true
httpclient:
pool:
metrics: true
开启统计
要想对HttpClient进行统计,我们需要手动打开metrics配置
HttpClient httpClient = reactorNettyWebSocketClient.getHttpClient();
httpClient.metrics(true, s -> s);
通过任务进行如下输出,这样就能得到HttpClient网络负载情况
meterRegistry.forEachMeter(meter -> {
if (meter.getId().getName().contains("reactor") || meter.getId().getName().contains("http")) {
log.info("{} : {}", meter.getId(), meter.measure());
}
});
最后输出网络连接池的如下信息
MeterId{name='reactor.netty.connection.provider.idle.connections', tags=[tag(id=-407496790),tag(name=proxy),tag(remote.address=10.233.74.96:8000)]} : [Measurement{statistic='VALUE', value=5.0}]
MeterId{name='reactor.netty.connection.provider.active.connections', tags=[tag(id=2115103796),tag(name=proxy),tag(remote.address=10.233.68.199:8000)]} : [Measurement{statistic='VALUE', value=0.0}]
MeterId{name='reactor.netty.connection.provider.max.pending.connections', tags=[tag(id=2115103796),tag(name=proxy),tag(remote.address=10.233.68.199:8000)]} : [Measurement{statistic='VALUE', value=2.147483647E9}]
MeterId{name='http.server.requests', tags=[tag(exception=CancelledServerWebExchangeException),tag(method=POST),tag(outcome=UNKNOWN),tag(status=200),tag(uri=UNKNOWN)]} : [Measurement{statistic='COUNT', value=13.0}, Measurement{statistic='TOTAL_TIME', value=0.932510201}, Measurement{statistic='MAX', value=0.030078583}]
MeterId{name='http.server.requests', tags=[tag(exception=AbortedException),tag(method=POST),tag(outcome=UNKNOWN),tag(status=200),tag(uri=UNKNOWN)]} : [Measurement{statistic='COUNT', value=1.0}, Measurement{statistic='TOTAL_TIME', value=0.039492304}, Measurement{statistic='MAX', value=0.039492304}]
MeterId{name='http.server.requests', tags=[tag(exception=None),tag(method=POST),tag(outcome=SUCCESS),tag(status=200),tag(uri=UNKNOWN)]} : [Measurement{statistic='COUNT', value=866.0}, Measurement{statistic='TOTAL_TIME', value=97.363644466}, Measurement{statistic='MAX', value=1.589130715}]
MeterId{name='reactor.netty.connection.provider.total.connections', tags=[tag(id=2115103796),tag(name=proxy),tag(remote.address=10.233.68.199:8000)]} : [Measurement{statistic='VALUE', value=3.0}]
MeterId{name='reactor.netty.connection.provider.pending.connections', tags=[tag(id=-407496790),tag(name=proxy),tag(remote.address=10.233.74.96:8000)]} : [Measurement{statistic='VALUE', value=0.0}]
MeterId{name='reactor.netty.connection.provider.max.pending.connections', tags=[tag(id=-407496790),tag(name=proxy),tag(remote.address=10.233.74.96:8000)]} : [Measurement{statistic='VALUE', value=2.147483647E9}]
MeterId{name='reactor.netty.connection.provider.total.connections', tags=[tag(id=-407496790),tag(name=proxy),tag(remote.address=10.233.74.96:8000)]} : [Measurement{statistic='VALUE', value=5.0}] MeterId{name='reactor.netty.connection.provider.pending.connections', tags=[tag(id=2115103796),tag(name=proxy),tag(remote.address=10.233.68.199:8000)]} : [Measurement{statistic='VALUE', value=0.0}]
MeterId{name='reactor.netty.connection.provider.max.connections', tags=[tag(id=2115103796),tag(name=proxy),tag(remote.address=10.233.68.199:8000)]} : [Measurement{statistic='VALUE', value=2.147483647E9}]
MeterId{name='http.server.requests', tags=[tag(exception=None),tag(method=OPTIONS),tag(outcome=SUCCESS),tag(status=200),tag(uri=UNKNOWN)]} : [Measurement{statistic='COUNT', value=2.0}, Measurement{statistic='TOTAL_TIME', value=0.003759986}, Measurement{statistic='MAX', value=6.19719E-4}]
MeterId{name='reactor.netty.connection.provider.idle.connections', tags=[tag(id=2115103796),tag(name=proxy),tag(remote.address=10.233.68.199:8000)]} : [Measurement{statistic='VALUE', value=3.0}]
MeterId{name='reactor.netty.connection.provider.active.connections', tags=[tag(id=-407496790),tag(name=proxy),tag(remote.address=10.233.74.96:8000)]} : [Measurement{statistic='VALUE', value=0.0}]
MeterId{name='reactor.netty.connection.provider.max.connections', tags=[tag(id=-407496790),tag(name=proxy),tag(remote.address=10.233.74.96:8000)]} : [Measurement{statistic='VALUE', value=2.147483647E9}]
额外扩展点
gateway也有提供自己的统计实现,在GatewayMetricsAutoConfiguration
配置中,如果你想自定义扩展标签,可以通过配置该properties的属性
@Bean public PropertiesTagsProvider propertiesTagsProvider(GatewayMetricsProperties properties) { return new PropertiesTagsProvider(properties.getTags()); }