multithread webserver probleme

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Lambda
User
Beiträge: 25
Registriert: Freitag 27. April 2007, 17:11

Code: Alles auswählen

import SocketServer, socket, BaseHTTPServer, os

def cacheFile(datei):
	return open(datei, 'rb').read()

_bild = cacheFile('%s/htdocs/wow.jpg' % os.getcwd())
_html = '''<html>
	<head>
		<link rel="stylesheet" href="style/style.css" type="text/css" />
	</head>

	<body>
		<img src="/wow.jpg" alt="Europa-Release" title="Europa-Release" align="absmiddle" />
		<p>Hello World!</p>
	</body>
</html>'''
_css = 'body {font-family:arial,sans-serif; background-color: #000000; color: #FFFFFF}'

class MyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
	protocol_version = 'HTTP/1.1'
	
	def do_GET(self):
		print 'neuer thread'
		if self.path == '/dev':
			self.send_stream(_html, 'text/html', 200, 'Keep-Alive')
			self.send_stream(_css, 'text/css', 200, 'Keep-Alive')
			self.send_stream(_bild, 'image/jpeg', 200, 'close')
		elif self.path == '/style/style.css':
			#self.send_stream(_css, 'text/css', 200, 'close')
			#print 'style.css'
			pass
		elif self.path == '/wow.jpg':
			#self.send_stream(_bild, 'image/jpeg', 200, 'close')
			#print 'wow.jpg'
			pass
		else:
			self.send_stream('Error 404 - File not found!', 'text/html', 404)

	#def handle(self):
	#	print 'handle do it'
	#	print self.protocol_version
	#	self.send_stream(_html, 'text/html', 200)

	def send_stream(self, stream, mimetype, code, connection):
		self.send_response(code)
		self.send_header('Content-type', mimetype)
		self.send_header('Content-Length', str(len(stream)))
		self.send_header('Connection', connection)
		self.end_headers()
		self.wfile.write(stream)
		self.wfile.flush()

	def send_text(self, text, mimetype='text/html', code=200):
		self.send_response(code)
		self.send_header('Content-type', mimetype)
		self.send_header('Content-Length', str(len(text)))
		self.end_headers()
		self.wfile.write(text)
		self.wfile.flush()

class MyThreadingServer(SocketServer.ThreadingTCPServer):
	def __init__(self, server_address, request_handler, AllowIPs):
		SocketServer.ThreadingTCPServer.__init__(self, server_address, request_handler)
		self.AllowIPs = [mask.split('.') for mask in AllowIPs]

	def server_bind(self):
		SocketServer.ThreadingTCPServer.server_bind(self)
		host, self.server_port = self.socket.getsockname()[:2]
		self.server_name = socket.getfqdn(host)

	def verify_request(self, dummy, client_address):
		def check_ip(mask):
			for mask_part, ip_part in zip(mask, ip):
				if mask_part != ip_part and mask_part != '*':
					return False
			return True
		ip = client_address[0].split('.')
		for mask in self.AllowIPs:
			if check_ip(mask):
				return True
		print "IP [%s] not allowed!" % client_address
		return False

def ServerStart(ListenPort, AllowIPs):
	print "Starte HTTP-Server auf Port .:", ListenPort
	print "Zugelassener IP-Bereich .....:", AllowIPs
	httpd = MyThreadingServer(("", ListenPort), MyRequestHandler, AllowIPs)
	httpd.serve_forever()

if __name__=="__main__":
	ServerStart(ListenPort=6667, AllowIPs=('*.*.*.*'))
