Comments 30
Спасибо, статья очень помогла!
Production server я бы перевёл как «рабочий сервер», в отличии от «сервера разработки» и «сервера сборки».
Существуют чудесные фреймворки для разработки асинхронных приложений, такие как twisted — они позволяют абстрагироваться от деталей select/poll/epoll/что-там-еще-придумали-на-данной-платформе.
> разрыв происходит не сразу же, а после нескольких последовательных таких холостых срабатываний, чтобы исключить возможность ошибочного определения.
Немного не понял Вашу мысль. Если epoll возвращает EPOLLIN, значит на сокете гарантированно есть события. Если данных нет, а событие есть — значит клиент закрыл соединение. Зачем тут делать лишние системные вызовы, это ведь, как-никак, лишние переключения контекста и трата ресурсов?
Немного не понял Вашу мысль. Если epoll возвращает EPOLLIN, значит на сокете гарантированно есть события. Если данных нет, а событие есть — значит клиент закрыл соединение. Зачем тут делать лишние системные вызовы, это ведь, как-никак, лишние переключения контекста и трата ресурсов?
В примерах данной статьи нет смысла использовать epoll вообще, так как мы сами блокируем сокет в строке
responses[connection.fileno()] = response
Мы не выходим из этой строки до тех пор пока не запишем в нее наш response. Те пока сервер пишет одному клиенту, он не обсуживает других. Убедится в этом можно записал в response строку на пару мегабайт, запустить сервер где нибудь не на локалхосте что бы скорость была не высока, а затем открыть две вкладки — сервер будет отвечеть только в одну из них, и только завершив, начнет во вторую. Те сокеты то ты опрашивем без форков, но конкурентой обработки в коде нет.
responses[connection.fileno()] = response
Мы не выходим из этой строки до тех пор пока не запишем в нее наш response. Те пока сервер пишет одному клиенту, он не обсуживает других. Убедится в этом можно записал в response строку на пару мегабайт, запустить сервер где нибудь не на локалхосте что бы скорость была не высока, а затем открыть две вкладки — сервер будет отвечеть только в одну из них, и только завершив, начнет во вторую. Те сокеты то ты опрашивем без форков, но конкурентой обработки в коде нет.
Все даже хуже оказалось, такак сокет не может быть готовым отправлять данные все время, то даже строку в 100кб пример передать не может, соединение рвется в призвольные моменты, ну и заблокированым остается как я и описал выше.
Что-то не то вы говорите по-моему
Сейчас потестирую…
responses[connection.fileno()] = response — тут вроде вообще работы с сокетом не наблюдается.Сейчас потестирую…
response_body = b'Hello, world!'*100000
response = b'HTTP/1.0 200 OK\r\nDate: Mon, 1 Jan 1996 01:01:01 GMT\r\n'
response += b'Content-Type: text/plain\r\nContent-Length: '+str(len(response_body))+b'\r\n\r\n'
response += response_bodyИ длину очереди повыше постваил
serversocket.listen(50). Результат:$ ab -n 5000 -c 200 http://localhost:8081/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 500 requests
Completed 1000 requests
Completed 1500 requests
Completed 2000 requests
Completed 2500 requests
Completed 3000 requests
Completed 3500 requests
Completed 4000 requests
Completed 4500 requests
Completed 5000 requests
Finished 5000 requests
Server Software:
Server Hostname: localhost
Server Port: 8081
Document Path: /
Document Length: 1300000 bytes
Concurrency Level: 200
Time taken for tests: 23.696 seconds
Complete requests: 5000
Failed requests: 0
Write errors: 0
Total transferred: 6500530000 bytes
HTML transferred: 6500000000 bytes
Requests per second: 211.01 [#/sec] (mean)
Time per request: 947.830 [ms] (mean)
Time per request: 4.739 [ms] (mean, across all concurrent requests)
Transfer rate: 267903.43 [Kbytes/sec] received
Connection Times (ms)
min mean[±sd] median max
Connect: 0 134 956.2 0 9024
Processing: 136 293 474.7 212 13151
Waiting: 5 213 410.9 180 13140
Total: 137 427 1223.4 212 22161
Percentage of the requests served within a certain time (ms)
50% 212
66% 223
75% 231
80% 236
90% 257
95% 1477
98% 3231
99% 6137
100% 22161 (longest request)
Если -c побольше ставить, то может и вывалиться
Дело не в валится/не валится. Вы запустите сервер, запустите ab как и делали. Потом в новом терминале запустите wget на этот же URL. Я ни разу не получил полный ответ, т.е. Hello, world!' повторенный 100 тыс раз.
Пруфпик:

Может Content-length неправильно прописали?

Может Content-length неправильно прописали?
Правильно, видимо дело в версии питона. На 2.6.6 рвется на 3.2.1rc1 — работает.
Я на 2.7.1 запускал. Попробовал 2.6 — тоже нормально.
Но вообще довольно нестабильно работает 3-й пример. Например после отработки ab скрипт впадает в бесконечный цикл (т.е. i очень быстро инкрементируется, но при этом нормально отвечает на запросы). Если добавить код из примечаний переводчика (
Ну и вылетает при высокой параллельности — нужно очередь увеличивать.
Но вообще довольно нестабильно работает 3-й пример. Например после отработки ab скрипт впадает в бесконечный цикл (т.е. i очень быстро инкрементируется, но при этом нормально отвечает на запросы). Если добавить код из примечаний переводчика (
if not data:) то ок.Ну и вылетает при высокой параллельности — нужно очередь увеличивать.
Извиняюсь за глупый вопрос, но что значит b перед строкой?
Шикарно. Сэкономили кучу времени, спасибо.
Пардон, в статью пока некогда вникать сейчас, просто хочу заметить, что можно перевести «production server», как боевой сервер. Может и не совсем официально звучит, но суть отражает.
Спасибо, тема интересная. Но примеры очень сложно читать и понимать т.к. комментарии находятся далеко от кода. Понимаю что перевод, но может встроить комментарии прям в код — как обычные питоньи комментарии?
Если будут еще желающие на такой вариант и не будет, соответственно, армии противников — сделаю.
Писать комментарии к строчкам кода отдельно от кода используя нумерацию — это очень жестоко по отношению к читателям. Первые примеры еще более-менее воспринимаются, так как кода и комментариев мало и есть возможность охватить их почти без скроллинга страницы. Но вот третий пример — совершенно нечитаемый. В итоге просто прочитал комментарии, а потом просмотрел код. Как-то пытаться их соотносить по номерам — развлечение для особо терпеливых и собранных.
Если не трудно, поясните, для чего так было сделано?
Если не трудно, поясните, для чего так было сделано?
В таком формате написан оригинал. Решил не менять уж порядка вещей, так как это перевод, а не пересказ.
Интересно можно ли использовать метод epoll что бы написать неблокирующий клиент используя httplib или urllib2, те делаем запросы сразу N URL,
получаем дескриптор сокета от данного объекта HTTPResponse.fileno() и засовываем в epoll.register
получаем дескриптор сокета от данного объекта HTTPResponse.fileno() и засовываем в epoll.register
Sign up to leave a comment.
Как применять Linux epoll в Python