high performance application webserver in C/C++
Is there any high performance (ideally evented and open source) web server in C or C++?
I'd like to be able to use it in that it calls a method/function in my application with a filled out HTTP Request class/struct, and then I can return a filled out HTTP Response class/struct to it.
If it isn't open source, I'd need built in support for long-polling connections, keep-alive, etc—otherwise, I think that I can add these things myself.
If you don't know of any such servers available, would you recommend writing my own web server to fit the task? It cannot be file-based, and must be written in high-performance C/C++.
Edit: I'm thinking something like the Ruby Mongrel for C, if that helps.
I had the very same requirements for my job, so I evaluated a number of solutions: mongoose, libmicrohttpd, libevent. And I also was thinking about writing nginx modules. Here is the summary of my findings:
I love this server and use it a lot. Its performance and resource usage is much better than that of Apache, which I also still use but plan migrating to nginx.
- Very good tunable performance. Rich functionality. Portability.
- Module API is not documented and seems to be very verbose. See this nginx hello world module as example.
- Nginx does not use threads but uses multiple processes. This makes writing modules harder, need to learn nginx API for shared memory, etc.
- All server's code is in single mongoose.c file (about 130K), no dependencies. This is good.
- One thread per connection, so if you need concurrency you've got to configure lots of threads, ie. high RAM usage. Not too good.
- Performance is good, although not exceptional.
- API is simple but you have to compose all response HTTP headers yourself, ie. learn HTTP protocol in detail.
- Official GNU project.
- Verbose API, seems awkward to me, although much more simple than writing nginx modules.
- Good performance in keep-alive mode (link to my benchmarks below), not so good without keep-alive.
Libevent library has built-in web server called evhttp.
- It is event based, uses libevent for that.
- Easy API. Constructs HTTP headers automatically.
- Officially single-threaded. This is major disadvantage. I've found a hack, which makes several instances of evhttp run simultaneously accepting connections from the same socket. Not sure if it is all safe and robust.
- Performance of single-threaded evhttp is surprisingly poor. Multi-threaded hack works better, but still not good.
G-WAN project is not open source, but I'd like to say a few words about it.
- Very good performance, low memory usage, 150 KB executable.
- Very convenient 'servlet' deployment: just copy .c file into csp directory, and running server automatically compiles it. Code modifications also compiled on the fly.
- Simple API. Although constrained in some ways. Rich functionality (json, key-value store, etc.).
- Unstable. I had segfaults on static files. Hangs on some sample scripts. (Experienced on clean install. Never mixed files of different versions).
- Only 32-bit binary (not anymore).
So as you can see, none of existing alternatives have fully satisfied me. So I have developed my own server, which is ...
- Very good performance; see benchmarks on project page
- Can serve tens of thousands concurrent requests
- Small memory footprint
- Multi-threaded model designed to scale
- Exceptionally light code base
- Simple API
- Decent HTTP protocol handling
- Keep-alive connections
- SSL support (via GNUTLS)
- HTTP proxy (with keep-alive connection pooling)
- Non-blocking sendfile support (with configurable small file memory cache; gzip pre-encoded file serving)
- Modular design for developers
- Can be run as daemon; relaunches itself on error
- Open source
- Depends on libev library (not anymore)
- Only tested on Linux
I would suggest to write a FastCGI executable that can be used with many high performance web servers (even closed source ones).
mongoose: one file. simple and easy to use. not an asycn io but perfect for embedded and particular purposes.
gwan. excellent. no crashes. ultra well planned configuration. very smart and easy for c/c++ development in other words, very clean sensible api compared to nginx. provides a thread per core. or whatever you specify. a great choice. largest disadvantage (maybe im lacking in this area): cannot step thru code.
libevent: single thread is not a disadvantage on a single core machine. afterall its point is an async i/o. does have multithreads for other cores.
nginx: no personal experience. gaining serious ground on a-patchy server. (terribly confusing api)
python bottle: awesome 1 file lib (framework/system) that makes it easy to build python web apps. has/is a built in httpd server, like libevent and node.js
I'm going to suggest the same thing as Axel Gneiting - but have provided an answer with my reasons for taking this approach:
1) HTTP is not trivial as a protocol - writing your own server or amending an off-the-shelf solution is a very complex task - a lot more complex than using the available APIs for implementing a separate processing engine
2) Using (an unmodified) mainstream webserver should provide you with more functionality than you require (so you've got growing room).
3) Using (an unmodified) mainstream webserver will usually mean that it has been far more extensively tested and documented than a homebrew system.
4) .. and its more likely to be secure and stable.
5) Using fastCGI you can use all sorts of languages to develop your back-end processing in - including C++ and C. There are standard toolkits available to facilitate this.
6) alternatively many webservers provide support for running interpreter engines in-process (e.g. mod_php, mod_perl). I'd advise against running your own native code as a module though.
It cannot be file-based.
Eh? What does that mean?
I'm an avid nginx user; nginx is written in C; nginx seems like it could work for you. If you want the very best speed out of nginx, I would make a nginx module. Here are 3rd party modules which you can examine to get an idea of what it requires.
As for the long polling requirement, you might want to have a look at the http push modules.