der aktuelle code dank euch :) leider funktioniert es nicht wirklich, habe mir bissel im netz bezüglich Connection: keel-alive durchgelesen (http://www.http.header.free.fr/http.html) und das schheint richtig zu sein, nur scheint es dem BaseHTTP handler nicht zu interessieren, und die methode handle() verstehe ich nicht wirklich also wie ich die benutzen soll...
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hallo Lambda!

Ich weiß noch nicht um was es dir genau geht, aber wenn du einen superschnellen Webserver mit Python programmieren möchtest, dann sollte ich dir sagen: "Das geht nicht." :wink:

Nimm stattdessen den Apachen: http://httpd.apache.org/

Was ist es, was du brauchst und warum willst du einen Webserver programmieren? Ist es wegen der Prüfung der Client-IP? --> http://httpd.apache.org/docs/2.2/de/mod ... _host.html

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Lambda
User
Beiträge: 25
Registriert: Freitag 27. April 2007, 17:11

naja mir gings darum was ich ne alternative für php gesucht habe. dann hatte ich mich mit wsgi beschäftigt, was allerdings nicht so einfach ist da es umständlicher ist als mit basehttpserver dahinterzusteigen wie es funktioniert.
gegen den apache hätte ich nichts, bloß ich habs mal nach nem tip mit SCGI versucht, hab ich bisher nicht zum laufen gebracht.
ich dachte mir ein python webserver mit ohne viel schnickschnack wäre ausreichend schnell, vorallem da ich vor habe alle .html dateien und die resourcen wie bilder im arbeitsspeicher zu cachen (videos, flashfilme, java-applets etc. allerdings nicht) und bei meiner webseiten größe von nichtmal 10-15mb macht mir das nix aus.
den webserver wollte ich nun programmieren der einfachheit halber, da ich finde das wsgi fürn anfänger nicht ideal ist, da man nicht wirklich lernt son webserver/gateway funzt und tutorials sind auch mangelware.

bei meinem letzten post wollte ich nun wissen wie das möglich ist mehere request in einem thread zu behandeln, also sprich wenn jemand XXX.html aufruft, das ich automatisch die .jpg etc. mitsende und somit für jedes bild ein thread spare.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Lambda hat geschrieben:gegen den apache hätte ich nichts
[...]
den webserver wollte ich nun programmieren der einfachheit halber, da ich finde das wsgi fürn anfänger nicht ideal ist
[...]
bei meinem letzten post wollte ich nun wissen wie das möglich ist mehere request in einem thread zu behandeln
Hallo Lambda!

Das sind jetzt fast schon zu viele Fragen auf einem Haufen. Ich hoffe ich verzettle mich nicht beim Antworten...

1.) Der Apache ist ein **sehr schneller** Webserver, der mit vielen gleichzeitigen Anfragen klar kommt und mit der Zeit immer besser wurde. Es wurden Vorkehrungen getroffen, um DOS-Attacken besser zu überstehen, er wurde sicherer und schneller. Es wurden Möglichkeiten geschaffen, Daten im Speicher und auf der Festplatte zu cachen. Sogar als Proxy kann er eingesetzt werden. Der Apache ist, in meinen Augen, der Webserver schlechthin. Auch wenn es einfachere Webserver geben sollte, die evt. auch etwas schneller sind, so ist der Apache als Gesamtpaket sehr ausgereift und kaum zu schlagen.

Wenn du also eine Website auf dem Apachen laufen lassen kannst, dann tu es. Du wirst nicht so schnell etwas Besseres finden.

2.) Man programmiert sich keinen Webserver, nur weil man Python als Skriptsprache für Internetanwendungen einsetzen will. Es gibt viele tausende fertige Lösungen. Ich muss nur wissen, was erwartet wird und schon kann ich dich zu einer erprobten Lösung führen.

Um das Ganze mal zu konkretisieren:

Verwende z.B. Zope und Plone, wenn du ein fertiges Content Management System verwenden willst.

Verwende CGI unter dem Apachen oder mit dem Python-SimpleHTTPServer, um in einfache Seiten ein wenig Dynamik zu bringen. Ich finde sowieso, dass es keinen besseren Einstieg in die Webprogrammierung mit Python gibt, als sich erst mal mit CGI zu befassen. Pfeif zuerst mal auf Geschwindigkeit. Schau erst mal, dass du **irgendetwas** zum Laufen bekommst.

- http://www.python.org/doc/current/lib/module-cgi.html
- [wiki]CGI[/wiki]
- [wiki]XAMPP mit Python CGI[/wiki]

Dieser CGI-Server http://www.python-forum.de/post-23648.html#23648 ist schon so programmiert, dass er mit Threads arbeitet. Versuche nicht ihn zu optimieren, bevor du deine Anwendung nicht fertig gestellt hast.

