Библиотека сайта rus-linux.net
Система обмена сообщениями ZeroMQ
Глава 24 из книги "Архитектура приложений с открытым исходным кодом", том 2.Оригинал: "ZeroMQ".
Автор: Martin Sústrik, перевод: Н.Ромоданов
24.2. Глобальное состояние
Глобальные переменные не всегда хороши при использовании с библиотеками. Библиотека может загружаться в процесс неоднократно, но даже в этом случае будет только один набор глобальных переменных. На рис.24.1 показана библиотека ØMQ, которая используется из двух различных и независимых библиотек. Затем приложение использует обе эти библиотеки.
Рис.24.1: ØMQ используется двумя различными библиотеками
Когда возникает такая ситуация, то оба экземпляра ØMQ имеют доступ к одним и тем же переменным, в результате чего возникают состояния гонки, странные сбои и неопределенное поведение.
Чтобы избежать этой проблемы, в библиотеке ØMQ отсутствуют глобальные переменные. Вместо этого пользователь библиотеки ответственен за работу в явном виде с глобальным состоянием. Объект, содержащий глобальные состояние, называется контекстом. Хотя с точки зрения пользователя контекст выглядит более или менее похожим на пул рабочих потоков, с точки зрения ØMQ это просто объект для хранения любого глобального состояния, которое нам понадобится. На рисунке, приведенном выше, библиотека libA
должна иметь свой собственный контекст точно также, как и библиотека libB
. Тогда ни одна из них не сможет вывести из строя или повлиять на другую библиотеку.
Усвоенный здесь урок довольно очевиден: не используйте в библиотеках глобальное состояние. Если вы это делаете, то в случае, когда в одном и том же процессе будет использовано два экземпляра библиотеки, библиотека выйдет из строя.
24.3. Производительность
Когда проект ØMQ был запущен, его основной целью была оптимизация производительности. Производительность системы обмена сообщениями оценивается с помощью двух метрик: пропускной способности - сколько сообщений может быть передано в течение определенного количества времени, и задержкой - сколько времени требуется сообщению для того, чтобы добраться от одной конечной точки к другой.
На какой показатель мы должны ориентироваться? Какая связь между ними? Разве это не очевидно? Запустите тест, разделите общее время теста на количество пришедших сообщений и вы получаете задержку. Разделите количество сообщений на время и вы получаете пропускную способность. Другими словами, задержка обратно пропорциональна величине пропускной способности. Тривиально, не так ли?
Вместо того, чтобы сразу начать кодирование, мы потратили несколько недель на более подробное исследование метрик производительности и выяснили, что отношения между пропускной способностью и задержкой гораздо более тонкое, чем приведенное выше, и часто метрики довольно нелогичны.
Представьте себе, A отправляет сообщения для B (смотрите рис.24.2.) Общее время теста составляет 6 секунд. Было передано 5 сообщений. Следовательно пропускная способность равна 0,83 сообщения/сек (5/6), а задержка равна 1,2 сек (6/5), не так ли?
Рис.24.2: Отправка сообщений из A в B
Снова взгляните на диаграмму. На ней видно различное время для каждого сообщения, которое поступает из A в B: 2 сек, 2,5 сек, 3 сек, 3,5 сек, 4 сек. В среднем это 3 секунды, что довольно далеко от нашего первоначального расчета в 1,2 секунды. Этот пример показывает заблуждения, которые интуитивно делаются относительно метрик производительности.
Теперь взгляните на пропускную способность. Общее время теста составляет 6 секунд. Однако, в A будет затрачено всего 2 секунды для того, чтобы отправить все сообщения. С точки зрения A пропускная способность равна 2,5 сообщений/сек (5/2). В B затрачивается 4 секунды для того, чтобы принять все сообщения. Так что с точки зрения B пропускная способность равна 1,25 сообщений/сек (5/4). Ни одно из этих значений не соответствует нашему первоначальному расчету в 1,2 сообщений/сек.
Короче говоря, задержка и пропускная способность являются двумя различными метриками - это очевидно. Важно понимать различие между ними и их взаимосвязь. Задержку можно измерить только между двумя различными точками в системе; нет такого понятия, как задержка в точке А. Каждое сообщение имеет свою собственную задержку. Вы можете вычислить среднее значение задержек нескольких сообщений, однако, нет такого понятия, как задержка потока сообщений.
Пропускная способность, с другой стороны, может измеряться только в одной точке системы. Имеется пропускная способность отправителя, пропускная способность принимающей стороны, есть пропускная способность любой промежуточной точкой между ними, но нет такого понятия, как общая пропускная способность всей системы. И пропускная способность имеет смысл только для набора сообщений, нет такого понятия, как пропускная способность одного сообщения.
Что касается отношений между пропускной способности и задержкой, то, оказывается, действительно, между ними есть взаимосвязь; однако, в формуле есть интегралы и мы здесь ее обсуждать не будем. Для получения дополнительной информации, читайте литературу по теории очередей.
При оценке производительности системы обмена сообщениями есть еще очень много подводных камней, так что мы не будем вдаваться в подробности. Упор нужно сделать на следующем усвоенном уроке: Убедитесь, что вы понимаете проблему, которую вы решаете. Даже такая проблема, как просто «сделать что-то более быстрым» может для ее правильного понимания потребовать большого объема работы. Более того, если вы не понимаете проблему, вы, вероятно, на основе неявных предположений и популярных мифов создадите код, в результате чего это решение будет иметь недостатки или, по крайней мере, будет гораздо более сложным или гораздо менее полезным, чем это можно было бы сделать.
Далее: 24.4. Выделение памяти