fastcgi: prefork oder threaded? - minspare, maxspare usw...
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Ja, das stimmt, mit minSpare und maxSpare sollte man entweder die Anzahl der Prozesse (bei prefork) oder die Anzahl der Threads (bei threaded) steuern können:
In https://code.djangoproject.com/browser/ ... fastcgi.py steht:
Und wenn ich das richtig sehe wird flup bei "threaded" aus server.fcgi und bei "prefork" aus server.fcgi_fork genommen, also:
"threaded" -> http://trac.saddi.com/flup/browser/flup/server/fcgi.py
"prefork" -> http://trac.saddi.com/flup/browser/flup ... gi_fork.py
Im Endeffekt wird dann das genutzt:
"threaded" -> http://trac.saddi.com/flup/browser/flup ... eadpool.py
"prefork" -> http://trac.saddi.com/flup/browser/flup ... kserver.py
Die DocStrings:
"prefork"
"threaded"
Also nach meinem Verständnis sollten bei "prefork" mehrere Prozesse mit jeweils einem Thread entstehen und bei "threaded" halt ein Prozess mit mehreren Threads, oder nicht?
Ich lasse ja, meine App per "threaded" laufen. Dennoch gibt es mehrere Prozesse, die immer 6 Threads haben...
Messe ich da vielleicht was falsches? Kann jemand mal https://github.com/jedie/django-processinfo/ probieren, ob er auf ähnliche Werte kommt?
EDIT: Hab gerade nochmal händisch nachgesehen. In /proc/$$/status steht halt Threads: 6 drin.
In https://code.djangoproject.com/browser/ ... fastcgi.py steht:
Code: Alles auswählen
maxspare=NUMBER max number of spare processes / threads.
minspare=NUMBER min number of spare processes / threads.
maxchildren=NUMBER hard limit number of processes / threads.
"threaded" -> http://trac.saddi.com/flup/browser/flup/server/fcgi.py
"prefork" -> http://trac.saddi.com/flup/browser/flup ... gi_fork.py
Im Endeffekt wird dann das genutzt:
"threaded" -> http://trac.saddi.com/flup/browser/flup ... eadpool.py
"prefork" -> http://trac.saddi.com/flup/browser/flup ... kserver.py
Die DocStrings:
"prefork"
Code: Alles auswählen
class PreforkServer(object):
"""
A preforked server model conceptually similar to Apache httpd(2). At
any given time, ensures there are at least minSpare children ready to
process new requests (up to a maximum of maxChildren children total).
If the number of idle children is ever above maxSpare, the extra
children are killed.
If maxRequests is positive, each child will only handle that many
requests in its lifetime before exiting.
...
"""
def __init__(self, minSpare=1, maxSpare=5, maxChildren=50,
maxRequests=0, jobClass=None, jobArgs=()):
...
Code: Alles auswählen
class ThreadPool(object):
"""
Thread pool that maintains the number of idle threads between
minSpare and maxSpare inclusive. By default, there is no limit on
the number of threads that can be started, but this can be controlled
by maxThreads.
"""
def __init__(self, minSpare=1, maxSpare=5, maxThreads=sys.maxint):
...
Also nach meinem Verständnis sollten bei "prefork" mehrere Prozesse mit jeweils einem Thread entstehen und bei "threaded" halt ein Prozess mit mehreren Threads, oder nicht?
Ich lasse ja, meine App per "threaded" laufen. Dennoch gibt es mehrere Prozesse, die immer 6 Threads haben...
Messe ich da vielleicht was falsches? Kann jemand mal https://github.com/jedie/django-processinfo/ probieren, ob er auf ähnliche Werte kommt?
EDIT: Hab gerade nochmal händisch nachgesehen. In /proc/$$/status steht halt Threads: 6 drin.
Wie misst du?jens hat geschrieben: Messe ich da vielleicht was falsches?
Nö, nimm doch bitte was ordentliches von dem du weißt dass es richtig tut.Kann jemand mal https://github.com/jedie/django-processinfo/ probieren, ob er auf ähnliche Werte kommt?
Dann passt das eh?EDIT: Hab gerade nochmal händisch nachgesehen. In /proc/$$/status steht halt Threads: 6 drin.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
https://github.com/jedie/django-processinfo/ geht halt auch hin und schaut sich den Thread Wert in /proc/$$/status an. Ich gehe davon aus, das der Wert darin auch richtig ist 
Gibt es sonst noch Wege die Anzahl der Threads zu ermitteln?

