SlideShare a Scribd company logo
Асинхронное
программирование в
Python
Проблема C10K
• Условное название задачи конфигурирования и
обслуживания высокопроизводительного
сервера
• Сервер должен быть способен обслуживать
порядка 10 тыс. соединений одновременно
Проблема C10K
• Решение №1
• Поток на каждого клиента
• Решение №2
• Поток на несколько клиентов
Сервера, выдерживающие
проблему
• nginx, which relies on an event-driven (asynchronous) architecture, instead
of threads, to handle requests
• Lighttpd, which relies on an asynchronous architecture to handle requests
• Tornado, a non-blocking web server and web application framework
written in Python (used by Facebook's FriendFeed)
• Apache AWF (retired, formerly Apache Deft), asynchronous, non-blocking
web server running on the JVM
• JBoss Netty, a NIO client server framework which enables quick and easy
development of network applications such as protocol servers and clients
• Node.js, asynchronous, non-blocking web server running on Google's V8
JavaScript engine
Сервера, выдерживающие
проблему
• EventMachine, an asynchronous, non-blocking web
server running on Ruby EventMachine
• Cowboy (web server), another very lightweight web
server written in Erlang
• asyncore (in the standard Python library), a non-
blocking web server library. It is based on Medusa,
which is no longer maintained.
• Django, some research is being done using the
asynchronous IO support in Python 3.3
sync VS async
Sync
• Делится на однопоточную и многопоточную.
Sync: 1 thread
• В однопоточной модели каждая задача
выполняется последовательно. Поток выполняет
следующую задачу только тогда, когда
предыдущая точно завершилась.
Sync: N threads
• В многопоточной модели можно достичь
некоторой "одновременной работы" задач, но на
каждую задачу выделяется один поток. Деталями
управления в многопоточной синхронной модели
управляет ОС.
Async
• Асинхронная модель всегда будет чередовать
выполнение задач. Взаимодействие задач (их
синхронизация) лежит на ответственности
программиста.
sync VS async
• По сравнению с синхронной моделью, асинхронная
модель лучше когда:
1. Когда есть много задач таких, что почти всегда есть по
меньшей мере одна задача, которая может выполняться.
2. Задачи выполняют много операций ввода-вывода,
приводя к тому, что синхронная задача проводит много
времени впустую, блокируясь, в то время когда другие
задачи могли бы выполняться.
3. Задачи независимы друг от друга и не нуждаются во
взаимодействии.
Event-driven programming
• Событийно-ориентированное программирование
• Способ построения программы
• В коде явным образом выделяется главный цикл
приложения
• Тело главного цикла состоит из двух частей:
выборки события и обработки события.
Reactor
• Для ожидания задач и
управления ими, используется
внешний цикл, который
постоянно ждет каких-либо
действий.
• При возникновении задачи, он
немедленно реагирует.
• Каждая задача должна быть в
не блокирующем режиме. какой смысл использовать реактор, если мы
будем блокировать наш внешний цикл, который
как раз и следит за приходом новых задач или
выполнением следующих
Async-servers in Python
• Name Lic. Doc Ex. Prod. Com. Act. Blog Twt Rep. Pool Wsgi Scket Cmet Epoll Test Style
• Twisted! MIT! Yes! Yes! Yes! Huge! Yes! Lots! No! Trac! Yes! Yes! Yes! No! Yes! Yes! Callback!
• Tornado! Apache! Yes! Yes! F.Feed!Yes! Yes! FB! Yes! GHub! No! Lim.! Yes! No! Yes! No!
Async!
• Orbited MIT Yes Yes Yes Yes Yes Yes No Trac No No Yes Yes Yes Yes Callback
• DieselWeb BSD Yes Yes STalk Yes Yes Yes Yes BitB. No Lim. Yes Yes Yes No Generator
• MultiTask MIT Some No No No No Yes No Bzr No No No No No No Generator
• Chiral GPL2 API No No IRC No No No Trac No Yes Yes Yes Yes Yes Coroutine
• Eventlet! MIT! Yes! Yes! S. Life! Yes! Yes! Yes! No! BitB.! Yes! Yes! Yes! No! Yes! Yes! Greenlet!
• FriendlyFlow GPL2 Some One No No No No Yes Ggle No No Yes No No Yes
Generator
• Weightless GPL2 Yes No Yes No No No Yes SF No No Yes No No Yes Generator
• Fibra MIT No No No No No Yes No Ggle No No Yes No No No Generator
• Concurrence! MIT! Yes! Yes! hyves!Yes! Yes! No! No! GHub! No! Yes! Yes! No! Yes! Yes!
Tasklet!
• Circuits MIT Yes Yes Yes Yes Yes Yes Yes Trac No Yes Yes No No Yes Async
http://nichol.as/asynchronous-servers-in-python
Async-servers in Python
• What License does the framework have?
• Does it provide documentation?
• Does the documentation contain examples?
• Is it used in production somewhere?
• Does it have some sort of community (mailinglist, irc, etc..)?
• Is there any recent activity?
• Does it have a blog (from the owner)?
• Does it have a twitter account?
• Where can i find the repository?
• Does it have a Thread Pool?
• Does it provide access to a TCP Socket?
• Does it have any Comet features?
• Is it using EPOLL?
• What kind of server is it? (greenlets, callbacks, generators etc..)
http://nichol.as/asynchronous-servers-in-python
Tornado
• Расширяемый, неблокирующий веб-сервер и
фреймворк, написанный на Python.
• Создан для использования в проекте FriendFeed;
компания была приобретена Facebook в 2009
году и после этого были открыты исходные коды
Tornado.
Tornado
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import logging
from tornado.options import define, options
!
define("port", default=8888, help="run on the given port", type=int)
!
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world!")
!
def main():
tornado.options.parse_command_line()
application = tornado.web.Application([
(r"/", MainHandler),
])
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
!
if __name__ == "__main__":
main()
http://programmingzen.com/2009/09/13/benchmarking-tornado-vs-twisted-web-vs-tornado-on-twisted/
Twisted
• Проекты на Twisted могут поддерживать TCP,
UDP, SSL/TLS, IP Multicast, Unix domain sockets,
большое количество протоколов, включая HTTP,
XMPP, NNTP, IMAP, SSH, IRC, FTP и другие.
• Основан на парадигме событийно-
ориентированного программирования, и это
значит, что пользователи Twisted пишут
небольшие программы обратного вызова,
которые вызываются фреймворком.
Twisted
from twisted.internet import epollreactor
epollreactor.install()
from twisted.internet import reactor
from twisted.web import server, resource
!
!
class Simple(resource.Resource):
isLeaf = True
def render_GET(self, request):
return "Hello, world!"
!
!
site = server.Site(Simple())
reactor.listenTCP(8888, site)
reactor.run()
http://programmingzen.com/2009/09/13/benchmarking-tornado-vs-twisted-web-vs-tornado-on-twisted/
Чуть больше о
Twisted
Twisted
• Шаблон реактор - однопоточный.
• Twisted сам реализует цикл реактора, мы сами не должны
его реализовывать.
• При написании кода, нужно продумывать основную логику
задачи.
• Цикл реактора вызывает наш код в тот момент, когда мы об
этом сами скажем. Реактор наперед не может знать, какую
часть кода нужно вызвать.
• Когда наши callback’и выполняются, цикл реактора не
выполняется, и наоборот.
• После возврата из callback'а, цикл реактора возобновляется
Что делать с
исключениями?
Errbacks
• Реактор не обрабатывает исключения, потому что
ничего о них не знает.
• Реактор -- низкоуровневый метод, а исключения
генерируются из более высокоуровневого кода.
Sync VS Async
1. Синхронный код:!
try:!
text = run_print()!
except Exception, err:!
print err!
sys.exit()!
else:!
print text!
sys.exit()!
!
!
2. Асинхронный код:!
def print_ok(text):!
print text!
reactor.stop()!
!
def print_fail(err):!
print >>sys.stderr, err!
reactor.stop()!
!
run_print(print_ok, print_err)!
!
reactor.run()
Deferred
from twisted.internet.defer import Deferred!
!
def print_ok(text):!
print text!
!
def print_fail(err):!
print >>sys.stderr, err!
!
d = Deferred()!
d.addCallbacks(print_ok, print_fail)!
d.callback("Text is correct") !
# или d.errback(Exception('I have failed.'))!
print "End."!
!
reactor.run()
Deferred
Сервер на Twisted
from twisted.internet import reactor!
from twisted.internet.protocol import ServerFactory !
from twisted.protocols.basic import LineOnlyReceiver !
!
class ChatProtocol(LineOnlyReceiver): !
!
name = "" !
def getName(self): !
if self.name!="": !
return self.name !
return self.transport.getPeer().host !
!
def connectionMade(self): !
print "New connection from "+self.getName() !
self.sendLine("Welcome to my my chat server.") !
self.sendLine("Send '/NAME [new name]' to change your name.") !
self.sendLine("Send '/EXIT' to quit.") !
self.factory.sendMessageToAllClients(self.getName()+" has joined the party.") !
self.factory.clientProtocols.append(self)
Сервер на Twisted
!
!
def connectionLost(self, reason): !
print "Lost connection from "+self.getName() !
self.factory.clientProtocols.remove(self) !
self.factory.sendMessageToAllClients(self.getName()+" has disconnected.") !
!
def lineReceived(self, line): !
print self.getName()+" said "+line !
if line[:5]=="/NAME": !
oldName = self.getName() !
self.name = line[5:].strip() !
self.factory.sendMessageToAllClients(oldName+" changed name !
! ! ! ! to "+self.getName()) !
elif line=="/EXIT": !
self.transport.loseConnection() !
else: !
self.factory.sendMessageToAllClients(self.getName()+" says "+line) !
!
def sendLine(self, line): !
self.transport.write(line+"rn") !
!
Сервер на Twisted
class ChatProtocolFactory(ServerFactory): !
!
protocol = ChatProtocol !
!
def __init__(self): !
self.clientProtocols = [] !
!
def sendMessageToAllClients(self, mesg): !
for client in self.clientProtocols:!
client.sendLine(mesg) !
!
print "Starting Server"!
factory = ChatProtocolFactory()!
reactor.listenTCP(12345, factory)!
reactor.run()!
В качестве клиента: telnet localhost 12345
Async I/O for Python 3
• Пишем асинхронный код без тредов и коллбеков
• Сопрограмма (англ. coroutine) — компонент
программы, обобщающий понятие
подпрограммы, который дополнительно
поддерживает множество входных точек (а не
одну как подпрограмма) и остановку и
продолжение выполнения с сохранением
определённого положения.
Yield from
!
!
class BinaryTree_ForLoop:!
def __init__(self, left=None,
us=None, right=None):!
self.left = left!
self.us = us!
self.right = right!
!
def __iter__(self):!
if self.left:!
for node in self.left:!
yield node!
if self.us:!
yield self.us!
if self.right:!
for node in self.right:!
yield node!
class BinaryTree:!
def __init__(self, !
left=None, us=None, right=None):!
self.left = left!
self.us = us!
self.right = right!
!
def __iter__(self):!
if self.left:!
yield from self.left!
if self.us:!
yield self.us!
if self.right:!
yield from self.right!
!
# For comparison, here is the same thing using for-loops!
# instead of yield-from.
Tulip VS Twisted
import tulip!
from tulip import http!
!
@tulip.coroutine!
def download(url):!
response = yield from http.request('GET', url)!
for k, v in response.items():!
print('{}: {}'.format(k, v[:80]))!
!
data = yield from response.read()!
print('nReceived {} bytes.n'.format(len(data)))!
!
if __name__ == '__main__':!
loop = tulip.get_event_loop()!
coroutine = download('http://omegafeihong.tumblr.com')!
loop.run_until_complete(coroutine)
Tulip VS Twisted
from twisted.internet import reactor!
from twisted.internet.defer import Deferred, succeed!
from twisted.internet.protocol import Protocol!
from twisted.web.client import Agent!
!
def print_headers(response):!
for k, v in response.headers.getAllRawHeaders():!
print('{}: {}'.format(k, v[0][:80]))!
!
return get_response_body(response)!
!
def get_response_body(response):!
class BodyReceiver(Protocol):!
def dataReceived(self, data):!
chunks.append(data)!
def connectionLost(self, reason):!
finished.callback(''.join(chunks))!
!
finished = Deferred()!
chunks = []!
response.deliverBody(BodyReceiver())!
return finished!
!
def print_body(data):!
print('nReceived {} bytes.n'.format(len(data)))!
return succeed(None)!
!
if __name__ == '__main__':!
agent = Agent(reactor)!
d = agent.request('GET', 'http://megafei
d.addCallback(print_headers)!
d.addCallback(print_body)!
d.addCallback(lambda x: reactor.stop())!
reactor.run()
Почитать
• http://ninaevseenko.github.io/async_twisted_ru/async_twisted_ru.pdf
• http://legacy.python.org/dev/peps/pep-3156/#abstract
• http://moscowdjango.ru/meetup/18/tulip/
• http://neednourishment.blogspot.ru
• http://www.ibm.com/developerworks/ru/library/l-python_part_10/index.html
• http://www.slideshare.net/Smirnov.Andrey/twisted-framework-python-2211313
• http://moscowdjango.ru/meetup/14/gil-and-python-why/
• http://legacy.python.org/dev/peps/pep-0380/
• http://legacy.python.org/dev/peps/pep-3156/#event-loop-classes
• http://ru.wikipedia.org/wiki/%D1%EE%E1%FB%F2%E8%E9%ED%EE-%EE%F0%E8%E5%ED%F2%E8%F0%EE%E2%E0%ED
%ED%EE%E5_%EF%F0%EE%E3%F0%E0%EC%EC%E8%F0%EE%E2%E0%ED%E8%E5
• http://nichol.as/asynchronous-servers-in-python
• http://programmingzen.com/2009/09/13/benchmarking-tornado-vs-twisted-web-vs-tornado-on-twisted/
• http://www.slideshare.net/megafeihong/tulip-24190096
• http://www.dabeaz.com/coroutines/

More Related Content

PDF
Язык Lua — секреты производительности / Ник Заварицкий (Mail.ru)
PPTX
Как собирать gps треки раз в секунду, экономя траффик
PDF
PDF
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
PDF
Как сделать ваш JavaScript быстрее / Роман Дворнов (Авито)
PDF
Алексей Федоров
ODP
Top10 доводов против языка Ruby
PPTX
Опыт эксплуатации большого проекта на Ruby
Язык Lua — секреты производительности / Ник Заварицкий (Mail.ru)
Как собирать gps треки раз в секунду, экономя траффик
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
Как сделать ваш JavaScript быстрее / Роман Дворнов (Авито)
Алексей Федоров
Top10 доводов против языка Ruby
Опыт эксплуатации большого проекта на Ruby

What's hot (20)

PPTX
Андрей Акиньшин
PDF
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
PPTX
Введение в Akka
PPTX
Тестирование через мониторинг или холакратия на практике / Максим Чистяков (U...
PDF
Производительность WebGL-приложений / Дмитренко Кирилл (Яндекс)
PDF
Отладка производительности приложения на Erlang / Максим Лапшин (Erlyvideo)
PPTX
Производительность Unity3D: подводные камни / Алексей Чубарь (BIT.GAMES)
PPTX
Пайплайн машинного обучения на Apache Spark / Павел Клеменков (Rambler&Co)
PDF
Aviasales: миграция поискового движка в docker / Дмитрий Кузьменков (Aviasales)
PDF
Юрий Насретдинов, Badoo
PDF
Анатомия веб-сервиса (РИТ-2014)
PDF
Алексей Фомкин, Практическое применение Web Workers
PDF
"Fault tolerant workflow orchestration on PHP", Anton Tsitou
PDF
Практика разработки веб-серверов на Rust
PDF
Akka: как я перестал бояться и полюбил асинхронный код
PDF
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
PDF
«Тотальный контроль производительности» Михаил Юматов, ЦИАН
PDF
Денис Иванов
PDF
Путь к Go на конкретном примере
PDF
Оптимизация производительности фронтенда / Игорь Алексеенко (HTML Academy)
Андрей Акиньшин
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
Введение в Akka
Тестирование через мониторинг или холакратия на практике / Максим Чистяков (U...
Производительность WebGL-приложений / Дмитренко Кирилл (Яндекс)
Отладка производительности приложения на Erlang / Максим Лапшин (Erlyvideo)
Производительность Unity3D: подводные камни / Алексей Чубарь (BIT.GAMES)
Пайплайн машинного обучения на Apache Spark / Павел Клеменков (Rambler&Co)
Aviasales: миграция поискового движка в docker / Дмитрий Кузьменков (Aviasales)
Юрий Насретдинов, Badoo
Анатомия веб-сервиса (РИТ-2014)
Алексей Фомкин, Практическое применение Web Workers
"Fault tolerant workflow orchestration on PHP", Anton Tsitou
Практика разработки веб-серверов на Rust
Akka: как я перестал бояться и полюбил асинхронный код
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
«Тотальный контроль производительности» Михаил Юматов, ЦИАН
Денис Иванов
Путь к Go на конкретном примере
Оптимизация производительности фронтенда / Игорь Алексеенко (HTML Academy)
Ad

Similar to Async Python (20)

PDF
Про асинхронное сетевое программирование
PDF
Андрей Светлов
PDF
Введение в Python и Django
PDF
CodeFest 2014. Каплуновский Б. — Использование асинхронного I/O для снижения ...
PDF
Андрей Светлов. Aiohttp
PDF
Лекция 13. Многопоточность и GIL
PDF
Twisted Framework - фреймворк для написания сетевых приложений на Python (Анд...
PDF
Twisted Framework - сетевые приложения в Python
PDF
Twisted Framework - сетевые приложения в Python
PDF
Леонид Васильев "Python в инфраструктуре поиска"
PPT
Node.js (Андрей Костенко)
PDF
Smirnov Twisted Python
PDF
Курс высокие нагрузки: сеть (отрывок)
PPTX
Виктор Сергиенко «Асинхронный IO-boundPython: миф или реальность?»
PDF
SECON'2014 - Сергеев Антон - Асинхронные задачи в iFunny
PDF
Анатомия веб-сервиса, Андрей Смирнов
PDF
Framework Battle: Django vs Flask vs Chalice
PDF
Asyncio для процессинга распределенной базы данных
PDF
Баннерокрутилка на Erlang
PDF
Python-разработка в части Яндекс-вселенной - Александр Кошелев, PyCon RU 2014
Про асинхронное сетевое программирование
Андрей Светлов
Введение в Python и Django
CodeFest 2014. Каплуновский Б. — Использование асинхронного I/O для снижения ...
Андрей Светлов. Aiohttp
Лекция 13. Многопоточность и GIL
Twisted Framework - фреймворк для написания сетевых приложений на Python (Анд...
Twisted Framework - сетевые приложения в Python
Twisted Framework - сетевые приложения в Python
Леонид Васильев "Python в инфраструктуре поиска"
Node.js (Андрей Костенко)
Smirnov Twisted Python
Курс высокие нагрузки: сеть (отрывок)
Виктор Сергиенко «Асинхронный IO-boundPython: миф или реальность?»
SECON'2014 - Сергеев Антон - Асинхронные задачи в iFunny
Анатомия веб-сервиса, Андрей Смирнов
Framework Battle: Django vs Flask vs Chalice
Asyncio для процессинга распределенной базы данных
Баннерокрутилка на Erlang
Python-разработка в части Яндекс-вселенной - Александр Кошелев, PyCon RU 2014
Ad

Async Python

  • 2. Проблема C10K • Условное название задачи конфигурирования и обслуживания высокопроизводительного сервера • Сервер должен быть способен обслуживать порядка 10 тыс. соединений одновременно
  • 3. Проблема C10K • Решение №1 • Поток на каждого клиента • Решение №2 • Поток на несколько клиентов
  • 4. Сервера, выдерживающие проблему • nginx, which relies on an event-driven (asynchronous) architecture, instead of threads, to handle requests • Lighttpd, which relies on an asynchronous architecture to handle requests • Tornado, a non-blocking web server and web application framework written in Python (used by Facebook's FriendFeed) • Apache AWF (retired, formerly Apache Deft), asynchronous, non-blocking web server running on the JVM • JBoss Netty, a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients • Node.js, asynchronous, non-blocking web server running on Google's V8 JavaScript engine
  • 5. Сервера, выдерживающие проблему • EventMachine, an asynchronous, non-blocking web server running on Ruby EventMachine • Cowboy (web server), another very lightweight web server written in Erlang • asyncore (in the standard Python library), a non- blocking web server library. It is based on Medusa, which is no longer maintained. • Django, some research is being done using the asynchronous IO support in Python 3.3
  • 7. Sync • Делится на однопоточную и многопоточную.
  • 8. Sync: 1 thread • В однопоточной модели каждая задача выполняется последовательно. Поток выполняет следующую задачу только тогда, когда предыдущая точно завершилась.
  • 9. Sync: N threads • В многопоточной модели можно достичь некоторой "одновременной работы" задач, но на каждую задачу выделяется один поток. Деталями управления в многопоточной синхронной модели управляет ОС.
  • 10. Async • Асинхронная модель всегда будет чередовать выполнение задач. Взаимодействие задач (их синхронизация) лежит на ответственности программиста.
  • 11. sync VS async • По сравнению с синхронной моделью, асинхронная модель лучше когда: 1. Когда есть много задач таких, что почти всегда есть по меньшей мере одна задача, которая может выполняться. 2. Задачи выполняют много операций ввода-вывода, приводя к тому, что синхронная задача проводит много времени впустую, блокируясь, в то время когда другие задачи могли бы выполняться. 3. Задачи независимы друг от друга и не нуждаются во взаимодействии.
  • 12. Event-driven programming • Событийно-ориентированное программирование • Способ построения программы • В коде явным образом выделяется главный цикл приложения • Тело главного цикла состоит из двух частей: выборки события и обработки события.
  • 13. Reactor • Для ожидания задач и управления ими, используется внешний цикл, который постоянно ждет каких-либо действий. • При возникновении задачи, он немедленно реагирует. • Каждая задача должна быть в не блокирующем режиме. какой смысл использовать реактор, если мы будем блокировать наш внешний цикл, который как раз и следит за приходом новых задач или выполнением следующих
  • 14. Async-servers in Python • Name Lic. Doc Ex. Prod. Com. Act. Blog Twt Rep. Pool Wsgi Scket Cmet Epoll Test Style • Twisted! MIT! Yes! Yes! Yes! Huge! Yes! Lots! No! Trac! Yes! Yes! Yes! No! Yes! Yes! Callback! • Tornado! Apache! Yes! Yes! F.Feed!Yes! Yes! FB! Yes! GHub! No! Lim.! Yes! No! Yes! No! Async! • Orbited MIT Yes Yes Yes Yes Yes Yes No Trac No No Yes Yes Yes Yes Callback • DieselWeb BSD Yes Yes STalk Yes Yes Yes Yes BitB. No Lim. Yes Yes Yes No Generator • MultiTask MIT Some No No No No Yes No Bzr No No No No No No Generator • Chiral GPL2 API No No IRC No No No Trac No Yes Yes Yes Yes Yes Coroutine • Eventlet! MIT! Yes! Yes! S. Life! Yes! Yes! Yes! No! BitB.! Yes! Yes! Yes! No! Yes! Yes! Greenlet! • FriendlyFlow GPL2 Some One No No No No Yes Ggle No No Yes No No Yes Generator • Weightless GPL2 Yes No Yes No No No Yes SF No No Yes No No Yes Generator • Fibra MIT No No No No No Yes No Ggle No No Yes No No No Generator • Concurrence! MIT! Yes! Yes! hyves!Yes! Yes! No! No! GHub! No! Yes! Yes! No! Yes! Yes! Tasklet! • Circuits MIT Yes Yes Yes Yes Yes Yes Yes Trac No Yes Yes No No Yes Async http://nichol.as/asynchronous-servers-in-python
  • 15. Async-servers in Python • What License does the framework have? • Does it provide documentation? • Does the documentation contain examples? • Is it used in production somewhere? • Does it have some sort of community (mailinglist, irc, etc..)? • Is there any recent activity? • Does it have a blog (from the owner)? • Does it have a twitter account? • Where can i find the repository? • Does it have a Thread Pool? • Does it provide access to a TCP Socket? • Does it have any Comet features? • Is it using EPOLL? • What kind of server is it? (greenlets, callbacks, generators etc..) http://nichol.as/asynchronous-servers-in-python
  • 16. Tornado • Расширяемый, неблокирующий веб-сервер и фреймворк, написанный на Python. • Создан для использования в проекте FriendFeed; компания была приобретена Facebook в 2009 году и после этого были открыты исходные коды Tornado.
  • 17. Tornado import tornado.httpserver import tornado.ioloop import tornado.options import tornado.web import logging from tornado.options import define, options ! define("port", default=8888, help="run on the given port", type=int) ! class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world!") ! def main(): tornado.options.parse_command_line() application = tornado.web.Application([ (r"/", MainHandler), ]) http_server = tornado.httpserver.HTTPServer(application) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start() ! if __name__ == "__main__": main() http://programmingzen.com/2009/09/13/benchmarking-tornado-vs-twisted-web-vs-tornado-on-twisted/
  • 18. Twisted • Проекты на Twisted могут поддерживать TCP, UDP, SSL/TLS, IP Multicast, Unix domain sockets, большое количество протоколов, включая HTTP, XMPP, NNTP, IMAP, SSH, IRC, FTP и другие. • Основан на парадигме событийно- ориентированного программирования, и это значит, что пользователи Twisted пишут небольшие программы обратного вызова, которые вызываются фреймворком.
  • 19. Twisted from twisted.internet import epollreactor epollreactor.install() from twisted.internet import reactor from twisted.web import server, resource ! ! class Simple(resource.Resource): isLeaf = True def render_GET(self, request): return "Hello, world!" ! ! site = server.Site(Simple()) reactor.listenTCP(8888, site) reactor.run() http://programmingzen.com/2009/09/13/benchmarking-tornado-vs-twisted-web-vs-tornado-on-twisted/
  • 21. Twisted • Шаблон реактор - однопоточный. • Twisted сам реализует цикл реактора, мы сами не должны его реализовывать. • При написании кода, нужно продумывать основную логику задачи. • Цикл реактора вызывает наш код в тот момент, когда мы об этом сами скажем. Реактор наперед не может знать, какую часть кода нужно вызвать. • Когда наши callback’и выполняются, цикл реактора не выполняется, и наоборот. • После возврата из callback'а, цикл реактора возобновляется
  • 23. Errbacks • Реактор не обрабатывает исключения, потому что ничего о них не знает. • Реактор -- низкоуровневый метод, а исключения генерируются из более высокоуровневого кода.
  • 24. Sync VS Async 1. Синхронный код:! try:! text = run_print()! except Exception, err:! print err! sys.exit()! else:! print text! sys.exit()! ! ! 2. Асинхронный код:! def print_ok(text):! print text! reactor.stop()! ! def print_fail(err):! print >>sys.stderr, err! reactor.stop()! ! run_print(print_ok, print_err)! ! reactor.run()
  • 25. Deferred from twisted.internet.defer import Deferred! ! def print_ok(text):! print text! ! def print_fail(err):! print >>sys.stderr, err! ! d = Deferred()! d.addCallbacks(print_ok, print_fail)! d.callback("Text is correct") ! # или d.errback(Exception('I have failed.'))! print "End."! ! reactor.run()
  • 27. Сервер на Twisted from twisted.internet import reactor! from twisted.internet.protocol import ServerFactory ! from twisted.protocols.basic import LineOnlyReceiver ! ! class ChatProtocol(LineOnlyReceiver): ! ! name = "" ! def getName(self): ! if self.name!="": ! return self.name ! return self.transport.getPeer().host ! ! def connectionMade(self): ! print "New connection from "+self.getName() ! self.sendLine("Welcome to my my chat server.") ! self.sendLine("Send '/NAME [new name]' to change your name.") ! self.sendLine("Send '/EXIT' to quit.") ! self.factory.sendMessageToAllClients(self.getName()+" has joined the party.") ! self.factory.clientProtocols.append(self)
  • 28. Сервер на Twisted ! ! def connectionLost(self, reason): ! print "Lost connection from "+self.getName() ! self.factory.clientProtocols.remove(self) ! self.factory.sendMessageToAllClients(self.getName()+" has disconnected.") ! ! def lineReceived(self, line): ! print self.getName()+" said "+line ! if line[:5]=="/NAME": ! oldName = self.getName() ! self.name = line[5:].strip() ! self.factory.sendMessageToAllClients(oldName+" changed name ! ! ! ! ! to "+self.getName()) ! elif line=="/EXIT": ! self.transport.loseConnection() ! else: ! self.factory.sendMessageToAllClients(self.getName()+" says "+line) ! ! def sendLine(self, line): ! self.transport.write(line+"rn") ! !
  • 29. Сервер на Twisted class ChatProtocolFactory(ServerFactory): ! ! protocol = ChatProtocol ! ! def __init__(self): ! self.clientProtocols = [] ! ! def sendMessageToAllClients(self, mesg): ! for client in self.clientProtocols:! client.sendLine(mesg) ! ! print "Starting Server"! factory = ChatProtocolFactory()! reactor.listenTCP(12345, factory)! reactor.run()! В качестве клиента: telnet localhost 12345
  • 30. Async I/O for Python 3 • Пишем асинхронный код без тредов и коллбеков • Сопрограмма (англ. coroutine) — компонент программы, обобщающий понятие подпрограммы, который дополнительно поддерживает множество входных точек (а не одну как подпрограмма) и остановку и продолжение выполнения с сохранением определённого положения.
  • 31. Yield from ! ! class BinaryTree_ForLoop:! def __init__(self, left=None, us=None, right=None):! self.left = left! self.us = us! self.right = right! ! def __iter__(self):! if self.left:! for node in self.left:! yield node! if self.us:! yield self.us! if self.right:! for node in self.right:! yield node! class BinaryTree:! def __init__(self, ! left=None, us=None, right=None):! self.left = left! self.us = us! self.right = right! ! def __iter__(self):! if self.left:! yield from self.left! if self.us:! yield self.us! if self.right:! yield from self.right! ! # For comparison, here is the same thing using for-loops! # instead of yield-from.
  • 32. Tulip VS Twisted import tulip! from tulip import http! ! @tulip.coroutine! def download(url):! response = yield from http.request('GET', url)! for k, v in response.items():! print('{}: {}'.format(k, v[:80]))! ! data = yield from response.read()! print('nReceived {} bytes.n'.format(len(data)))! ! if __name__ == '__main__':! loop = tulip.get_event_loop()! coroutine = download('http://omegafeihong.tumblr.com')! loop.run_until_complete(coroutine)
  • 33. Tulip VS Twisted from twisted.internet import reactor! from twisted.internet.defer import Deferred, succeed! from twisted.internet.protocol import Protocol! from twisted.web.client import Agent! ! def print_headers(response):! for k, v in response.headers.getAllRawHeaders():! print('{}: {}'.format(k, v[0][:80]))! ! return get_response_body(response)! ! def get_response_body(response):! class BodyReceiver(Protocol):! def dataReceived(self, data):! chunks.append(data)! def connectionLost(self, reason):! finished.callback(''.join(chunks))! ! finished = Deferred()! chunks = []! response.deliverBody(BodyReceiver())! return finished! ! def print_body(data):! print('nReceived {} bytes.n'.format(len(data)))! return succeed(None)! ! if __name__ == '__main__':! agent = Agent(reactor)! d = agent.request('GET', 'http://megafei d.addCallback(print_headers)! d.addCallback(print_body)! d.addCallback(lambda x: reactor.stop())! reactor.run()
  • 34. Почитать • http://ninaevseenko.github.io/async_twisted_ru/async_twisted_ru.pdf • http://legacy.python.org/dev/peps/pep-3156/#abstract • http://moscowdjango.ru/meetup/18/tulip/ • http://neednourishment.blogspot.ru • http://www.ibm.com/developerworks/ru/library/l-python_part_10/index.html • http://www.slideshare.net/Smirnov.Andrey/twisted-framework-python-2211313 • http://moscowdjango.ru/meetup/14/gil-and-python-why/ • http://legacy.python.org/dev/peps/pep-0380/ • http://legacy.python.org/dev/peps/pep-3156/#event-loop-classes • http://ru.wikipedia.org/wiki/%D1%EE%E1%FB%F2%E8%E9%ED%EE-%EE%F0%E8%E5%ED%F2%E8%F0%EE%E2%E0%ED %ED%EE%E5_%EF%F0%EE%E3%F0%E0%EC%EC%E8%F0%EE%E2%E0%ED%E8%E5 • http://nichol.as/asynchronous-servers-in-python • http://programmingzen.com/2009/09/13/benchmarking-tornado-vs-twisted-web-vs-tornado-on-twisted/ • http://www.slideshare.net/megafeihong/tulip-24190096 • http://www.dabeaz.com/coroutines/