Live data from Hacker News

Serving 200M requests per day with a CGI-bin

jacob.gold

11–20 of 87 posts

Re: Serving 200M requests per day with a CGI-bin

#11
post #7

Surprised with the choice of Apache. There are better choices for serving CGI nowadays. The only reason for still running Apache is you have legacy cruft that requires Apache (like .htaccess).

Apache is still a solid option. It does everything, works with everything and is easy to configure. Performance is perfectly fine for ~99% of everything.

I host 1200 vhosts off apache as an authenticating proxy, and run Al sorts of random scripts.

This is all internal use though, I don’t need to scale to hundreds of concurrent users let alone thousands. Apache and cgi bin is fine.

Re: Serving 200M requests per day with a CGI-bin

#12
Even back in the 1990s, CGI programs written in C were lightning fast. It just was (is) an error prone environment. Any safer modern alternative like the article's Go program or Nim or whatever not making database connections will be very fast & low latency to localhost - really similar to a CLI utility where you fork & exec. It's not free, but it's not that expensive compared to network latencies then or now.

People/orgs do tend to get kind of addicted to certain technologies that can interact poorly with the one-shot model, though. E.g., high start up cost Python interpreters with a lot of imports are still pretty slow, and people get addicted to that ecosystem and so need multi-shot/persistent alternatives.

The one-shot model in early HTTP was itself a pendulum swing from other concerns, e.g. ftp servers not having enough RAM for 100s of long-lived, often mostly idle logins.

Re: Serving 200M requests per day with a CGI-bin

#13
post #10

I got my start in the CGI era, and it baked into me an extremely strong bias against running short-lived subprocesses for things. We invented PHP and FastCGI mainly to get away from the performance hit of starting a new process just to handle a web request! It was only a few years ago that I realized that modern hardware means that it really isn't prohibitively expensive to do that any more - this benchmark gets to 2…

> We invented PHP and FastCGI mainly to get away from the performance hit of starting a new process just to handle a web request!

Yes! Note that the author is using a technology that wasn't available when I too was writing cgi_bin programs in the 00's: Go. It produces AOT compiled executables but is also significantly easier to develop in and safer than trying to do the same with C/C++ in the 00's. Back then we tended to use Perl (now basically dead). Perl and Python would incur significant interpreter startup and compilation costs. Java was often worse in practice.

> I have seen AWS Lambda described as the CGI model reborn and that's a pretty fair analogy.

Yes, it's almost exactly identical to managed FastCGI. We're back to the challenges of deployment: can't we just upload and run an executable? But of course so many technologies make things much, much more complicated than that.

Re: Serving 200M requests per day with a CGI-bin

#15

Surprised with the choice of Apache. There are better choices for serving CGI nowadays. The only reason for still running Apache is you have legacy cruft that requires Apache (like .htaccess).

Apache's httpd is great, reliable, fast, and feature-full, and you don't have to deal with Nginx's ongoing conflict over the the open source vs commercial offerings. That conflict has caused needless pain, like e.g. that quirk around dns resolution where if you put the hostname under proxy_pass it only used to resolve it on start-up and ignored TTL (not sure if it's still doing that). There were work-arounds on the open source version, like using a variable instead, but that wasn't necessary in the commercial offering.

Re: Serving 200M requests per day with a CGI-bin

#16
post #10

I got my start in the CGI era, and it baked into me an extremely strong bias against running short-lived subprocesses for things. We invented PHP and FastCGI mainly to get away from the performance hit of starting a new process just to handle a web request! It was only a few years ago that I realized that modern hardware means that it really isn't prohibitively expensive to do that any more - this benchmark gets to 2…

I think you might have found that CGI scripts deployed as statically-linked C binaries, with some attention given to size, you might've not been so disappointed.

The "performance hit of starting a new process" is bigger if the process is a dynamically-linked php interpreter with gobs of shared libraries to load, and some source file, reading parsing compiling whatever, and not just by a little bit, always has been, so what the author is doing using go, I think, would still have been competitive 25 years ago if go had been around 25 years ago.

Opening an SQLite database is probably (surprisingly?) competitive to passing a few sockets through a context switch, across all server(ish) CPUS of this era and that, but both are much faster than opening a socket and authenticating to a remote mysql process, and programs that are not guestbook.cgi often have many more resource acquisitions which is why I think FastCGI is still pretty good for new applications today.

Re: Serving 200M requests per day with a CGI-bin

#17
post #4
post #3

Earlier quoted context omitted.

I miss this so much. Deployment should be just copying the file (over ssh or whatever). Why people overcomplicated it so much?

PHP can work the same way. Push / FTP / SFTP PHP file to directory, deployed.

We used to use symlinks to enable atomic operations, too. e.g. under /var/www/ we'd have /var/www/webapp_1.0, and have a symlink /var/www/webapp pointing to it. When there was a new version, upload it to /var/www/webapp_1.1, and then to bring it live, just update the symlink. Need to roll back? Switch the symlink back.

Re: Serving 200M requests per day with a CGI-bin

#18
The nice thing about CGI is that you don't have to reinvent isolation primitives for multi-tenant use cases. A bug in one request doesn't corrupt another request, due to process isolation. An infinite loop in one request doesn't DoS other requests, due to preemptive scheduling. You can kill long-running requests with rlimit. You can use per-tenant cgroups to fairly allocate resources like memory, CPU and disk/network I/O. You can use namespaces/jails and privilege separation to restrict what a request has access to.

Re: Serving 200M requests per day with a CGI-bin

#19
post #9

Try an apache tomcat 11 next. You can just dump .jsp files or whole java servlet applications as .war file via ssh and it will just work! One shared JVM for maximum performance! It can also share db connection pools, caches, etc. among those applications! Wow!

It depends on the application usage pattern. For heavily used applications, sure, it's an excellent choice. But imagine having to host 50 small applications each serving a couple of hundreds requests per day. In that case, the memory overhead of Tomcat with 50 war files is much bigger than a simple Apache/Nginx server with a CGI script.

The other issue with Tomcat is that a single bad actor can more easily compromise the server.

Not saying that can't happen with CGI, but since Tomcat is a shared environment, it's much more susceptible to it.

This is why shared, public Tomcat hosting never became popular compared to shared CGI hosting. A rogue CGI program can be managed by the host accounting subsystem (say, it runs too long, takes up too much memory, etc.), plus all of the other guards that can be put on processes.

The efficiency of CGI, specifically for compiled executables, is that the code segments are shared in virtual memory, so forking a new one can be quite cheap. While forking a new Perl or PHP process shares that, they still need to repeatedly go through the parsing phase.

The middle ground of "p-code" can work well, as those files are also shared in the buffer cache. The underlying runtime can map the p-code files into the process, and those are shared across instances also.

So, the fork startup time, while certainly not zero, can be quite efficient.

Re: Serving 200M requests per day with a CGI-bin

#20
post #16
post #10

I got my start in the CGI era, and it baked into me an extremely strong bias against running short-lived subprocesses for things. We invented PHP and FastCGI mainly to get away from the performance hit of starting a new process just to handle a web request! It was only a few years ago that I realized that modern hardware means that it really isn't prohibitively expensive to do that any more - this benchmark gets to 2…

I think you might have found that CGI scripts deployed as statically-linked C binaries, with some attention given to size, you might've not been so disappointed. The "performance hit of starting a new process" is bigger if the process is a dynamically-linked php interpreter with gobs of shared libraries to load, and some source file, reading parsing compiling whatever, and not just by a little bit, always has been, s…

That's likely true - but C is a scary language to write web-facing applications in because it's so easy to have things like buffer overflows or memory leaks.
Post reply on HN