multi-threaded FastCGI-App
Möchte ich mal eine FastCGI-Anwendung sollte in der Lage mehrere gleichzeitige Anfragen, die Verwendung von threads. Ich hatte einen Blick auf die Gewinde.c Probe, die mit dem SDK geliefert:
#define THREAD_COUNT 20
static int counts[THREAD_COUNT];
static void *doit(void *a)
{
int rc, i, thread_id = (int)a;
pid_t pid = getpid();
FCGX_Request request;
char *server_name;
FCGX_InitRequest(&request, 0, 0);
for (;;)
{
static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t counts_mutex = PTHREAD_MUTEX_INITIALIZER;
/* Some platforms require accept() serialization, some don't.. */
pthread_mutex_lock(&accept_mutex);
rc = FCGX_Accept_r(&request);
pthread_mutex_unlock(&accept_mutex);
if (rc < 0)
break;
server_name = FCGX_GetParam("SERVER_NAME", request.envp);
FCGX_FPrintF(request.out,…
…
FCGX_Finish_r(&request);
}
return NULL;
}
int main(void)
{
int i;
pthread_t id[THREAD_COUNT];
FCGX_Init();
for (i = 1; i < THREAD_COUNT; i++)
pthread_create(&id[i], NULL, doit, (void*)i);
doit(0);
return 0;
}
In der FastCGI-Spezifikation es ist eine Erklärung, wie der web-server wird bestimmen, wie viele verbindungen unterstützt durch die FastCGI-app:
Web-server kann die Abfrage bestimmter
Variablen, die innerhalb der Anwendung. Die
server wird in der Regel führen Sie eine Abfrage
beim starten der Anwendung, um zu
automatisieren bestimmte Aspekte des Systems
- Konfiguration....
• FCGI_MAX_CONNS: Die maximale Anzahl
der gleichzeitige transport-verbindungen
diese Anwendung akzeptiert, z.B. "1"
oder "10".• FCGI_MAX_REQS: Die maximale Anzahl
von gleichzeitigen Anfragen diese
Anwendung akzeptiert, z.B. "1" oder
"50".• FCGI_MPXS_CONNS: "0", wenn dies
Anwendung nicht-multiplex
verbindungen (D. H. gleichzeitigen Griff
Anfragen über jede Verbindung), "1"
ansonsten.
Aber die return Werte für diese Abfrage sind hart codiert in der FastCGI-SDK und gibt 1 für FCGI_MAX_CONNS und FCGI_MAX_REQS und 0 für FCGI_MPXS_CONNS. Also das Gewinde.c-Probe erhalten nie mehrere verbindungen.
Getestet habe ich das Beispiel mit lighttpd und nginx, und die app behandelt nur eine Anfrage auf einmal. Wie kann ich meine Anwendung für die Verarbeitung mehrerer Anfragen? Oder ist das der falsche Ansatz?
- Wie hast du den test Parallelität? Es gibt eine Menge unterschiedlicher Informationen über den Grad, zu dem FCGI unterstützt Parallelität. Während ich nicht behaupten, alle Antworten haben herausgefunden, ich habe versucht, eine multi-Thread-test, um zu überprüfen Parallelität: Zwei threads zum akzeptieren von verbindungen konfiguriert. Der erste Schlaf für 10s nach dem akzeptieren einer Verbindung, die Sperrung, die thread. Eine zweite Verbindung wird angenommen und beantwortet. Endlich, der erste thread beendet ist und reagiert. Deine Frage ist fast ein Jahr alt, aber ich habe Probleme Antworten zu finden über FCGI, ich hoffe das hilft.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Getestet das Gewinde.c-Programm mit http_load. Das Programm läuft hinter nginx. Es gibt nur eine Instanz des Programms läuft. Wenn die Anfragen werden nacheinander serviert, würde ich erwarten, dass es dauern würde, 40 Sekunden für 20 Anfragen, auch wenn geschickt parallel. Hier sind die Ergebnisse (ich habe dieselben zahlen wie Andrew Bradford - 20, 21, und 40) -
20 Anfragen, 20 parallel, dauerte 2 Sekunden -
21 Anfragen, 20 parallel dazu nahm 4 Sekunden -
40 Anfragen, davon 20 in parallel, dauerte 4 Sekunden -
So, es beweist, dass selbst wenn die FCGI_MAX_CONNS, FCGI_MAX_REQS, und FCGI_MPXS_CONNS Werte sind fest codiert, die Anfragen, werden Ihnen parallel.
Wenn Nginx erhält mehrere Anfragen, stellt er Sie alle in der FCGI Anwendung Warteschlange zurück. Es wartet nicht auf eine Antwort von der ersten Anfrage vor dem senden der zweiten Anfrage. In der FCGI-Anwendung, wenn ein thread bedient die erste Anfrage für was auch immer Zeit, ein anderer thread wartet nicht auf die erste, die fertig ist, wird es abholen, die zweite Anfrage und mit der Arbeit beginnen. Und so weiter.
So, die einzige Zeit, die Sie verlieren, ist die Zeit, die zum Lesen eine Anforderung aus der Warteschlange. Diese Zeit ist in der Regel vernachlässigbar im Vergleich zu der Zeit es braucht, um die Anforderung zu verarbeiten.
Gibt es nicht eine einzige Antwort auf diese Frage, da dieser nicht nur davon abhängig, dass das FastCGI-Protokoll, auch und vor allem, hängt von der FastCGI-Prozess-manager im Einsatz. Für Apache2 web-Server, die FastCGI-Prozess-manager in der Regel werden
mod_fastcgi
odermod_fcgid
. Diese beiden Verhalten sich anders.mod_fastcgi
zu sein scheint, multi‑thread bewusst sind, und senden gleichzeitige Anfragen an einen FastCGI-server, das erklärt es‑selbst-zu unterstützen.mod_fcgid
so weit ist (kann sich in Zukunft ändern?) nicht multi‑thread bewusst, und immer erzeugen Sie einen neuen FastCGI-server-Prozess auf die gleichzeitige Anfrage und senden niemals per gleichzeitige Anfragen an einen FastCGI-server.Alle, die sagen: ja, FastCGI, hat Bestimmung für multi‑threaded-FastCGI-Server, aber das Umfeld, in dem die FastCGI-server ausgeführt wird, muss auch diese Funktion eine der Realität... in der Praxis kann es, oder kann es nicht, und leider
mod_fcgid
nicht, zumindest bisher.Wenn Ihr FastCGI-SDK wurde von
mod_fcgid
, das mag der Grund sein, warum die Antwort auf dieFCGI_MAX_CONNS
management Anfrage immer wieder die Feste hartcodierten Wert1
.Die Sie interessieren können, der in meiner letzten Frage, und in zwei anderen web‑links, die alle drei nennt das jeweilige Thema von multi‑threaded-FastCGI-server:
Ich denke, man kann die Tests in einer Weise, dass Grenzen, die Sie zu einem einzelnen Thread. Ich hatte in einer ähnlichen situation, mit libfcgi und lighttpd, aber festgestellt, dass wenn ich Firefox zum testen mit, dass Firefox würde künstlich zu limitieren Einreichung der HTTP-Anforderung an den server, bis die Vorherige auf dem gleichen server abgeschlossen hatte. Das Werkzeug, das Sie verwenden, um zu testen, kann etwas ähnliches tun.
Sollten Sie nicht brauchen, ändern Sie die
FCGI_MAX_CONNS
,FCGI_MAX_REQS
oderFGCI_MPXS_CONNS
. Die hart-kodierten Werten sollte keine Rolle spielen, auf modernen Webservern wie nginx oder lighttpd.Über ein Kommandozeilen-tool wie curl und laichen in 20 Prozesse von curl auf einmal alle Treffer die server-Ergebnisse in allen 20 threads Aktivierung und alle 20 der curl finishing-Prozesse zur gleichen Zeit, nach 2 Sekunden, beim laufen gegen die Beispiel-Gewinde.c zur Verfügung gestellt von SDK (eine explizite
sleep(2)
nennen).Habe ich meine lighttpd-Konfiguration eingestellt wie:
max-procs
auf 1 gesetzt werden nur laichen Sie eine Kopie der fcgi-Programm und lighttpd sollte der Bericht die zunehmende "Belastung" über die Steckdose, wie Anfragen kommen, bevor eine Vorherige Anforderung abgeschlossen ist.Wenn Sie laichen 21 curl Prozesse, die ersten 20 sollte fertig in 2 Sekunden, dann sollte das Letzte finish in weiteren 2 Sekunden. Laichzeit 40 curl-Prozesse sollten nehmen fast die gleiche Dauer wie 21 (knapp über 4 Sekunden insgesamt).