FastCGI in PHP. The way it could be

Intro

Most PHP programmers believe, that PHP has support for FastCGI. They refer to fastcgi-sapi, which is bundled with php since long ago, and which was recently reimplemented for PHP 5.1.3/4. This SAPI really does exist and actually working quite good. But… it is not a real fast-cgi. It is just an imitation of mod_php which is linked against fastcgi api, instead of apache api. So, it’s time for you to ask: if it exists and works, then what am I talking here about? Let’s start from the basics..

History

Once upon a time, in a galaxy far-far away, … hmm…

CGI.

The age of server-side web programming, as we know it, started with the introduction of Common Gateway Interface (CGI) in 1993. It allows http-server to launch external application, which gets raw HTTP-input and produces some output. This was a strictly UNIX-ish way of doing things, because CGI is basically a pipe between the server, which knows how to deal with TCP/IP and an application which just knows how to deal with stdin and stdout. CGI-app can be written in any programming language, doesn’t require any specific linking or compile-options. The advantage of such simplicity becomes the disadvantage, when your web-app starts to get a lot of hits. Every request ends in creating another process, and creating process can be quite an expensive operation.

pro: web-server independent
contra: slow

This problem received 2 independent solutions. The first one was creating server-dependent APIs for embedding applications directly into web-server process, and the second one was FastCGI.

Server APIs.

Embedding application into web-server is really good speed-wise, as the process initialization happens only once, and all of the requests are served in preloaded environment. No separate processes are started for serving requests, everything stays inside. This is good, and this is bad, at the same time. Think “security”, think “scalability”. Running your application inside of web-server means, that at the base-level it will have all the rights, which web-server itself has, which means that at the virtual-hosting any user can have access to any other users file (which include passwords and any other sensitive information). At the same time, there is no easy way to scale application to several machines, if there is a need to do so. Scalability issue can be solved by proxy’ing, but that is not the most beautiful solution, imho. (Mark Mayo has the different opinion on this subject).

The most well-known example of such embedding is Apache’s mod_php. It is faster than CGI, it runs with apache’s privileges, it has to be proxied if you need scaalbility.

pro: fast (lack of startup overhead)
contra: not secure, scalability requires additional tools, incompatible between server-manufacturers

FastCGI

Appeared in 1996, FastCGI is a solution which was trying to overcome problems of CGI, while keeping it’s good sides. Basically, it is a wrapper around CGI-application, which adds it a runloop. Application can make some initialization before entering runloop and can do some cleanup in the end. Web-server uses either UNIX or TCP-sockets to communicate with fastcgi-application. This gives us possibility to run target application under any user-privileges we need, without compromising other users privacy, to move application to the separate machine (or even several separate machines), and still to have very nice request-times.

FastCGI is also very nice speed-wise for application, which tend to have complex initialization process. Just do it before the runloop and leave only the actual serving logic inside.

typical fastcgi-application way of doing stuff (written in pseudo-code):

    load_all_modules();
    init_cache();
    init_database();

    while (wait_for_next_request()) {
        if (time_to_break())
            break;

        parse_request();
        serve_reply();
    }

    shut_down();

pro: fast (lack of startup overhead), secure, scalable, web-server independent
contra: requires a little-bit more programming than CGI

Getting back to PHP

Now, when you have all the required background let’s talk about mod_php and the way that it works. mod_php is an implementation of PHP for Apache web-server and is the most used environment for running PHP-scripts. The main idea behind it is simplicity for the final user. Each script is run from the beginning, when apache receives the request, allocates and uses any resources it needs in process and just forgets about those in the end — it’s mod_php’s tasks to do the cleanup. This means, that every request is completely separated (“sandboxed”) from all the other requests and it is not possible by standard means to have any data to be persistent between requests. This is reqlly good if you need something simple to be running easily and right now, but becomes a bottle-neck when you make “enterprise” application, which becomes slow just because it is big.

At some point, fastcgi implementation appeared in PHP’s list of SAPI’s, but the concept behind it was just to emulate mod_php’s behavior and make it consistent over web-servers which are not apache. PHP’s fastcgi SAPI doesn’t expose runloop to the PHP application, but implements it inside of itself, instead. As a result, we still have “everything is cleaned up on exit” mode, which leaves us without possibility to pre-init anything. What really bugs me a lot is that all of the php-competitors have proper fast-cgi support: Perl, Python, Ruby. This is one of the reasons, by the way, why Ruby’s “Rails” and Python’s “Django” are working faster than similiar PHP’s frameworks.

