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