0

Currently on application startup I'm deploying a single verticle and calling createHttpServer(serverOptions).

I've set up a request().connection().closeHandler for handling a closed connection event, primarily so when clients decide to cancel their request, we halt our execution of that request.

However, when I set up that handler in that same verticle, it only seems to execute the closeHandler code once any synchronous code is finished executing and we're waiting on databases to respond via Futures and asynchronous handlers.

If instead of that, I deploy a worker verticle for each new HTTP request, it properly interrupts execution to execute the closeHandler code.

As I understand it, the HttpServer is already supposed to handle scalability of requests on its own since it can handle many at once without deploying new verticles. Essentially, this sounds like a hacky workaround that may affect our thread loads or things of that nature once our application is in full swing. So my questions are:

Is this the right way of doing this?

If not, what is the correct method or paradigm to follow?

How do you cancel the execution of a verticle from within itself verticle and inside that closeHandler? And by cancel execution, I mean including any Futures waiting to be completed.

Why does closeHandler only execute asynchronously when doing this multiple verticle approach? Using the normal way and simply executing requests using the alloted thread pool postpones closeHandler's execution until the eventloop finishes its queue, we need this to happen asynchronously

  • Does this answer your question? [How do I make a Vertx handler execute earlier in eventloop?](https://stackoverflow.com/questions/66822091/how-do-i-make-a-vertx-handler-execute-earlier-in-eventloop) – Alexey Soshin Apr 09 '21 at 21:58
  • Sorry no, one solution to that post is actually the implementation I've discussed on this post. Now my issue is halting verticle execution, but it seems this is all done via an undeploy call. This implementation just seems hacky so I wanted some clarification. – guy_who_can't_code Apr 10 '21 at 07:06

2 Answers2

1

I think you need to understand Vert.x better. Vert.x does not start and stop thread per request. Verticles are long living and each handle multiple events during their lifetime but never concurrently. Also you should not deploy worker (or non-worker) Verticles per request.

What you do is that you deploy a pool of Verticles (worker and non) and Vert.x divides the load between them. An HTTP server is placed in front and will receive requests and forward them to verticle(s) to be handled.

for stopping processing a request, you need to keep a flag somewhere which is set if connection is closed. then you can check for it in your process and stop processing. Just don't forget to clear the flag at beginning of each request.

mohamnag
  • 2,709
  • 5
  • 27
  • 40
  • I definitely am very green to vertx! However, this doesn't quite solve why my closeHandler (the thing that is updating that flag variable you're talking about) only executes after all of the synchronous code for that request has executed. It only properly executes as a nearly real-time event when I give that request its own verticle. Also worth noting, my app is crazy fast with this new verticle approach but I assume it's also heavily affecting thread count and such. – guy_who_can't_code Apr 09 '21 at 16:02
  • I'm not sure what you are looking for, but the idea behind vertx and similar frameworks is not to deal with threads and follow some basic rules so that framework takes care of managing threads. and yes you can not interrupt a sync code running because this would mean interrupting the thread. If you really want to, you need to build places into your sync code which check for that flag and exit early if thats set. – mohamnag Apr 13 '21 at 06:33
0

Deploying or undeploying verticles doesn't affect threads count. Vert.x uses thread pools of a limited size.

Undeploying verticles is a mean to downscale your service. Ideally, you shouldn't undeploy verticles at all. Deploying or undeploying does have a performance impact.

closeHandler, as I mentioned previously, is a callback method to release resources.

Vert.x Future doesn't provide cancellation means. The reason is that even Java's Future.cancel() is a cooperative operation.

As a means to fix this, probably passing a reference to AtomicBoolean as was suggested above, and checking it before every synchronous step is the best way. You will still be blocked by synchronous operations, though.

Alexey Soshin
  • 16,718
  • 2
  • 31
  • 40
  • Ahhh I see. So I'll just set up something to close all of the DB connections for that routingContext triggered by that closeHandler. Last thing that's unanswered though: Why does closeHandler only execute asynchronously when doing this multiple verticle approach? Using the normal way and simply executing requests using the alloted thread pool postpones closeHandler's execution until the eventloop finishes its queue, we need this to happen asynchronously. – guy_who_can't_code Apr 11 '21 at 19:41
  • Close Handler needs to run on the same thread the original handler runs. Otherwise you'll be in a race. When you run multiple verticles, they may get different threads. If you run a single instance, you'll get only one thread. – Alexey Soshin Apr 11 '21 at 20:41
  • Right, the problem is that we have blocking operations on the eventloop that are delaying the handler's execution. This is why I thought multiple verticles would be the way to go: https://stackoverflow.com/a/57419950/15488392 – guy_who_can't_code Apr 12 '21 at 15:56