Hacker News new | ask | show | jobs
by qbasic_forever 1330 days ago
For better or worse fast CGI never took off much beyond PHP. Python, node, ruby, etc. all do their own thing with their own app servers and protocols. I mean sure something like python can use fast CGI but no one in that community uses it that way, everyone uses uWSGI, gunicorn, etc.

Plain old CGI doesn't scale beyond toy usage--it spawns a process per request.

So there really isn't a good single option for Cloudflare to use.

1 comments

> Plain old CGI doesn't scale beyond toy usage--it spawns a process per request.

I'd be willing to bet the opposite: CGI is more than enough for 80% of workload, performance-wise.

There are a few good reasons why CGI isn't the best today: the tooling doesn't exist, the security model is really bad, and you can cram fewer websites on a single machine, so for the same number of websites you need more machines, and that's an ecological aberration. But there is no problem about CGI being too slow.

Speed is the only reason CGI doesn't fly.

What do you think is the upper limit of requests per second, if your HTTP server does process-per-request? For simplicity, assume server class hardware, that each request does no work besides producing a response, and an upper bound of 10k unique remote addresses (i.e. no more than 10k concurrent connections in a different model).

How do you think those metrics compare to other designs? I have an affinity for the conceptual simplicity of CGI but I've never been able to get a process-per-request server within even an order of magnitude of the performance of the more common designs. But I could be missing something!

Also, how does this design adapt to HTTP/2?

> What do you think is the upper limit of requests per second, if your HTTP server does process-per-request ?

In the hundreds, which is absolutely enough for most use cases. If CGI is enough for sqlite.org displaying dynamic content (such as in https://www.sqlite.org/cgi/src/timeline), it is enough for 80% of websites. You are not bigger than sqlite.

> How do you think those metrics compare to other designs

The important question is not "is it better or worse than alternatives" but "is it enough for me". Yes, it is.

> Also, how does this design adapt to HTTP/2?

HTTP/2 doesn't change anything. Requests are on the same socket until the webserver, and the webserver forks a process for each request, multiplexes the responses and all is well.

> The important question is not "is it better or worse than alternatives" but "is it enough for me". Yes, it is.

All good! But if you're OK with O(100) RPS out of a server, then I guess basically every possible option is on the table. I bet `nc` spawning background `bash` scripts to handle requests would get to 1k RPS, even! ;)

> HTTP/2 doesn't change anything.

I guess that would work, as long as the fronting server managed all of the connection management details, stream demuxing, etc. But I wonder how you'd do that in a single thread?

> Speed is the only reason CGI doesn't fly.

It is indeed very very slow; mostly because it is not possible to pre-fork your CGI scripts (environment variables get set from the request, so each cgi program will have different values in the environment).

But, if you could pass HTTP data via some way other than environment variables, you could pre-fork the binaries and have acceptable speed[1].

[1] Pre-forking makes a large difference, and surprisingly is not too far off from other approaches to concurrent request handling. See https://unixism.net/2019/04/linux-applications-performance-i...

Your link benchmarks with ab, which unfortunately has an unsound concurrency model, so you can't put too much trust in its results.
Sure but developers don't want to bifurcate their service code and releases into a simple version using CGI and a dedicated app server version for when CGI doesn't scale for them or their users. They just want to write one python web app and run it everywhere.

There's no way a CGI app can reach a million requests a second on the same hardware that a nodejs (single thread, worker loop) would take to do 1M RPS. Processes have a lot of overhead. Almost no one needs 1M RPS but it cannot be waived away that CGI is perfect for everything.

That's the problem: people absolutely exaggerate how much their site will need. I didn't say CGI is perfect for everything, I said it is enough for 80% of the websites, for the entire lifetime of said sites. Your blog won't suddenly reach Alexa top 100. Your family sharing photo site will remain seen by your relatives only. You HOA website won't become a trending topic overnight.
Yep. Also, sharing resources between connections is (at best) very difficult using CGI, and its trivially easy using a stand-alone app server. You can just set up a global variable at process startup and you're done. (This is useful in just about every web app I've ever written - eg for the connection to a database, cached resources, cached renders of common pages, in-memory only security tokens, etc).

I also find the modern approach much easier to reason about and debug. I don't need Apache + fastCGI + php + php fastCGI + apache configuration to get started. I can just run `node server.js` and my web app works.

The fact that it also scales much better is a cherry on top.

> Also, sharing resources between connections is (at best) very difficult using CGI, and its trivially easy using a stand-alone app server. You can just set up a global variable at process startup and you're done

You can pass environment variables to CGI scripts as well. In fact, that's exactly how CGI works. Shared resources can be cached in memory through redis, although a shared file (for example sqlite) is enough in many cases.

> I don't need Apache + fastCGI + php + php fastCGI + apache configuration to get started

I'm talking about CGI, not fastCGI

Environment variables can’t store a TCP connection to a database or a pre rendered HTML string.

In the latter case you could use redis, but that’s a poor, inconvenient, inefficient replacement for a global variable.

Again, I'm not saying CGI is the fastest but that it is fast enough. Opening a new connection (or better yet, using SQLite), reading a file that contains a prerendered HTML string are fast enough for most use cases