Zum Thema Geschwindigkeit: Der Apache bietet einige Möglichkeiten an, Daten zu cachen. Statischer Content fühlt sich im Memory-Cache ziemlich wohl. Dynamischer Inhalt, kann so eingestellt werden, dass dieser ständig neu erstellt wird, falls das nötig ist, oder sich alle paar Minuten/Stunden/Tage erneuert. Man sollte sich zuerst mal darauf konzentrieren, dass die Anwendung funktioniert und erst dann mit der Geschwindigkeit befassen, wenn man merkt dass etwas zu langsam ist. So spart man sich viele, viele, viele unnötige Programmiertage.

Es gibt da auch noch Karrigell. http://karrigell.sourceforge.net/
Karrigell ist genau so etwas, was du zu programmieren versuchst. Es ist ein Python-Webserver, der wunderbar mit Python klar kommt. Karrigell ist von sich aus schon nicht langsam. Aber Karrigell kann, wie jeder andere Webserver, **hinter** einem Apachen betrieben werden. Der Apache kümmert sich dann um das Caching und entlastet damit Karrigell. Das ist wirklich schnell. Überhaupt dann, wenn man statischen Content direkt vom Apachen ausliefern lässt. Aber auch das ist erst dann notwendig, wenn man merkt, dass die Website zu langsam wird. ;-)

- http://www.python-forum.de/topic-9077.html

3.) Thema Multithreading mit dem BaseHTTPServer:
Schon das einfachste Programm, das statt dem "SocketServer.TCPServer" den "SocketServer.ThreadingTCPServer" verwendet, arbeitet mit Threads. Du musst dich um fast NICHTS mehr kümmern. Wichtig ist nur, dass du nicht schreibend von mehreren Threads aus auf die gleichen Objekte zugreifst, wenn diese nicht speziell "thread-safe" sind. Wie ich schon erklärte, meine ich damit schreibenden Zugriff auf globale Variablen genau so wie den schreibenden Zugriff auf File-Objekte, usw.

Es ist komplett ungefährlich, wenn du von mehreren Threads aus auf die gleichen Daten "lesend" zugreifst.

Es ist GUT, wenn die einzelnen Requests in einzelnen Threads abgearbeitet werden. Es gibt keinen Grund, weshalb du dich da einmischen solltest. Jeder Job in einem eigenen Thread -- und gut. Versuche nicht erst irgendwelche Jobs wieder in einen Thread zusammenzulegen. Damit drehst du dich nur im Kreis.

Wenn zehn Leute gleichzeitig deine Website ansehen, dann werden nicht alle zehn Leute gleichzeitig auf einen Link klicken. Du kannst also davon ausgehen, dass wenn zehn Leute deine Website ansehen, dass (geschätzt) im Durchschnitt nur zwei gleichzeitige Requests abzuarbeiten sind. Das ist lächerlich wenig. Meine Website schauen sich täglich ca. 100 Leute an. Aber auf einen ganzen Tag verteilt ist das *nichts*. Ich habe es mit 500 bis 3000 Hits am Tag zu tun. Was sind schon 3000 Requests. Bei einem 10-Stunden Tag wären das 5 Requests pro Minute.

Apache: Schnell bei wenigen gleichzeitigen Zugriffen und schnell bei vielen gleichzeitigen Zugriffen.
CGI: Schnell genug bei wenigen gleichzeitigen Zugriffen. Wird langsamer bei mehreren gleichzeitigen Zugriffen.
Karrigell: Schnell bei wenigen gleichzeitigen Zugriffen. Wird langsamer bei mehreren gleichzeitigen Zugriffen.

Erst dann, wenn die Website zu langsam wird -- und nur dann -- solltest du dir Gedanken über die Beschleunigung machen. In den allermeisten Fällen genügt ein wenig Caching.

Edit: Fast hätte ich es vergessen:
HTTP/1.1 sieht als Standard vor, dass der Client eine Verbindung aufbaut und diese so lange offen hält, bis der Webserver im Header "Connection" "close" zurück gibt. Es braucht, meines Wissens, keine zusätzliche Aktion dafür.

Wenn der Server "Connection" "close" nicht zurück gibt, dann wird die Verbindung sowiso vom Server getrennt. Es ist also nicht unbedingt notwendig, sich um "Connection" "close" zu kümmern, aber es ist auch nicht schlecht.