Gibt es sonst noch Wege die Anzahl der Threads zu ermitteln?
Gut dir mal folgendes an:
Thunderbird rennt, so weit so gut
thunderbird hat einige threads, spalte 3 is SPID
Ein Prozess mit SPID 3180 existiert nicht (wahllos aus der oberen Liste entnommen)
Dennoch existiert ein proc entry dafür, ich weiß jetzt nicht nach welchen Kriterien du /proc/ durchsuchst, aber kann sein, dass das bei dir Probleme verursacht?
Code: Alles auswählen
florian@apollo13:~$ ps -ef|grep thunderbird
florian 2708 2630 1 08:09 ? 00:00:49 /usr/lib/thunderbird-6.0/thunderbird-bin
Code: Alles auswählen
florian 5132 4999 0 09:32 pts/2 00:00:00 grep --color=auto thunderbird
florian@apollo13:~$ ps -ef -T|grep thunderbird
florian 2708 2708 2630 0 08:09 ? 00:00:46 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 2712 2630 0 08:09 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 2713 2630 0 08:09 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 2714 2630 0 08:09 ? 00:00:01 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 2715 2630 0 08:09 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 2716 2630 0 08:09 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 2717 2630 0 08:09 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 2718 2630 0 08:09 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 2719 2630 0 08:09 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 2720 2630 0 08:09 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3178 2630 0 08:18 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3180 2630 0 08:18 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3186 2630 0 08:18 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3194 2630 0 08:18 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3195 2630 0 08:18 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3196 2630 0 08:18 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3198 2630 0 08:18 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3199 2630 0 08:18 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3200 2630 0 08:18 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3201 2630 0 08:18 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3203 2630 0 08:18 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3206 2630 0 08:18 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3207 2630 0 08:18 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3209 2630 0 08:18 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3214 2630 0 08:18 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3283 2630 0 08:23 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3602 2630 0 08:28 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 3969 2630 0 08:42 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 2708 4383 2630 0 08:51 ? 00:00:00 /usr/lib/thunderbird-6.0/thunderbird-bin
florian 5134 5134 4999 0 09:32 pts/2 00:00:00 grep --color=auto thunderbird
Code: Alles auswählen
florian@apollo13:~$ ps -ef|grep 3180
florian 5138 4999 0 09:32 pts/2 00:00:00 grep --color=auto 3180
Code: Alles auswählen
florian@apollo13:~$ ls /proc/3180
attr auxv clear_refs comm cpuset environ fd io loginuid mem mounts net numa_maps oom_score pagemap root sessionid stack statm syscall wchan
autogroup cgroup cmdline coredump_filter cwd exe fdinfo limits maps mountinfo mountstats ns oom_adj oom_score_adj personality sched smaps stat status task
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
django-processinfo nimmt /proc/self/status
Bei mir ist die 3 Spalte nicht SPID, sondern PPID Beschriftet:
Keine Ahnung, was PPID ist, aber IMHO ist es: /proc/PID/status.
Also, z.B.:
Bei mir ist die 3 Spalte nicht SPID, sondern PPID Beschriftet:
Code: Alles auswählen
~$ ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 Jun28 ? 00:00:00 /sbin/init
...
Also, z.B.:
Code: Alles auswählen
~$ ps -ef|grep jedie
...
jedie 1927 4101 0 Aug30 ? 00:00:09 python index.fcgi
jedie 11488 4101 0 Aug29 ? 00:00:59 python index.fcgi
jedie 11489 4101 6 Aug29 ? 02:34:08 python index.fcgi
jedie 18913 4101 2 Aug30 ? 00:28:55 python index.fcgi
...
Code: Alles auswählen
~$ cat /proc/1927/status
Name: python
State: S (sleeping)
Tgid: 1927
Pid: 1927
PPid: 4101
...
Threads: 6
...
Code: Alles auswählen
~$ cat /proc/11488/status
Name: python
State: S (sleeping)
Tgid: 11488
Pid: 11488
PPid: 4101
...
Threads: 6
...
Du solltest lesen was ich schreibe, dann siehst du auch die SPID, PPID ist die Parent PID, SPID ist thread IDjens hat geschrieben: Bei mir ist die 3 Spalte nicht SPID, sondern PPID Beschriftet:Keine Ahnung, was PPID ist, aber IMHO ist es: /proc/PID/status.Code: Alles auswählen
~$ ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 Jun28 ? 00:00:00 /sbin/init ...
Das sagt dir, dass du 4 prozesse hat mit dem parent 4101. Ich würde einfach mal den flup source anschauen, was dort passiert… Aber die 6 Threads pro Process machen sinn mit deinem maxspare setting denk ich.Code: Alles auswählen
~$ ps -ef|grep jedie ... jedie 1927 4101 0 Aug30 ? 00:00:09 python index.fcgi jedie 11488 4101 0 Aug29 ? 00:00:59 python index.fcgi jedie 11489 4101 6 Aug29 ? 02:34:08 python index.fcgi jedie 18913 4101 2 Aug30 ? 00:28:55 python index.fcgi ...
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Das habe ich ja schon bei http://www.python-forum.de/viewtopic.ph ... 76#p206176 gemacht. Aber ich hab mir jetzt die Datei http://trac.saddi.com/flup/browser/flup ... eadpool.py näher angeschaut und das gefunden:apollo13 hat geschrieben:Ich würde einfach mal den flup source anschauen, was dort passiert… Aber die 6 Threads pro Process machen sinn mit deinem maxspare setting denk ich.
Code: Alles auswählen
53 # Start the minimum number of worker threads.
54 for i in range(maxSpare):
55 self._start_new_thread()
Später steht das im Code:
Code: Alles auswählen
90 # Maintain minimum number of spares.
91 while self._idleCount < self._minSpare and \
92 self._workerCount < self._maxThreads:
93 try:
94 self._start_new_thread()
95 except thread.error:
96 return False
97 self._workerCount += 1
98 self._idleCount += 1
Die flup Variable maxThreads kommt von Django's maxchildren.
Möchte ich also das Standartmäßig weniger Threads laufen, könnte ich die Angaben machen:
Code: Alles auswählen
maxspare=1 max number of spare processes / threads.
minspare=1 min number of spare processes / threads.
maxchildren=10 hard limit number of processes / threads.
EDIT: Ja, es scheint so zu sein. Allerdings starten mit den obrigen Werte nicht ein Thread, sondern mindestens zwei. Anscheinend also immer einer mehr, als angegeben ist. Ist es vielleicht ein "main-Flup-Thread" der dann die eigentliche App als Thread startet?
Was ich außerdem komisch finde: Es werden neben den mehreren Threads auch mehrere Prozesse gestartet. Woher kommen die? Startet Apache mehrere fcgi Prozesse, bei Last?
Ist nur educated guessing, aber auf beide fragen: ja. Im Grunde baut man jeden Server so, dass man einen zentralen Prozess/Thread hat, der Anfragen entgegen nimmt. Und dann einen Worker-Prozess/Thread mit der Abarbeitung beauftragt. Wie sonst willst du mehrere eingehende Anfragen bearbeiten?jens hat geschrieben:Ja, es scheint so zu sein. Allerdings starten mit den obrigen Werte nicht ein Thread, sondern mindestens zwei. Anscheinend also immer einer mehr, als angegeben ist. Ist es vielleicht ein "main-Flup-Thread" der dann die eigentliche App als Thread startet?
Was ich außerdem komisch finde: Es werden neben den mehreren Threads auch mehrere Prozesse gestartet. Woher kommen die? Startet Apache mehrere fcgi Prozesse, bei Last?
Und Apache wird auch pro Prozess den er selbst startet einen FCGI-Prozess starten. Sonst muesste man ja irgendwie kompliziert Pipe-File-Deskriptoren durch die Gegend reichen (was uU gar nicht geht), und dann auch noch eine Queue oder sowas implementieren.
Schau nach ob einer deiner Threads nicht vlt der Managementprozess istjens hat geschrieben: EDIT: Ja, es scheint so zu sein. Allerdings starten mit den obrigen Werte nicht ein Thread, sondern mindestens zwei. Anscheinend also immer einer mehr, als angegeben ist. Ist es vielleicht ein "main-Flup-Thread" der dann die eigentliche App als Thread startet?
Das hängt wohl von der genauen apache config ab (möglichweise auf je mpm etc…)Was ich außerdem komisch finde: Es werden neben den mehreren Threads auch mehrere Prozesse gestartet. Woher kommen die? Startet Apache mehrere fcgi Prozesse, bei Last?
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Im IRC hab ich nun aufgeschnappt, das flup einfach Mist ist
Als Alternative zu fastCGI gäbe es da noch:
http://pypi.python.org/pypi/python-fastcgi/
http://pypi.python.org/pypi/fcgi-python/
Was nutzt eigentlich ihr so? Kein fastCGI nur noch mod_WSGI?

Als Alternative zu fastCGI gäbe es da noch:
http://pypi.python.org/pypi/python-fastcgi/
http://pypi.python.org/pypi/fcgi-python/
Was nutzt eigentlich ihr so? Kein fastCGI nur noch mod_WSGI?
- noisefloor
- User
- Beiträge: 4178
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
mod_wsgi.
Gruß, noisefloor
mod_wsgi.
Gruß, noisefloor
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Hängt ab, vielleicht mod_wsgi, vielleicht GEvent, Gunicorn oder uWSGI. Müsste ich dann erstmal ausführlicher evaluieren. Die einfachste Route wäre vermutlich mod_wsgi wenn ich eh Apache nutze.jens hat geschrieben:Statt dessen dann was?Leonidas hat geschrieben:Ja, würde bei neueren Deployments auch kein FastCGI mehr nutzen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Läuft seit dem sehr gutjens hat geschrieben:Bin gerade dabei einen neuen Server mit nginx und Gunicorn einzurichten. Mal sehen wie gut das läuft...

Hab gerade Informationen dazu zusammen gesammelt: http://www.pylucid.org/permalink/411/ru ... d-gunicorn
Frage mich allerdings gerade, wo ich am besten ein ./gunicorn.sh start einfügen soll, damit der WSGI Prozess direkt nach dem Booten startet...