Возьмем для примера скрипт:
import BaseHTTPServer
import time
from SocketServer import ThreadingMixIn
tpl = """<html>
<body>
<p><a href="/stop">stop it!</a></p>
</body>
</html>"""
class ThreadingHTTPServer(ThreadingMixIn, BaseHTTPServer.HTTPServer):
pass
class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
global RUN
if self.path != "/":
if self.path == "/stop":
print "STOP!"
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write("Server stopped")
RUN = False
return
self.send_error(404, "File not found")
return
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(tpl)
#time.sleep(1)
class FBServer(ThreadingHTTPServer):
def __init__(self, *a, **k):
ThreadingHTTPServer.__init__(self, *a, **k)
self.pathHandlers = {}
def registerPathHandler(self, path, func):
self.pathHandlers.append[path] = func
PORT = 8000
RUN = True
httpd = ThreadingHTTPServer(("", PORT), Handler)
print "serving at port", PORT
while(RUN):
httpd.handle_request()
print "stop serving"
На самом деле я написал немного более другой скрипт, там я фактически реализовал http-сервер с нуля (используя только низкоуровневые модули типа socket, thread, threading).
Короче парочка сравнительных тестов этого скрипта (скажу сразу, мой работает медленнее, что странно) с апачем (понимаю что звучит смешновато но все же…)
Использовалась утилита ab (Apache Benchmark) из поставки апача
ab -n 900 -c 50 "http://127.0.0.1/fghfhfh" (тут запущен апач)
результат:
Server Software: Apache/2.0.59
Requests per second: 800.00 (mean)
Time per request: 62.500 (mean)
Time per request: 1.250 (mean, across all concurrent requests)
ab -n 900 -c 50 "http://127.0.0.1:8000/fghfhfh" (тут работает наш скрипт)
результат:
Server Software: BaseHTTP/0.3
Requests per second: 20.85 (mean)
Time per request: 2398.438 (mean)
Time per request: 47.969 (mean, across all concurrent requests)
При этом когда ставим -с 1 (т.е. конкурентных соединений всего 1) то питон отрабатывает 100 запросов\сек, апач 116 запросов\сек
Заметил явственно следующие 2 закономерности:
1) Питоновский скрипт никогда (за все время тестирования ab) не занимает более ~20% CPU-usage, обычно единицы процента, что мне показалось очень странным, при этом апач при большой конкурентности доходит до 100%. ПОЧЕМУ ТАК?
2) Реальное число потоков скрипта очень мало 2-4 максимум десяток, при этом апач может дать 50 и более (наблюдалась колонка в Диспечере задач виндовс). ПОЧЕМУ ?
Конечно тут может последовать оговорка: не рекомендуется запускать для тестирования ab на одном компе с серваком. Но думается это слабо на что то влияет.
Так ли плоха многопоточнось питона. Возможно это GIL (Global interpreter lock) так пагубно влияет?
Не ужели идея написания на питоне простого, быстрого, очень узкоспециализированного http-сервера обречена на провал?