Der Client ist dafür zuständig, die Verbindung aufrecht zu erhalten und die Requests über diese Verbindung zu übergeben. Der Server muss sich nicht besonders darum kümmern. Wenn der Client HTTP/1.1 kann, dann wird er es auch damit versuchen und erst dann auf HTTP/1.0 zurück schalten, wenn der Server nicht korrekt auf die HTTP/1.1-Anfrage reagiert.

Was ich damit sagen will? Dein Server kümmert sich eh schon automatisch um alles. Du musst nichts mehr dazuprogrammieren. Zumindest habe ich es so verstanden und man möge mich ausbessern, falls ich falsch liege.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

gerold hat geschrieben:1.) Der Apache ist ein **sehr schneller** Webserver, der mit vielen gleichzeitigen Anfragen klar kommt und mit der Zeit immer besser wurde. Es wurden Vorkehrungen getroffen, um DOS-Attacken besser zu überstehen, er wurde sicherer und schneller. Es wurden Möglichkeiten geschaffen, Daten im Speicher und auf der Festplatte zu cachen. Sogar als Proxy kann er eingesetzt werden. Der Apache ist, in meinen Augen, der Webserver schlechthin. Auch wenn es einfachere Webserver geben sollte, die evt. auch etwas schneller sind, so ist der Apache als Gesamtpaket sehr ausgereift und kaum zu schlagen.
Apache ist laut diversen Benchmarks einer der langsameren Server [1][2][3], wobei er insbesondere bei statischen Dateien oft hinterher ist (habe irgnedwo einen Vergleich mit gatling gesehen). Hängt aber auch von seiner Konfiguration ab. In aller Regel ist er aber ausreichend schnell. Apaches Vorteil ist in meinen Augen die hohe Akzeptanz und die vielen Features. Wobei ich zugeben muss, dass Lighttpds Unterstützung für FastCGI und SCGI direkt vom Upstream kommt und daher besser maintained wird. Zu testen wäre auch nginx, aber damit habe ich im Moment keinerlei Erfahrungen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Leonidas hat geschrieben:
gerold hat geschrieben:1.) Der Apache ist ein **sehr schneller** Webserver, der mit vielen gleichzeitigen Anfragen klar kommt und [...]
Apache ist laut diversen Benchmarks einer der langsameren Server [1][2][3], wobei er insbesondere bei statischen Dateien oft hinterher ist[...]
Hallo Leonidas!

:wink: Ich wage zu bezweifeln, dass in den Tests der Apache auf Geschwindigkeit getrimmt war und dass alle für die Tests unnötigen Module deaktiviert wurden. Ich schrieb ja auch, dass der Apache sich von DOS-Angriffen nicht so schnell in die Knie zwingen lässt. Ein Ansatz dafür ist, dass man auf sehr viele Anfragen von einer IP-Adresse langsamer reagiert. Ob das jetzt speziell auch der Fall bei den Benchmarks ist, kann ich nicht sagen, aber ich vermute es. -- Ich muss ja meine Aussage ein wenig verteidigen. :lol:

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

gerold hat geschrieben:Ich finde sowieso, dass es keinen besseren Einstieg in die Webprogrammierung mit Python gibt, als sich erst mal mit CGI zu befassen.
Das sehe ich auch so! CGI ist kein Jet mit Nachbrenner, aber es ist relativ direkt und man lernt sehr viel wichtiges Grundwissen zu Webservern, CGI, HTTP und mehr, das später oft hilfreich ist. Und wenn man ohnehin erst mit der Webprogrammierung anfängt, wird man kaum eine Website haben, die über CGI an Grenzen stößt.


