[英]Inconsistent latency values between Dropwizard metrics and JMeter in Netty server
我有一台Netty HTTP服务器,正在通过Apache JMeter发送请求进行测试。 我正在使用Dropwizard指标库来测量服务器上的延迟。 我遇到了Dropwizard指标存在问题的情况,该指标显示的延迟值与JMeter不同(平均和第99个百分位数),但有时只是这样。
该处理在使用ThreadPoolExecutor类创建的单独的线程池中进行。 但是,我用sleep语句替换了要在Test.java中完成的实际处理,因此我知道处理需要多长时间。
我的代码如下
LatencyTester.java
public class LatencyTester {
public static void main(String[] args) throws Exception {
Executors.newScheduledThreadPool(1);
displayMetrics.scheduleAtFixedRate(new Metrics(), 10, 10, TimeUnit.SECONDS);
new NettyServer().run();
}
}
NettyServer.java
public class NettyServer {
ThreadPoolExecutor executor;
public NettyServer() {
}
public void run() throws Exception {
executor = new ThreadPoolExecutor(7,7,100, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(), new ThreadPoolExecutor.CallerRunsPolicy());
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
Timer.Context context = Metrics.TIMER.time(); //Start Dropwizard metrics timer
ChannelPipeline p = ch.pipeline();
p.addLast(new HttpServerCodec());
p.addLast("aggregator", new HttpObjectAggregator(1048576));
p.addLast(new NettyServerHandler(executor, context));
}
}).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f = b.bind(15000).sync();
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
NettyServerHandler.java
public class NettyServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
private Future<ByteBuf> result;
private Timer.Context cntx;
private ThreadPoolExecutor threadPool;
public NettyServerHandler(ThreadPoolExecutor pool, Timer.Context cntx) {
this.cntx = cntx;
this.threadPool = pool;
}
@Override
public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
Test tst = new Test();
result = threadPool.submit(tst);
boolean keepAlive = HttpUtil.isKeepAlive(msg);
FullHttpResponse response = null;
response = new DefaultFullHttpResponse(HTTP_1_1, OK, result.get());
String contentType = msg.headers().get(HttpHeaderNames.CONTENT_TYPE);
if (contentType != null) {
response.headers().set(HttpHeaderNames.CONTENT_TYPE, contentType);
}
response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
if (!keepAlive) {
ctx.write(response).addListener(ChannelFutureListener.CLOSE);
} else {
response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
ctx.write(response);
}
ctx.flush();
cntx.stop(); //Stop Dropwizard metrics timer
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
Test.java
public class Test implements Callable<ByteBuf> {
public Test() {
}
@Override
public ByteBuf call() throws Exception {
TimeUnit.SECONDS.sleep(5);
return (Unpooled.copiedBuffer("Done".getBytes()));
}
}
这是在JMeter上进行一些测试(每次持续5分钟)后获得的一些结果。 服务器和JMeter都在我的笔记本电脑上运行。 下面的服务器线程是指NettyServer.java中为ThreadPoolExecutor实例设置的值(下面的延迟值以毫秒为单位)ServerThreads,JMeterThreads,MetricsAverage,Metrics99thP,JMeterAvg,JMeter99thP
1,1,5018,5167,5012,5031
1,7,33407,35165,33380,35003
5,17,15695,19998,16667,19970-平均相差1秒
50,50,8963,15032,15356,29959-大不同
7,23,11295,14965,16121,20002-大不同
为什么其中一些测试显示与JMeter和Metrics结果不一致? 我在启动和停止Dropwizard Metrics计时器的地方做错了吗?
我该怎么做才能在服务器端准确测量请求延迟,以便它们显示从接收请求到发送答复所花费的时间?
从服务器(此处为Netty)和客户端(分别为JMeter)的角度来看,延迟的设计完全不同,因此根本无法匹配。
不过,它们可能是客户端的延迟很可能包括服务器的延迟-因此,JMeter端的值将始终更大(显示的值只有平均值和百分位-那里的确如此)。
只需查看Jmeter的延迟定义:
延迟时间 。 JMeter测量从发送请求之前到收到第一个响应之后的延迟。 因此, 该时间包括组装请求以及组装响应的第一部分所需的所有处理 ,通常这将比一个字节长。 协议分析器(例如Wireshark)测量通过接口实际发送/接收字节的时间。 JMeter时间应该更接近浏览器或其他应用程序客户端所经历的时间。
看到?
服务器对客户端上发生的阶段了解为零(并计入延迟)。 它也不知道网络路径上正在发生什么。
结论:您所看到的完全是期望的。
UPD:有人指出,在边缘情况下,服务器端的一项测量超出了JMeter的一项。 这很有趣,在这里我试图解释这是怎么可能的。
首先免责声明 :我不知道您在那里使用的工具包的内在发生了什么(因此,如果我错过了,请不要用力打我)。
尽管在常识推理的帮助下,我可以猜测:
1)问题是您在冲洗后停止计时器。 那里似乎是同步的。
2)因此,服务器端的延迟测量包括缓冲区的全部刷新。
3)当JMeter测量直到第一块到达和组装的延迟。
4)在大多数情况下,服务器的刷新速度足够快,快于网络+ JMeter吞没它的速度。
5)但是在某些情况下,服务器或网络只是偶然发现了某些东西,而最后的数据块却迟到了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.