FastCGI
FastCGI
FastCGI ist ein Protokoll für die Kommunikation zwischen Webservern und externen Anwendungen, das als Weiterentwicklung des Common Gateway Interface (CGI) konzipiert wurde. FastCGI löst die Performance-Probleme von CGI durch die Wiederverwendung von Prozessen und bietet dabei mehr Flexibilität als eingebettete Lösungen wie Apache-Module.
Geschichte
FastCGI wurde 1996 von Open Market entwickelt, um die Nachteile des traditionellen CGI zu überwinden. Das Protokoll wurde als offener Standard veröffentlicht und wird heute von praktisch allen modernen Webservern unterstützt. Die Spezifikation ist in RFC-ähnlicher Form dokumentiert und wird von der FastCGI-Community gepflegt.
Funktionsweise
Grundprinzip
Im Gegensatz zu CGI, das für jede Anfrage einen neuen Prozess startet, verwendet FastCGI persistente Prozesse, die mehrere Anfragen nacheinander bearbeiten können:
Traditionelles CGI: Request 1 → [Start Process] → [Execute] → [Terminate] → Response 1 Request 2 → [Start Process] → [Execute] → [Terminate] → Response 2 FastCGI: Request 1 → [Persistent Process] → Response 1 Request 2 → [Same Process] → Response 2 Request 3 → [Same Process] → Response 3
Protokoll-Architektur
FastCGI verwendet ein binäres Protokoll für die Kommunikation zwischen Webserver und Anwendung:
- Records
- Dateneinheiten mit Header und Body
- Multiplexing
- Mehrere Requests können gleichzeitig über eine Verbindung laufen
- Streams
- Verschiedene Datentypen (STDIN, STDOUT, STDERR) werden getrennt übertragen
Kommunikationsarten
TCP-Sockets
Webserver ←→ TCP:9000 ←→ FastCGI Application
- Vorteile: Verteilung auf mehrere Server möglich
- Nachteile: Netzwerk-Overhead, Latenz
Unix-Domain-Sockets
Webserver ←→ /path/to/socket ←→ FastCGI Application
- Vorteile: Höhere Performance, geringere Latenz
- Nachteile: Nur lokal verwendbar
Vergleich mit anderen Technologien
| Technologie | Prozess-Overhead | Memory-Sharing | Skalierbarkeit | Isolation |
|---|---|---|---|---|
| CGI | Sehr hoch | Nein | Schlecht | Vollständig |
| FastCGI | Niedrig | Nein | Sehr gut | Gut |
| Apache mod_php | Mittel | Ja | Begrenzt | Gering |
| Embedded | Niedrig | Ja | Begrenzt | Keine |
Vorteile
Performance
- Keine Prozess-Erstellung bei jeder Anfrage
- Persistente Datenbankverbindungen bleiben erhalten
- Shared Memory für häufig verwendete Daten
- Kompilierte Module müssen nicht neu geladen werden
Skalierbarkeit
- Load Balancing zwischen mehreren FastCGI-Prozessen
- Horizontale Skalierung über mehrere Server
- Process Pooling für optimale Ressourcen-Nutzung
- Adaptive Skalierung basierend auf Last
Flexibilität
- Verschiedene Programmiersprachen können verwendet werden
- Unabhängige Updates von Webserver und Anwendung
- Verschiedene Versionen parallel möglich
- Service-orientierte Architektur unterstützt
Stabilität
- Prozess-Isolation verhindert gegenseitige Beeinflussung
- Graceful Restarts ohne Downtime möglich
- Fehler-Isolation - Absturz betrifft nur einzelne Anfrage
- Resource Limiting pro Prozess möglich
Implementierungen
Webserver-Unterstützung
Apache
# mod_fcgid
LoadModule fcgid_module modules/mod_fcgid.so
<Directory "/var/www/html">
SetHandler fcgid-script
FCGIWrapper /usr/bin/php-cgi .php
</Directory>
# mod_proxy_fcgi (Apache 2.4+)
<FilesMatch \.php$>
SetHandler "proxy:fcgi://127.0.0.1:9000"
</FilesMatch>
nginx
server {
listen 80;
server_name example.com;
root /var/www/html;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
# oder Unix-Socket:
# fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
lighttpd
server.modules += ( "mod_fastcgi" )
fastcgi.server = (
".php" => ((
"host" => "127.0.0.1",
"port" => 9000
))
)
FastCGI-Anwendungen
PHP-FPM
PHP-FPM ist die bekannteste FastCGI-Implementierung für PHP:
[www]
listen = 127.0.0.1:9000
user = www-data
group = www-data
pm = dynamic
pm.max_children = 50
Python
#!/usr/bin/env python
from flup.server.fcgi import WSGIServer
def application(environ, start_response):
status = '200 OK'
headers = [('Content-Type', 'text/plain')]
start_response(status, headers)
return ['Hello World from FastCGI!']
if __name__ == '__main__':
WSGIServer(application).run()
Ruby
#!/usr/bin/env ruby
require 'fcgi'
FCGI.each_cgi do |cgi|
cgi.print "Content-Type: text/html\r\n\r\n"
cgi.print "<html><body>Hello from Ruby FastCGI!</body></html>"
end
Protokoll-Details
Record-Format
Ein FastCGI-Record besteht aus:
typedef struct {
unsigned char version;
unsigned char type;
unsigned char requestIdB1;
unsigned char requestIdB0;
unsigned char contentLengthB1;
unsigned char contentLengthB0;
unsigned char paddingLength;
unsigned char reserved;
unsigned char contentData[contentLength];
unsigned char paddingData[paddingLength];
} FCGI_Record;
Record-Typen
- FCGI_BEGIN_REQUEST
- Startet eine neue Anfrage
- FCGI_PARAMS
- Überträgt Umgebungsvariablen
- FCGI_STDIN
- Überträgt Request-Body
- FCGI_STDOUT
- Response-Daten von der Anwendung
- FCGI_STDERR
- Fehler-Ausgaben
- FCGI_END_REQUEST
- Beendet eine Anfrage
Multiplexing
FastCGI unterstützt Request-Multiplexing über eine einzige Verbindung:
Connection 1: ├── Request A (ID: 1) ├── Request B (ID: 2) └── Request C (ID: 3) Records können verschachtelt übertragen werden: BEGIN_REQUEST(1) → PARAMS(2) → STDIN(1) → BEGIN_REQUEST(3) → ...
Konfiguration und Tuning
Process Management
# Statische Prozessanzahl
PM_STYLE = static
PM_MAX_CHILDREN = 20
# Dynamisches Management
PM_STYLE = dynamic
PM_MAX_CHILDREN = 50
PM_START_SERVERS = 5
PM_MIN_SPARE_SERVERS = 5
PM_MAX_SPARE_SERVERS = 35
Connection Pooling
upstream backend {
server 127.0.0.1:9000;
server 127.0.0.1:9001;
server 127.0.0.1:9002;
keepalive 32;
}
server {
location ~ \.php$ {
fastcgi_pass backend;
fastcgi_keep_conn on;
}
}
Timeout-Einstellungen
location ~ \.php$ {
fastcgi_connect_timeout 60s;
fastcgi_send_timeout 60s;
fastcgi_read_timeout 60s;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
}
Monitoring und Debugging
Status-Monitoring
Viele FastCGI-Implementierungen bieten Status-Seiten:
http://example.com/fpm-status
Ausgabe:
pool: www
process manager: dynamic
start time: 01/Jan/2024:00:00:00 +0000
accepted conn: 12345
active processes: 5
idle processes: 10
Debugging
# Debug-Logging aktivieren
error_log /var/log/nginx/error.log debug;
# FastCGI-spezifische Parameter loggen
fastcgi_param HTTP_X_DEBUG_INFO $request_id;
Sicherheitsaspekte
Prozess-Isolation
- Separate Benutzer für verschiedene Anwendungen
- chroot-Umgebungen für zusätzliche Isolation
- Resource Limits (CPU, Memory, File Descriptors)
Netzwerk-Sicherheit
# Nur lokale Verbindungen erlauben
fastcgi_pass 127.0.0.1:9000;
# Bei Unix-Sockets: Dateiberechtigungen
# chmod 660 /var/run/php-fpm.sock
# chown www-data:www-data /var/run/php-fpm.sock
Input-Validation
# Gefährliche Parameter blockieren
if ($fastcgi_script_name ~ \.\.) {
return 403;
}
# Upload-Limits
client_max_body_size 10M;
fastcgi_param CONTENT_LENGTH $content_length;
Performance-Optimierung
Caching
- OPcode-Caching bei Skriptsprachen
- Application-Level Caching
- FastCGI Cache im Webserver
Load Balancing
upstream fastcgi_backend {
least_conn;
server 127.0.0.1:9000 weight=3;
server 127.0.0.1:9001 weight=2;
server 127.0.0.1:9002 weight=1;
server 192.168.1.10:9000 backup;
}
Memory Management
# Prozess-Recycling nach X Requests
PM_MAX_REQUESTS = 1000
# Memory-Limits
memory_limit = 128M
max_execution_time = 30
Anwendungsfälle
- Multi-Tenant-Umgebungen mit Isolation
- Verschiedene PHP-Versionen parallel
- Resource-Limiting pro Kunde
High-Performance Websites
- Horizontale Skalierung über mehrere Server
- Load Balancing zwischen FastCGI-Backends
- Optimierte Resource-Nutzung
Microservices
- Service-spezifische FastCGI-Anwendungen
- Unabhängige Deployments
- Language-agnostische Architektur
Alternativen
- CGI: Einfacher, aber langsamer
- WSGI (Python): Python-spezifisches Interface
- Rack (Ruby): Ruby-spezifisches Interface
- PSGI (Perl): Perl-spezifisches Interface
- gRPC/HTTP/2: Moderne Alternative für Microservices
Siehe auch
Weblinks
Einzelnachweise
<references />