Zu Lighttpd werfe ich noch Cherokee ins Rennen, der scheinbar etwas jünger ist, aber sonst vergleichbar (IIRC: "schnell", bringt FastCGI und SCGI mit, gleiche hässliche Config-Syntax wie Lighty). Hab ich ebenfalls installiert und er wartet ebenso wie Lighty darauf, genauer getestet zu werden. Letztlich macht man aber mit Apache auch nichts falsch.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Y0Gi hat geschrieben:Das sehe ich auch so! CGI ist kein Jet mit Nachbrenner, aber es ist relativ direkt und man lernt sehr viel wichtiges Grundwissen zu Webservern, CGI, HTTP und mehr, das später oft hilfreich ist. Und wenn man ohnehin erst mit der Webprogrammierung anfängt, wird man kaum eine Website haben, die über CGI an Grenzen stößt.
Man kann aber auch CGI mit WSGI nutzen. Das ist leider doch nicht ganz so gut dokumentiert, aber nach dem Hallo-Welt-CGI-Script sollte man wirklich bedenken WSGI zu verwenden. Schon allein wenn man schaut, was man als Middleware gratis dazubekommt ist es nützlich.
Y0Gi hat geschrieben:Zu Lighttpd werfe ich noch Cherokee ins Rennen, der scheinbar etwas jünger ist, aber sonst vergleichbar (IIRC: "schnell", bringt FastCGI und SCGI mit, gleiche hässliche Config-Syntax wie Lighty). Hab ich ebenfalls installiert und er wartet ebenso wie Lighty darauf, genauer getestet zu werden. Letztlich macht man aber mit Apache auch nichts falsch.
Wenn man nach "Cherokee HTTPD" sucht, bekommt man erstmal eine Menge Vulnerabilities. Die Homepage zu finden ist nicht ganz so einfach, aber sie sieht nicht übel aus (auch von den dort beschriebenen Features). Interessant warum man von dem so wenig hört. Und die Lighttpd ist gar nicht mal so übel, mit dem =~ Operator kann man einige Sachen ganz hübsch konfigurieren. Insgesamt erinnert mich die Syntax eher an eine Programmiersprache denn an eine ``httpd.conf``, finde ich als Programmierer aber akzeptabel.

Letztendlich muss jeder den HTTPd wählen der ihm passt - Apache ist keine schlechte Wahl. Lighttpd auch nicht und wie nginx und Cheerokee abschneiden werden Y0Gi und ich wohl noch schauen müssen :)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Leonidas hat geschrieben:Man kann aber auch CGI mit WSGI nutzen.
Ich bin nicht sicher, welche Richtung du meinst, aber meines Wissens geht es in beide: Man kann sowohl WSGI-Applikationen über CGI deployen (mit entsprechenden Einschränkungen) als auch CGI-Scripte als WSGI-Applikation wrappen (ich meine bei Paste mal was derartiges gesehen zu haben).
Lambda
User
Beiträge: 25
Registriert: Freitag 27. April 2007, 17:11

danke erstmal für die replys. ich werde mir jetzt paralell CGI anschauen, allerdings werde ich den server weitermachen, ich werde dann nen performance test machen. für kleine projekte werde ich auf jedenfall meinen eignen python webserver verweden, der einfachheit halber.

nun zu CGI, da hätte ich noch paar fragen:

- CGI soll bei vielen connections langsamer sein, empfiehlt sich dann FCGI oder SCGI?
- Wo sind die unterschiede zwischen FCGI und SCGI, gibts da performance unterschiede?
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

CGI ist deshalb langsamer, weil für jeden Request eine neue Interpreter-Instanz gestartet wird.

FastCGI ist älter als SCGI, letzteres verwendet ein simpleres Interface. Letztlich nehmen sich aber beide praktisch wenig.
Lambda
User
Beiträge: 25
Registriert: Freitag 27. April 2007, 17:11

vielen dank :)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Lambda hat geschrieben:- CGI soll bei vielen connections langsamer sein, empfiehlt sich dann FCGI oder SCGI?
CGI ist definitiv bei vielen Requests signifikant langsamer als FasttCGI oder SCGI (mit denen es bis auf den Namen kaum etwas zu tun hat). Es wird für jeden Request ein Interpreter gestartet, der eben die Entsprechende Vorlaufzeit benötigt. Das ist auch ein Grund, warum niemand Java über CGI verwendet, weil die Vorlaufzeit der Java-VM noch weitaus größer ist, als die der Python-VM.
Lambda hat geschrieben:- Wo sind die unterschiede zwischen FCGI und SCGI, gibts da performance unterschiede?
Performance-Unterschiede gibt es kaum, aber FastCGI ist älter und etwas komplizierter konzipiert. Aber über WSGI verhalten sich beide gleich. Letztendlich hängt die Wahl von deinem Webserver ab: FastCGI ist weit verbreitet, fast jeder Server hat zumindest ein Modul dafür (auch wenn beispielsweise die Module im Fall Apache nicht optimal maintained werden), SCGI hat dagegen eine noch etwas geringere Unterstützung, was sich aber langsam ändert.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten