Re: [libuv] Threaded workers which also do I/O
On Tuesday, October 18, 2016 at 11:52:22 PM UTC+2, Saúl Ibarra Corretgé wrote: > > > > One thing is that when I control-C out of the running server, it prints > > the following and then hangs: > > ^C[INFO] (../src/server.c:16) Received SIGINT, stopping... > > [INFO] (../src/server.c:107) Stopping workers... > > [INFO] (../src/worker.c:81) [Worker #0] stopped > > [INFO] (../src/worker.c:81) [Worker #1] stopped > > [INFO] (../src/worker.c:81) [Worker #3] stopped > > [INFO] (../src/worker.c:81) [Worker #2] stopped > > > > I have to kill -9 the process to terminate it. This is on CentOS 6.8 > > using kernel 2.6.32 (hangs head in shame...). Perhaps too old to support > > SO_REUSEPORT? The #define is there and the compilation doesn't throw any > > warnings, but there. > > > > Maybe it got backported? No idea, AFAIK it appeared on 3.7 or 3.9. It > used to work, though it may require an adjustment or 2 :-) At any rate > is more of a toy example than a functioning one... > I got it to respect Ctrl-C with this patch, although I am not sure the semantics are right: diff --git a/src/worker.c b/src/worker.c index 99e4297..92ac32a 100644 --- a/src/worker.c +++ b/src/worker.c @@ -56,7 +56,7 @@ static void uttp__worker_close(uttp_worker_t* worker) { } ASSERT(QUEUE_EMPTY(>conn_queue)); -r = uv_run(>loop, UV_RUN_DEFAULT); +r = uv_run(>loop, UV_RUN_NOWAIT); ASSERT(r == 0); r = uv_loop_close(>loop); What exactly do you mean by your code being "more of a toy example than a functioning one"? It seems quite good to me as the basis for a multi-threaded HTTP server. What would you say is missing here? Cheers, Gonzalo -- You received this message because you are subscribed to the Google Groups "libuv" group. To unsubscribe from this group and stop receiving emails from it, send an email to libuv+unsubscr...@googlegroups.com. To post to this group, send email to libuv@googlegroups.com. Visit this group at https://groups.google.com/group/libuv. For more options, visit https://groups.google.com/d/optout.
Re: [libuv] Threaded workers which also do I/O
On Tuesday, October 18, 2016 at 7:23:54 AM UTC+2, Saúl Ibarra Corretgé wrote: > > On 17/10/16 19:41, Gonzalo Diethelm wrote: > > First post, libuv newbie. > > Hi and welcome to libuv then! > Thanks, and thank you for your thorough response. > > I am trying to understand how a multi-threaded web server would fit in > > the libuv design. This is how I envision it, but I have some questions. [snip] > If each thread is a uv loop, then you could send the connection where > the request came from from one loop to another using uv_write2. That > way the job of the "acceptor loop" would only be accepting and > dispatching connections. That's a great suggestion. This is not how you implemented things in your example, right? I believe there each worker accepts its own connections and processes everything from there on. I didn't know you could do the accept in separate threads... Ah, the magic of SO_REUSEPORT? That makes things even easier! > 1. Is using a thread-safe queue a good match for libuv? If libuv > > provides something like this, I have not been able to find it, and that > > makes me doubt this would be the libuv way. > > For certain scenarios such a construct would be useful, we don't provide > it though. Have a loop at http://concurrencykit.org/ > I see in your example you instead used QUEUE; I guess that's enough for these purposes. > > 2. Is it possible / advisable to have multiple threads in a process, > > each handling I/O with its own libuv loop? I guess yes. > > Yep. Nginx (which doesn't use libuv) uses a similar model. > Thanks for confirming this. > In case it helps, I created a multi-threaded HTTP server prototype to > try out some stuff here: https://github.com/saghul/uttp It currently > uses SO_REUSEPORT for kernel level connection balancing in Linux and the > NOTES file https://github.com/saghul/uttp/blob/master/NOTES contains the > other strategies I was going to try but never found the time :-) > > I hope you find it useful. > This is very useful indeed, thanks much! One thing is that when I control-C out of the running server, it prints the following and then hangs: ^C[INFO] (../src/server.c:16) Received SIGINT, stopping... [INFO] (../src/server.c:107) Stopping workers... [INFO] (../src/worker.c:81) [Worker #0] stopped [INFO] (../src/worker.c:81) [Worker #1] stopped [INFO] (../src/worker.c:81) [Worker #3] stopped [INFO] (../src/worker.c:81) [Worker #2] stopped I have to kill -9 the process to terminate it. This is on CentOS 6.8 using kernel 2.6.32 (hangs head in shame...). Perhaps too old to support SO_REUSEPORT? The #define is there and the compilation doesn't throw any warnings, but there. Cheers, > Saúl Ibarra Corretgé > Again, thanks for all the help. Cheers. -- You received this message because you are subscribed to the Google Groups "libuv" group. To unsubscribe from this group and stop receiving emails from it, send an email to libuv+unsubscr...@googlegroups.com. To post to this group, send email to libuv@googlegroups.com. Visit this group at https://groups.google.com/group/libuv. For more options, visit https://groups.google.com/d/optout.
Re: [libuv] Threaded workers which also do I/O
On 17/10/16 19:41, Gonzalo Diethelm wrote: First post, libuv newbie. Hi and welcome to libuv then! I am trying to understand how a multi-threaded web server would fit in the libuv design. This is how I envision it, but I have some questions. The main thread would run the HTTP accept loop, and I would expect each connection request to be handled to a worker in the thread pool. Each thread in the worker pool will also be doing I/O (think running a query against MySQL), and will somehow pass the results back to the main thread. After reading a bit here and there, I would think this is one way to do this with libuv: 1. Main thread runs default loop and handles all the HTTP traffic. Whenever it gets an HTTP request, it puts it in a thread-safe queue and does a notify_all to awake one random thread in the pool; all of these threads would be waiting on the queue. 2. One worker thread awakes, dequeues pending work from the queue and runs it. I guess each thread has its own libuv loop, to handle the I/O needed to go to MySQL / read a file / etc. If each thread is a uv loop, then you could send the connection where the request came from from one loop to another using uv_write2. That way the job of the "acceptor loop" would only be accepting and dispatching connections. 3. Once the request has been processed, the worker thread notifies the main thread that the response is ready and tries to read the next pending request from the queue; iterate. 4. The main thread sends the response back to the HTTP client and closes that connection. Now, there's some hand waving here, and I am not sure if what I'm describing is the proper / correct / best / possible way to do this with libuv. Some specific questions: 1. Is using a thread-safe queue a good match for libuv? If libuv provides something like this, I have not been able to find it, and that makes me doubt this would be the libuv way. For certain scenarios such a construct would be useful, we don't provide it though. Have a loop at http://concurrencykit.org/ 2. Is it possible / advisable to have multiple threads in a process, each handling I/O with its own libuv loop? I guess yes. Yep. Nginx (which doesn't use libuv) uses a similar model. 3. How would the worker threads notify the main thread that a response is ready? Would they use an async handle for this? If yes, can they all use the same async handle, or would each worker require their own async handle plugged to the main thread loop? But if they all share the same async handle, how does the main thread know which connection this response should be sent to? They don't need to! They can handle the connection themselves and send the response without having the main thread do it. In case it helps, I created a multi-threaded HTTP server prototype to try out some stuff here: https://github.com/saghul/uttp It currently uses SO_REUSEPORT for kernel level connection balancing in Linux and the NOTES file https://github.com/saghul/uttp/blob/master/NOTES contains the other strategies I was going to try but never found the time :-) I hope you find it useful. Cheers, -- Saúl Ibarra Corretgé http://bettercallsaghul.com -- You received this message because you are subscribed to the Google Groups "libuv" group. To unsubscribe from this group and stop receiving emails from it, send an email to libuv+unsubscr...@googlegroups.com. To post to this group, send email to libuv@googlegroups.com. Visit this group at https://groups.google.com/group/libuv. For more options, visit https://groups.google.com/d/optout.