The main reason for the current situation is, that PHP’s main aim always was “simplicity” and strict orientation on the small web-apps. Perl, Python and Ruby and general-purpose languages which came into the web-world and are looking for the best ways to fit here (so they chose fastcgi), while PHP originated as a web-language and has a big legacy and traditions of such. Proper fastcgi support in the beginning would have slowed PHP adoption (as it would add complications). PHP is just making it first steps as a general-purpose language and as a language for “big apps”. This time, FastCGI is required.

I am in the mood, actually, to implement the proper FastCGI-SAPI and FastCGI-extension for PHP, but I have really big troubles with allocating time for this project. If anyone is interested in doing some coding in this direction I would be just happy to cooperate.

Some links:

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • DZone
  • FriendFeed
  • Reddit
  • Tumblr
  • Twitter

View CommentsFastCGI in PHP. The way it could be

  • Just implement the AJP protocol and use the built in support in version 2.2 or mod_jk for previous versions.

  • ajp is not as “beautiful” and complete solution as fastcgi, imho.

  • Stanislav Malyshev

    I see no reason why you can’t implement FCGI protocol in long-running PHP script. However, PHP webserver model is targeted on (relatively) short isolated requests – that’s how web applications work and that’s how webservers expect them to work. It is not right that this is only for Apache’s mod_php – it is true for *all* webserver SAPIs. There’s nothing “improper” in PHPs FCGI implementation – FCGI is a protocol to communicate with the webserver and PHP implements it properly – it’s just not meant to do what you want it to do, because it is oriented on different model of communication with the server and different model of applications.
    If, however, you do need the long-running script having its own event loop communicating with the web server, nothing prevents you from using non-webserver SAPI – namely CLI – and implementing the event loop inside your script on top of it. Well, not entirely correct – there’s one thing: there’s no PHP extension I know that implements it right now, so you’d have to either write one or parse all bits and bytes of FCGI in PHP (this BTW is exactly what Python is doing). If you find such module or implement it yourself, you are more than welcome to share it with the world :) However, while such things could be very useful, I don’t see it becoming default model of running PHP over FCGI anytime soon.

  • Stanislav: That’s exactly what I am implementing right now. :)
    SCGI in pure php (FastCGI will be next)

  • [...] Long story: Some time ago I was ranting about PHP and it’s “way” of handling FastCGI. The idea is to have persistent PHP-application which would handle requests from inside. This would allow us have “real” persistent cache in application (persistent connection to arbitary resources, preparsed XSLT’s in memory) and reply to queries really fast as we wouldn’t need to load all the classes on each request (classes would be loaded only once, during app initialization). And no, APC and similiar technologies do not completely solve this problem. [...]

  • [...] Тяжело сказать, конечно, что всё это блоги и “добавлено в Google Reader”, просто всё это читалось, курилось, переваривалось: High Scalability – Building bigger, faster, more reliable websites. MySQL Performance Blog Domas Mituzas – специалист по MySQL + поддержка Wikipedia рекомендую Wikipedia: site internals, etc (the workbook) Load Balancing Your Web Site Performance Tuning Best Practices for MySQL MySQL Manual Index Hint Syntax Optimizing Queries with EXPLAIN FastCGI in PHP. The way it could be Lighttpd Performance Improvements Lighttpd Optimizing FastCGI performance Understanding FastCGI Application Performance Squid: Accelerator Mode XCache Faster Is Possible Using X-Accel-Redirect Header With Nginx to Implement Controlled Downloads Lighttpd X-Sendfile Scaling with MySQL replication Может чего и забыл – у меня нет лаптопа (я их ненавижу), поэтому часть ссылок ещё есть на другой машине, и возможно завтра я их тоже добавлю сюда. Blog, Web — Сергей Куракин @ 16:46 Уже комментировало (1) » [...]

  • genabatyan

    Hey, I had the same Idea since ages. Today have been crawling the web if anyone has done anything this way.
    It really surprises me that there's almost nothing on this topic and nobody seems to be interested!

    Many sophisticated and resource-hungry PHP frameworks appear and become very popular, but come on, a test page of 5 lines, using doctrine to fetch one record from the database needs 50ms! and that's with APC enabled. This is absolutely ridiculous.
    I believe if doctrine initialization – a great part of which is shared absolutely the same way across all requests – would be moved out of the fast-cgi request loop, performance boost would be gigantic and had a chance to get close to “normal” fast-cgi experiences.

    I was trying to write a proof-of-concept almost zero-config pure-php solution to “long-living php workers” but without using any standards like fast-cgi. But it turned out to be too complex to waste time on it, why not doing it “right” from the beginning, that is implementing a widely accepted fastcgi protocol in pure PHP.

    If you're still interested drop me a line!

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

blog comments powered by Disqus