I know that the current options are: creating a thread, a fork or a non-blocking socket?
What are the main advantages and disadvantages of all options?
What would be the recommendation for a small HTTP library?
4 Replies
For wiimmfi.de (a public Wii server) I programmed several servers, all of them are without threads. One of them manage 10+N clients with N=number_of_connected_consoles. The maximum online count was 754, so that the server had to manage more then 760 clients. Currently the server is running since September with an average CPU usage of 0.4% of a single CPU. In that time (2 months) it managed 2.6 millions connects and 250 millions received packets. This includes about 29 millions database queries. So there is no need to go to more complex multitasking.
What I will say is: If your server is fast enough to manage all connections, a single thread application can be the better solution. It's easier to develop, debug and maintain.
Best usually needs to be defined... The "best" for a quick small size server should depend heavily on ease to code. While if you have a requirement for a huge number of connection, the resource footprint per connection should receive the most attentions.
Additionally, for a server that could run inattendedly for large periods of time, implementing a mechanism allowing to "drop and restart" heavy working parts could have a major interest.
That is the reason why a number of HTTP engines or proxies implement a mix of the 3 approaches, letting a sysadmin choose what actually best suits a specific use case.
Let us have a quick look at the major characteristics:
multiple processes
This one involves the most heavy resources requirements because creating a full process is a costly operation. But when you stop the process, the OS will reclaim everything, which can be a thing if problems in code (or in any used library) contain memory leaks
multiple threads
Often seen as a not so bad middle approach. Threads allow to use simple code (when each thread manages a simple connection), yet providing good performance because the load can be shared among multiple cores... until you need to accept huge number of connections
non blocking socket
When the processing is truly IO bounded, this is indeed a very efficient way: no kernel context switching is involved to pass from one connection to another one. The drawbacks are:
- the code is harder to write, test and maintain
- only uses one single core (which may or not be a concern, specially if the application runs on a virtual system)
- facing any resource leak, your only option is to periodically restart the whole server
Up to you to decide what best means, simple code, ability to serve large number of clients or ease to have the server run unattended for large periods of time
I believe I once read about a web server spawning child processes for handling HTTP requests, but to only let a child process handle a certain number of requests before it terminates and is replaced by a new child process. That way, if there are any memory leaks in the code which handles the HTTP requests, these memory leaks will not accumulate forever; they will only accumulate for a limited time.
This means that memory leaks in the parent process will still be a serious issue, because they will accumulate over time. But memory leaks inside the child processes will be less of an issue.
Processing HTTP requests in child processes also has the advantage that if the code crashes while handling a request, then it will only cause the child process to terminate, instead of the entire server.