Использование 0MQ для построения low latency распределёных систем, Андрей Охлопков, Алексей Ермаков

2,349 views

Published on

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,349
On SlideShare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
18
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Использование 0MQ для построения low latency распределёных систем, Андрей Охлопков, Алексей Ермаков

  1. 1. Использование ØMQ для построения распределенных систем Андрей Охлопков Алексей Ермаков
  2. 2. План доклада • Разработка распределенных систем • ØMQ: краткий обзор • Case study: GH ATP
  3. 3. Распределенные системы
  4. 4. Распределенные системы • Более гибкие в разработке • Проще масштабировать • Надежнее
  5. 5. Масштабируемость
  6. 6. Отказоустойчивость
  7. 7. Гетерогенность
  8. 8. Взаимодействие • HTTP • TCP/IP • Message-Oriented Middleware (MOM)
  9. 9. MOM • Асинхронное взаимодействие через прием и отправку сообщений • Очереди и маршрутизация
  10. 10. Распространенные MOM • Amazon SQS • MSMQ • JMS • AMQP (RabbitMQ, Apache Qpid)
  11. 11. ØMQ • Разработан компанией iMatix (AMQP) • LGPL • Поддерживает C/C++, C#, Java, Python, PHP, Ruby, Erlang и другие языки • “Sockets on steroids”
  12. 12. Отличия от других MOM • Отсутствие брокера • API, похожий на BSD sockets API • Произвольный формат сообщений • Различные модели взаимодействия
  13. 13. Отличия от обычных сокетов • N:M взаимодействие • bind()/connect() могут быть вызваны в любом порядке на любой стороне • Поток сообщений а не байтов • Автоматическое переподключение
  14. 14. Модели взаимодействия • Request/reply • Publish/subscribe • Pipeline
  15. 15. Request/reply
  16. 16. Request/reply: сервер import zmq context = zmq.Context(1) s = context.socket(zmq.REP) s.bind("tcp://*:5000") while True: request = s.recv() s.send(request.upper())
  17. 17. Request/reply: клиент import zmq, sys context = zmq.Context(1) s = context.socket(zmq.REQ) s.connect("tcp://localhost:5000") s.send(sys.argv[1]) print socket.recv(),
  18. 18. Request/reply $ python server.py & [1] 79259 $ python client.py foo FOO $ python client.py bar BAR
  19. 19. Request/reply: сервер import zmq context = zmq.Context(1) s = context.socket(zmq.REP) s.bind("tcp://*:5000") while True: request = s.recv() s.send(request.upper())
  20. 20. Request/reply: клиент import zmq, sys context = zmq.Context(1) s = context.socket(zmq.REQ) s.connect("tcp://localhost:5000") s.send(sys.argv[1]) print socket.recv(),
  21. 21. Проблема с масштабируемостью
  22. 22. Решение: queue device
  23. 23. Queue = XREQ + XREP + device
  24. 24. Queue = XREQ + XREP + device import zmq, random, time context = zmq.Context(1) xrep = context.socket(zmq.XREP) xrep.bind("tcp://*:5000") xreq = context.socket(zmq.XREQ) xreq.bind("tcp://*:5001") zmq.device(zmq.QUEUE, xrep, xreq)
  25. 25. Несколько devices в одной сети
  26. 26. Модели взаимодействия • Request/reply • Publish/subscribe • Pipeline
  27. 27. Publish/subscribe
  28. 28. Publish/subscribe: сервер import zmq, random, time context = zmq.Context(1) s = context.socket(zmq.PUB) s.bind("tcp://*:5000")
  29. 29. Publish/subscribe: сервер while True: for city in ["Moscow", "Murmansk", "St. Petersburg"]: s.send(city, zmq.SNDMORE) s.send(str(random.randint(10, 20))) time.sleep(2)
  30. 30. Publish/subscribe: клиент import zmq, sys context = zmq.Context(1) s = context.socket(zmq.SUB) s.connect("tcp://localhost:5000")
  31. 31. Publish/subscribe: клиент s.setsockopt(zmq.SUBSCRIBE, sys.argv[1]) while True: city = socket.recv() temp = socket.recv() print city + ": " + temp
  32. 32. Publish/subscribe $ python server.py & [1] 79569 $ python client.py M Moscow: 11 Murmansk: 11 Moscow: 13 Murmansk: 17
  33. 33. Модели взаимодействия • Request/reply • Publish/subscribe • Pipeline
  34. 34. Pipeline
  35. 35. Другие возможности • PAIR-сокеты • Долговременные сокеты • Транспорты: in-process, IPC, TCP, PGM • Межпоточное взаимодействие
  36. 36. Другие возможности • Polling • Альтернативные модели взаимодействия • Devices (queue, forwarder, streamer и собственные)
  37. 37. Что отсутствует • Транзакции • Гарантированная доставка сообщений • Информация о подключениях и контроль над ними
  38. 38. Внимание! • В inproc-сокетах connect() должен быть вызван после bind() • Сокеты привязаны к потокам • Фильтрация на стороне клиента в PUB/SUB • assert() в случае ошибок
  39. 39. Заключение • Легко использовать • Высокая производительность • Большой выбор моделей взаимодействия • Легко модифицировать существующую архитектуру
  40. 40. Case study: GH ATP
  41. 41. Case study: GH ATP • Автоматизированная торговля ценными бумагами • Большой объем данных (сотни тысяч котировок в секунду) • Жесткие требования к производительности
  42. 42. Задача: получение котировок • Разные поставщики данных с разными протоколами • Данные используются в нескольких продуктах • Нужен унифицированный API
  43. 43. Требования • Низкое время отклика (<1 мс) • Большие объемы данных • Поддержка нескольких языков (на данный момент — Scala и C++) • Load balancing, fault tolerance
  44. 44. Решение • Клиент-серверное взаимодействие на основе ØMQ • Google Protocol Buffers для сериализации сообщений
  45. 45. Клиент-сервер
  46. 46. Архитектура
  47. 47. Архитектура • Stateless взаимодействие • Легко балансировать нагрузку и обеспечивать устойчивость • Высокая производительность
  48. 48. Цифры • Тестовые сервер и клиент (Scala), TCP/IP • Около 250 000 котировок в секунду • Средняя задержка: <1 мс • CPU bound (protobuf), ØMQ может дать большую производительность
  49. 49. ØMQ — это • Легкая разработка высонагруженных распределенных систем • Простая модификация и добавление нового функционала • Масштабирование и скорость
  50. 50. • http://www.zeromq.com • http://mongrel2.org • Андрей Охлопков <oh@ghcg.com> • Алексей Ермаков <ae@ghcg.com>

×