Использование 0MQ для построения low latency распределёных...

Preview:

DESCRIPTION

 

Citation preview

Использование ØMQ для построения распределенных систем

Андрей ОхлопковАлексей Ермаков

План доклада• Разработка распределенных систем• ØMQ: краткий обзор• Case study: GH ATP

Распределенные системы

Распределенные системы• Более гибкие в разработке• Проще масштабировать• Надежнее

Масштабируемость

Отказоустойчивость

Гетерогенность

Взаимодействие• HTTP• TCP/IP• Message-Oriented Middleware (MOM)

MOM• Асинхронное взаимодействие через прием

и отправку сообщений• Очереди и маршрутизация

Распространенные MOM• Amazon SQS• MSMQ• JMS• AMQP (RabbitMQ, Apache Qpid)

ØMQ• Разработан компанией iMatix (AMQP)• LGPL• Поддерживает C/C++, C#, Java, Python, PHP,

Ruby, Erlang и другие языки • “Sockets on steroids”

Отличия от других MOM• Отсутствие брокера• API, похожий на BSD sockets API• Произвольный формат сообщений• Различные модели взаимодействия

Отличия от обычных сокетов• N:M взаимодействие• bind()/connect() могут быть вызваны в

любом порядке на любой стороне• Поток сообщений а не байтов• Автоматическое переподключение

Модели взаимодействия• Request/reply• Publish/subscribe• Pipeline

Request/reply

Request/reply: серверimport zmqcontext = zmq.Context(1)s = context.socket(zmq.REP)s.bind("tcp://*:5000")  while True: request = s.recv() s.send(request.upper())

Request/reply: клиент import zmq, syscontext = zmq.Context(1)s = context.socket(zmq.REQ)s.connect("tcp://localhost:5000")s.send(sys.argv[1])print socket.recv(),

Request/reply$ python server.py &[1] 79259$ python client.py foo FOO$ python client.py barBAR

Request/reply: серверimport zmqcontext = zmq.Context(1)s = context.socket(zmq.REP)s.bind("tcp://*:5000")  while True: request = s.recv() s.send(request.upper())

Request/reply: клиент import zmq, syscontext = zmq.Context(1)s = context.socket(zmq.REQ)s.connect("tcp://localhost:5000")s.send(sys.argv[1])print socket.recv(),

Проблема с масштабируемостью

Решение: queue device

Queue = XREQ + XREP + device

Queue = XREQ + XREP + deviceimport zmq, random, timecontext = 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)

Несколько devices в одной сети

Модели взаимодействия• Request/reply• Publish/subscribe• Pipeline

Publish/subscribe

Publish/subscribe: сервер import zmq, random, timecontext = zmq.Context(1)s = context.socket(zmq.PUB)s.bind("tcp://*:5000")

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)

Publish/subscribe: клиент import zmq, syscontext = zmq.Context(1)s = context.socket(zmq.SUB)s.connect("tcp://localhost:5000")

Publish/subscribe: клиентs.setsockopt(zmq.SUBSCRIBE, sys.argv[1])while True: city = socket.recv() temp = socket.recv() print city + ": " + temp

Publish/subscribe$ python server.py &[1] 79569$ python client.py MMoscow: 11Murmansk: 11Moscow: 13Murmansk: 17

Модели взаимодействия• Request/reply• Publish/subscribe• Pipeline

Pipeline

Другие возможности• PAIR-сокеты• Долговременные сокеты• Транспорты: in-process, IPC, TCP, PGM• Межпоточное взаимодействие

Другие возможности• Polling• Альтернативные модели взаимодействия• Devices (queue, forwarder, streamer и

собственные)

Что отсутствует• Транзакции• Гарантированная доставка сообщений• Информация о подключениях и контроль

над ними

Внимание! • В inproc-сокетах connect() должен быть

вызван после bind()• Сокеты привязаны к потокам• Фильтрация на стороне клиента в PUB/SUB• assert() в случае ошибок

Заключение• Легко использовать• Высокая производительность• Большой выбор моделей взаимодействия• Легко модифицировать существующую

архитектуру

Case study: GH ATP

Case study: GH ATP• Автоматизированная торговля ценными

бумагами• Большой объем данных (сотни тысяч

котировок в секунду)• Жесткие требования к производительности

Задача: получение котировок• Разные поставщики данных с разными

протоколами• Данные используются в нескольких

продуктах• Нужен унифицированный API

Требования• Низкое время отклика (<1 мс)• Большие объемы данных• Поддержка нескольких языков (на данный

момент — Scala и C++)• Load balancing, fault tolerance

Решение• Клиент-серверное взаимодействие на

основе ØMQ• Google Protocol Buffers для сериализации

сообщений

Клиент-сервер

Архитектура

Архитектура• Stateless взаимодействие• Легко балансировать нагрузку и

обеспечивать устойчивость• Высокая производительность

Цифры• Тестовые сервер и клиент (Scala), TCP/IP• Около 250 000 котировок в секунду• Средняя задержка: <1 мс• CPU bound (protobuf), ØMQ может дать

большую производительность

ØMQ — это• Легкая разработка высонагруженных

распределенных систем• Простая модификация и добавление нового

функционала• Масштабирование и скорость

• http://www.zeromq.com• http://mongrel2.org• Андрей Охлопков <oh@ghcg.com>• Алексей Ермаков <ae@ghcg.com>

Recommended