public class ServerVerticle extends Verticle {
@Override
public void start() throws Exception {
HttpServer server = vertx.createHttpServer();
RouteMatcher route = new RouteMatcher();
route.get("/", new Handler<HttpServerRequest>() {
@Override
public void handle(HttpServerRequest req) {
req.response.statusCode=200;
req.response.end();
}
});
server.requestHandler(route);
server.listen(8080);
}
}Requests per second: 10960.33 [#/sec] (mean)
Time per request: 36.495 [ms] (mean)
public class ServerVerticle extends Verticle {
@Override
public void start() throws Exception {
HttpServer server = vertx.createHttpServer();
RouteMatcher route = new RouteMatcher();
route.get("/", new Handler<HttpServerRequest>() {
@Override
public void handle(final HttpServerRequest req) {
vertx.setTimer(100, new Handler<Long>() {
@Override
public void handle(Long timerId) {
req.response.statusCode = 200;
req.response.end();
}
});
}
});
server.requestHandler(route);
server.listen(8080);
}
}Requests per second: 2246.05 [#/sec] (mean)
Time per request: 178.090 [ms] (mean)
Percentage of the requests served within a certain time (ms)
50% 123
66% 128
75% 133
80% 137
90% 152
95% 341
98% 1122
99% 1130
100% 3133 (longest request)
apr_socket_recv: Connection reset by peer (104)
--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To view this discussion on the web, visit https://groups.google.com/d/msg/vertx/-/19FNWhW6884J.
To unsubscribe from this group, send email to vertx+unsubscribe@googlegroups.com.
We have a timing requirement for each request:
Every request must return before a certain time, say, 200ms,
if at that time no recipient have returned, we need to return some default value.
I have no idea how else can I meet this requirement
锟斤拷 2012锟斤拷6锟斤拷21锟斤拷锟斤拷锟斤拷锟斤拷UTC+8锟斤拷锟斤拷3时51锟斤拷31锟诫,Tim Fox写锟斤拷锟斤拷
A quick question - what's the reason you are setting so many timers - are you trying to simulate the processing time of the request?
Is this something you would be doing in real-life?
Cheers
On 21/06/2012 08:41, Tim Fox wrote:
I'll take a look tomorrow (I'm out today)
To view this discussion on the web, visit https://groups.google.com/d/msg/vertx/-/gJl6S86dAP0J.
To post to this group, send an email to ve...@googlegroups.com.
To unsubscribe from this group, send email to vertx+un...@googlegroups.com.
Requests per second: 7989.97 [#/sec] (mean)
Time per request: 62.578 [ms] (mean)
Requests per second: 7145.44 [#/sec] (mean)
Time per request: 139.949 [ms] (mean)
Requests per second: 6398.20 [#/sec] (mean)
Time per request: 312.588 [ms] (mean)
--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To view this discussion on the web, visit https://groups.google.com/d/msg/vertx/-/gnEN68il-1gJ.
you mean the remote recipient in step #2 ? No. Those are the servers of our business clients. We can not control their behavior. All I can do is set a timeout on my HttpClientRequest, which communicates with them.
My problem is that I don't have the knowledge of the internals of vert.x, netty and NIO. I'm a newbie on these things.
Another thing that I found today is that even in the simplest server (the one that returns 200 OK), when I set ApacheBench's concurrent level higher, the average request time will increase
ab -n 100000 -c 500 http://localhost:8070/Requests per second: 7989.97 [#/sec] (mean)
Time per request: 62.578 [ms] (mean)ab -n 100000 -c 2000 http://localhost:8070/
ab -n 100000 -c 1000 http://localhost:8070/Requests per second: 7145.44 [#/sec] (mean)
Time per request: 139.949 [ms] (mean)
Requests per second: 6398.20 [#/sec] (mean)
Time per request: 312.588 [ms] (mean)
I don't know whether the concurrent level in AB reflects actual situations, but I definitely can't pass the team review with these number. Lighttpd on the same machine does'nt have this problem.
Some initial observations (more will follow):1) I've been playing with ab this morning. AIUI it doesn't support pipelining (bad), and, by default, it creates and tears down a new TCP connection for every message sent (bad). Are your clients really doing this? Connection setup and teardown is clearly going to be much slower than re-using the same connection.
2) Regarding timeouts: If you set a timeout of 100 ms, after which you send a response, then the next request won't be read on the server until the previous response has been written. If we did this otherwise it would mean you could write responses in the wrong order which would break the HTTP protocol.So for one connection, that means you can never get more than 1000 / timeout requests second = 10 req/s for a timeout of 100 ms.If you have 400 connections you could get a maximum of 400 * 10 = 4000 req/s which is pretty close to what I see when I run it here.
Sorry for the late response, I was on vacation the last three days.
First, regards to -instances, I've tried with 2, 4, 8 and 16, seems not much difference. I conceived that the bottleneck in the benchmark is not CPU, so more cores does not help here.Some initial observations (more will follow):1) I've been playing with ab this morning. AIUI it doesn't support pipelining (bad), and, by default, it creates and tears down a new TCP connection for every message sent (bad). Are your clients really doing this? Connection setup and teardown is clearly going to be much slower than re-using the same connection.
As for pipelining, I have tested 200 OK benchmark with HttpPerfClient, and results is good. So pipelining is going to help here. But in our really production environment there won't be pipelining, with all requests coming from the browsers. And most browsers don't have pipelining enabled by default.
As for keep-alive, I'll try that later and report back. I think it is really a reason here :)
Thanks for the tip.
2) Regarding timeouts: If you set a timeout of 100 ms, after which you send a response, then the next request won't be read on the server until the previous response has been written. If we did this otherwise it would mean you could write responses in the wrong order which would break the HTTP protocol.So for one connection, that means you can never get more than 1000 / timeout requests second = 10 req/s for a timeout of 100 ms.If you have 400 connections you could get a maximum of 400 * 10 = 4000 req/s which is pretty close to what I see when I run it here.
That is the real meat here. That explains the drastic drop of throughput. So this means if we set a timer in the process, then is is not a really async process anymore?
What if I do not use a timer, but send a message vie the event bus, and do the response after I receive a message from the event bus, Is that also blocked ?
My question is : Is there a way that I can do this otherwise? Our requests are independent and do not care about the order.
And most of them is very small, so no need to do http chunking (no multiple request send for each real request). Can I somehow disable the ordering for this scenario?
So if I don't use a setTimer, but use event bus and HttpClientRequest.setTimout (which is not there yet), can I make it real async?
--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To view this discussion on the web, visit https://groups.google.com/d/msg/vertx/-/AZtjyKwNwYcJ.
As promised here is a summary of my findings / observations1. Connection per request.You are creating a new TCP connection for every request that is sent. This is going to be slow - setting up a TCP connection requires a 3 way handshake at minimum (that's three trips across the network). By doing this you're really benchmarking the speed of your network (or loopback), not the server ;)
2. Slow connection time.You observed that connection times are sometimes slow (around 3000 ms), I replicated this too using a raw Netty program with no Vert.x involved. I spent a few days looking into this at a low level with Wireshark.What's happening on the TCP level is something like this. With the TCP connect handshake the client first sends a SYN packet to the server, the server replies with a SYN-ACK packet, and then the client replies to that with an ACK packet. I observed that some packets weren't being replied to by the server, so the client eventually sent them after a timeout. The default SYN resend timeout on Linux happens to be 3000 ms.This appears to be because the accept queue for TCP connections in the process of being setup has been exceeded. This occurs because ab is a slow single threaded client and can't handle that many setups fast enough.To fix this you need to do 3 things (10000 is just an arbitrarily high number I chose)a) sudo sysctl -w net.core.somaxconn=10000b) sudo sysctl -w net.ipv4.tcp_max_syn_backlog=10000c)HttpServer server = vertx.createHttpServer();server.setAcceptBacklog(10000);Just increasing the backlog in Java is *not* sufficient on Linux systems (and probably on other *nixes)Once you've done that you should find that the longest connection setup times reported are much shorter.
3) Adding a timeout of 100ms for each request reduces throughput.This is to be expected.You are creating a new connection for each request. And Apache bench with a concurrency level of 400 will have no more than 400 connections open at any one time.What's happening is this:a) Create a connectionb) Send a requestc) Request received on server, timeout is setd) 100ms later timeout fires, and response is written.e) Connection is closed.Since you have at most 400 connections at any one time, and each connection handles a single request, and each request-response takes *at least* 100ms, then that means you will have a maximum theoretical throughput of:T = 400 * (1000/100) = 4000 requests / per secGoing faster than that would break the laws of physics.This does not take into account the time for the three way handshake so the actual throughput will be somewhat less than this.The actual figure I observe on my desktop is:Requests per second: 3265.87 [#/sec] (mean)
"if you set a timeout of 100 ms, after which you send a response, then the next request won't be read on the server until the previous response has been written".
Yes, if you are calling response.end when you get a reply, then the
connection will be "blocked" (actually nothing is blocked but nothing
will be read from the connection) until you call response.end
Is most of the time being spent in connection?
I would expect connection time to degrade linearly with number of connections using ab since it is single threaded. I.e. that single thread has to handle more connections so it will take longer. Using a multi-threaded client might help, but testing this properly is going to be hard - you will need many clients on different machines to the server. Putting clients on the same machine as the server is going to steal cpu cycles from the server and so not give you fair results.
But fundamentally a single server will only be able to handle X connection attempts per second. So increasing number of connections / second is going to increase accept queue size and therefore average connection time. This will be true for any server.The way to mitigate that would be to calculate your maximum acceptable connect time, and then given the maximum number of connections you expect, you can work out how many servers you will need to satisfy that.
What you are measuring here is not the number of connections, but the
number of *connects* per second (i.e. a rate). Vert.x can handle many
thousands of concurrent connections, but can only handle (like any
server) a lower number of connects per second.
If you disable timeouts on the server, and put your server on a real
production machine with several instances, tune TCP then fire many
clients (on different machines) at it, you should be able to measure how
many connects per second the server can handle within your allowable time.
What you are measuring here is not the number of connections, but the
number of *connects* per second (i.e. a rate). Vert.x can handle many
thousands of concurrent connections, but can only handle (like any
server) a lower number of connects per second.
If you disable timeouts on the server, and put your server on a real
production machine with several instances, tune TCP then fire many
clients (on different machines) at it, you should be able to measure how
many connects per second the server can handle within your allowable time.
OK, I misused the unit 'connection', from now on I'll use connects per second (CPS?)
The 1000 I mentioned was meaning : If I use AB with -c 1000, in which case, there are about 1000 connections active (because AB starts a new connection only after the last one finishes),
then the average response time is good. If I set -c more than 1000, it will become bad.
I now know AB does not detect the really situation. I'll get the environment later and try with the method you mentioned :)
--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To view this discussion on the web, visit https://groups.google.com/d/msg/vertx/-/e0vmpG7u-z4J.