FastCGI

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen

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

Shared Hosting

  • 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 />