Использование 0MQ для построения low latency распределёных систем, Андрей Охлопков, Алексей Ермаков
Использование 0MQ для построения распределёных систем...
Transcript of Использование 0MQ для построения распределёных систем...
Использование Ø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• Андрей Охлопков <[email protected]>• Алексей Ермаков <[email protected]>