-
Notifications
You must be signed in to change notification settings - Fork 3k
FastCGI
HHVM-FastCGI works much the same way as PHP-FPM. An application server (HHVM running in FastCGI mode) is started independently of the web server (Apache, Nginx, etc.). It listens on either a TCP socket (by convention this is localhost:9000) or UNIX socket. The web server listens on port 80. When a new request comes in, the web server makes a connection to the application server (or reuses one of the previously open connections) and communicates with it using FastCGI protocol. The web server decodes HTTP protocol and supplies application server with information such as the path of the file to be executed, request headers & body. The application server computes the response and sends it back to the web server, again using FastCGI protocol. The web server is then in charge of sending back the HTTP response back to the client.
To run the server in FastCGI mode pass the following parameters to hhvm runtime:
hhvm --mode server -vServer.Type=fastcgi -vServer.Port=9000
The server will now accept connections on localhost:9000. To use a UNIX socket, use the Server.FileSocket
option instead:
hhvm --mode server -vServer.Type=fastcgi -vServer.FileSocket=/var/run/hhvm/sock
To turn the server into a daemon, change the value of mode:
hhvm --mode daemon -vServer.Type=fastcgi -vServer.FileSocket=/var/run/hhvm/sock
Note, all the usual options that are accepted by hhvm runtime can be used in FastCGI mode as well. In particular, -vAdminServer.Port=9001
will create an additional "admin" server listening on a port 9001.
The recommended way of integrating with Apache is using mod_proxy
mod_proxy_fcgi
. Enable the modules, then in your Apache configuration, add a line as so:
ProxyPass / fcgi://127.0.0.1:9000/path/to/your/www/root/goes/here/
This will route all the traffic to the FastCGI server. If you want to route only certain requests (e.g. only those from a subdirectory or ending *.php, you can use ProxyPassMatch
, e.g.
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/path/to/your/www/root/goes/here/$1
Consult mod_proxy_fcgi
docs for more details on how to use ProxyPass
and ProxyPassMatch
.
Apache 2.2 does not have mod_proxy_fcgi
so you need to install libapache2-mod-fastcgi
and then enable the module. Additionally you need the actions
module which comes bundled with apache 2.2.
<IfModule mod_fastcgi.c>
Alias /hhvm.fastcgi /var/www/fastcgi/hhvm.fastcgi
FastCGIExternalServer /var/www/fastcgi/hhvm.fastcgi -socket /var/run/hhvm/socket -pass-header Authorization -idle-timeout 300
<Directory "/var/www/fastcgi">
<Files "hhvm.fastcgi">
Order deny,allow
</Files>
</Directory>
AddHandler hhvm-hack-extension .hh
AddHandler hhvm-php-extension .php
Action hhvm-hack-extension /hhvm.fastcgi virtual
Action hhvm-php-extension /hhvm.fastcgi virtual
</IfModule>
This will make all .php and .hh files go over to the FastCGI server. The /var/www/fastcgi
folder above needs to exist and be writable by the webserver user.
If you started hhvm
with tcp host config (-vServer.Port=9000
) change the line FastCGIExternalServer
to FastCGIExternalServer /var/www/fastcgi/hhvm.fastcgi -host <hhvm_host_ip>:9000 -pass-header Authorization -idle-timeout 300
, where <hhvm_host_ip>
can be 127.0.0.1
The default FastCGI configuration from Nginx should work just fine with HHVM-FastCGI. For instance you might want to add the following directives inside one of your location
directives:
root /path/to/your/www/root/goes/here;
fastcgi_pass unix:/var/run/hhvm/hhvm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
If using a TCP socket, replace unix:/var/run/hhvm/hhvm.sock
with 127.0.0.1:9000
.
The traffic for the surrounding location
directive will be now routed to the HHVM-FastCGI server.
All the I/O is non-blocking. The server uses two types of threads: I/O worker threads and HHVM worker threads:
- A single I/O worker thread is responsible for accepting connections.
- A few I/O worker threads jointly handle I/O on the open connections. Under heavy load there will roughly be a single I/O thread per CPU which is the optimal setup. New connections are distributed among I/O threads using a round robin algorithm. I/O threads never block waiting on a single connection. An I/O thread will only block if there is no activity on either of the connections that it handles (it then waits on a call to
select
or a similar system routine). - HHVM worker threads are in charge of PHP execution. They may block waiting for the body of the message (this will typically happen only for large POSTs). Translation cache is shared by all the worker threads and lives on after request handling is finished. This approach works well with JIT. When the same file is executed multiple times, you will see significant speed-ups.