Архитектура и принципы функционирования прозрачной распределенной сети Qnet, разрешение имен
Как было показано в разделах Микроядро: реализация и сервисы и Межпроцессное взаимодействие (IPC) ключевым механизмом в микроядерной ОС является обмен сообщениями, причем рассматривался лишь вариант их использования в пределах одного узла. Одной из сильных сторон ЗОСРВ «Нейтрино» является возможность прозрачного распространения этого механизма по сети между узлами с родственными микроядерными системами.
В данной статье рассматривается собственная встроенная распределенная сеть, основанная на протоколе Qnet, которая не связана со стеком протоколов TCP/IP.
Сеть Qnet позволяет доверенным узлам эффективно обмениваться ресурсами по локальной вычислительной сети с минимальными накладными расходами. В ней можно одинаково просто использовать как стандартные утилиты ( cp, mv и т.п.) для единообразного управления файлами в любом фрагменте сети, так и типовые примитивы IPC ( MsgSend(), open() и т.п.) для взаимодействия процессов на разных узлах. Пользователь имеет возможность не только получать доступ к файлам, но и запускать или останавливать процессы (в том числе менеджеры ресурсов) на подключенных к сети Qnet узлах.
Протокол Qnet не выполняет аутентификацию удаленных запросов. Это может показаться уязвимостью, однако это не так. Сетевые объекты защищаются как стандартными дискреционными правами доступа, применяемыми для пользователей и пользовательских групп. Кроме того, на коммуникации распространяются мандатные ограничения на уровень разрешенных коммуникаций. Управление этими параметрами осуществляется как автоматически, так и путем ужесточения правил функционирования с помощью утилиты kszconfig.
Защищенный сегмент сети Qnet отделен от регулярного и коммуникация между ними не осуществляется в любом виде. Узлы, функционирующие в защищенном сегменте не имеют возможности обнаруживать остальные. В полном объеме справедливо и обратное. |
Встроенная в ОС распределенная сеть позволяет эффективно решать следующие задачи:
Протокол Qnet позволяет в распределенном ключе использовать не только механизм обмена сообщениями, но также и ряд других примитивов межзадачного взаимодействия, включая, например, сигналы, очереди сообщений, именованные семафоры и т.п.
Для понимания сете-прозрачного функционирования механизмов IPC рассмотрим два процесса, которым необходимо взаимодействовать: клиентский процесс и серверный процесс, реализующий работу менеджера последовательного порта. В случае одного узла, клиент просто вызывает функции open(), read(), write() и т.д. Такие высокоуровневые POSIX функции, как, например, open(), в действительности порождают ряд низкоуровневых системных вызовов, управляющих обменом сообщениями, включая ConnectAttach(), MsgSend() и т.д. Однако, для клиента последние являются неявными, что позволяет ему заботиться лишь о параметрах функции open().
/* Открыть последовательное устройство */fd = open( "/dev/ser1", O_RDWR, ... );
Теперь рассмотрим изменения, которые произойдут с данными процессами, если они будут исполняться на разных узлах:
Исходный код этих двух процессов в данном случае идентичен тому, который используется в случае с одним узлом, с лишь одним исключением: имя ресурса, который открывает клиент. Это имя будет содержать префикс, определяющий узел, на котором расположен сервис (/dev/ser1
). Как будет рассмотрено далее, данный префикс преобразуется в дескриптор узла для последующего неявного вызова ConnectAttach(). Каждый узел в сети имеет собственный сетевой дескриптор, который служит единственным признаком, определяющим характер взаимодействия — сетой или локальный.
При запуске сети Qnet пространства имен всех узлов данной сети добавляется к перечню локальных ресурсов. Имя — это символьное обозначение ресурса, которое сообщает программе путь, по которому следует искать некоторый объект (файл) в иерархии каталогов, начинающейся с корневого каталога /
.
Пространства имен удаленных узлов транслируются на локальном узле через псевдо-каталог /net
, который создается менеджером прозрачной распределенной сети Qnet.
Например, удаленный узел с именем node1 (см. hostname) будет отображаться следующим образом:
/net/node1/dev/socket /net/node1/dev/ser1 /net/node1/home /net/node1/bin ...
Итак, при работе в сети Qnet можно обращаться к файлам, менеджерам ресурсов или процессам на других узлах так же, как при взаимодействии с ними локально на своем собственном узле.
В приведенном ранее примере с функцией open() для открытия последовательного устройства на узле node1 достаточно лишь изменить путь:
/* Открыть последовательное устройство на узле node1 */fd = open( "/net/node1/dev/ser1", O_RDWR... );
Клиент всегда использует пространство имен для поиска адреса сервера (и дескриптора его узла). В случае с локальным взаимодействием результатом поиска будет набор идентификаторов сервера: дескриптор узла, идентификатор процесса и идентификатор канала. При сетевом взаимодействии результат поиска будет аналогичным с поправкой лишь на дескриптор узла:
В обоих рассмотренных случаях результатом поиска сервера и соединения с ним является файловый дескриптор. Он же является идентификатором соединения для системного вызова ConnectAttach(). Этот файловый дескриптор используется для всех последующих операций обмена сообщениями. Необходимо отметить, что для клиента файловый дескриптор идентичен как при локальном взаимодействии, так и при сетевом.
Вернемся к рассматриваемому примеру. Допустим, что клиент на узле A хочет использовать последовательный порт /dev/ser1
на узле B. При этом, клиенту достаточно выполнить функцию open() с указанием имени /net/nodeB/dev/ser1
. На следующей диаграмме показана последовательность выполняемых при этом операций:
Выполнение клиентом open() приводит к следующей последовательности операций:
/net/nodeB/dev/ser1
.
Так как за обслуживание запросов к пространству имен ниже префикса /net
отвечает lsm-qnet.so, менеджер процессов переадресовывает сообщение ему.
nodeB/dev/ser1
(запрос включает лишь часть имени, ниже точки монтирования).
Менеджер сети сообщает дескриптор узла nodeB, идентификатора удаленного процесса и идентификатора канала для удаленного менеджера процессов, что фактически перекладывает разрешение запроса на узел nodeB.
Менеджер процессов узла nodeB переадресовывает запрос драйверу на удаленном узле и возвращает клиенту дескриптора узла, идентификаторы канала и процесса драйвера последовательного порта.
После этого обмен сообщениями на данном соединении происходит так же, как и при локальной отправке сообщений. С этого момента все последующие операции происходят напрямую между клиентом и сервером (драйвером).
Ключевая особенность состоит в том, что клиент не знает о производимых операциях — они реализованы внутри функции open(). Клиент лишь выполняет функцию и получает файловый дескриптор, соответствующий идентификатору соединения, или код ошибки.
На каждом последующем шаге из запроса клиента удаляются компоненты имени, которые были разрешены. Так, на шаге 2 запрос содержит лишь к nodeB/dev/ser1 . На шаге 3 остается dev/ser1 , так как это все, что должен знать удаленный менеджер процессов. И, наконец, на шаге 4 запрос содержит лишь пустую строку, так как префикс драйвера последовательного порта не является каталоговым. |
В приведенных примерах удаленные службы или файлы расположены на известных узлах и по известным путям. Например, последовательный порт на узле nodeB находится по известному пути /net/nodeB/dev/ser1
.
Служба глобальных имен (англ. Global Name Service, GNS) позволяет определить местонахождение служб по их именам независимо от того, находятся ли они в локальной системе или на некотором удаленном узле. Например, если необходимо обнаружить модем в сети, можно просто применить поиск по имени "modem". В результате вместо использования статичного пути вроде /net/nodeB/dev/modem
, GNS-сервер позволяет найти сетевую службу с именем "modem". GNS-сервер можно настроить таким образом, чтобы он обслуживал все или часть узлов в сети Qnet. Кроме того, в сети может быть несколько GNS-серверов.
Как уже упоминалось, префикс /net
используется менеджером lsm-qnet.so наиболее часто. При разрешении имен в сетевом пространстве используются определенные термины:
/
или .
. В приведенном ранее примере в качестве имени одного из узлов использовалось nodeB. Значение по умолчанию можно получить с помощью функции confstr() с параметром _CS_HOSTNAME
. _CS_DOMAIN
. /net
. Распознаватели имен
В сетевой менеджер интегрированы три распознавателя имен (name resolver):
.
и следом домен узла. Полученная строка становится результатом функции gethostbyname().
Политика качества обслуживания (QoS) — это тот вопрос, который часто возникает в сетях высокой готовности, а также в системах управления реального времени. В сетях Qnet задача QoS по сути сводится к выбору среды передачи. В системе с несколькими сетевыми интерфейсами Qnet выберет тот, который больше соответствует заданной политике качества обслуживания.
Если в системе предусмотрен только один сетевой интерфейс, то политика QoS не применяется. |
Qnet поддерживает передачу по нескольким сетям (интерфейсам). Для этого предусмотрены следующие политики качества обслуживания, которые позволяют определять наиболее подходящий сетевой интерфейс для передачи:
Для получения преимуществ от использования QoS в Qnet, необходимо иметь физически отделенные сети. Например, рассмотрим конфигурацию сети с двумя узлами и общим хабом, причем, каждый узел имеет два подключения к нему:
Если канал, который используется в данный момент, становится недоступен, Qnet обнаруживает это, но не может переключиться на другой канал, поскольку они оба подключены к одному хабу. Приложение само должно исправить ошибку и только когда оно повторно установит соединение, Qnet переключится на рабочий канал.
Рассмотрим схожую конфигурацию сети, но включающую два хаба:
Если сети физически разделены и один из каналов становится недоступным, Qnet автоматически переключается на другое соединение, в зависимости от выбранной политики QoS. В этом случае приложение не узнаёт, что используемый канал стал недоступен.
Можно указать опцию tx_retries модуля lsm-qnet.so, чтобы ограничить количество попыток повторной передачи через сбойный канал. Это позволяет контролировать длительность ожидания со стороны Qnet перед признанием сетевого интерфейса недоступным. Следует учесть, что если количество попыток повторных передач слишком маленькое, то Qnet не будет допускать потери пакетов и может начать постоянно и преждевременно считать, что тот или иной канал стал недоступен.
Рассмотрим QoS политики подробнее.
Qnet решает, какие каналы связи использовать для передачи пакетов данных в зависимости от текущей нагрузки и пропускной способности сетевых интерфейсов, определенной менеджером io-pkt-*. Пакет ставится в очередь на отправку того канала, который способен быстрее других доставить пакет до пункта назначения. Такой подход эффективно обеспечивает высокую пропускную способность между узлами по корректно функционирующим каналам (пропускная способность между узлами определяется как сумма пропускных способностей всех доступных им каналов) и в случае сбоя канала — плавное ограничение передачи данных оптимальным способом.
Если канал перестает функционировать, Qnet обеспечит переключение на иной доступный канал. В первый раз такое переключение происходит в течение нескольких секунд, так как сетевой драйвер на неисправном канале связи выдерживает таймаут и лишь затем делает повторную попытку передачи. Только после этого соединения на данном канале считаются обрушенными. После этого Qnet получит уведомление о том, что данный канал не функционирует и перестанет использовать его для передачи пользовательских данных.
В процессе перебалансировки нагрузки между доступными каналами Qnet будет периодически отправлять сервисные пакеты по неисправному каналу для обнаружения факта его восстановления. Как только данное событие будет обнаружено, канал вновь помещается в список используемых.
Данная политика используется по умолчанию. |
При использовании этой политики задается предпочтительный канал передачи. Qnet будет использовать только этот канал, при условии, что он остается работоспособным. При его сбое, Qnet переключится на другие доступные каналы и продолжит передачу данных в соответствии с политикой loadbalance.
Как только обнаружится восстановление предпочтительного канала связи, Qnet возвращается к исходной логике его использования, игнорируя все остальные.
Эта политика используется в тех случаях, когда необходимо жестко привязать передачу данных только к одному каналу связи. Независимо от доступности других каналов, Qnet не будет их использовать. Если выбранный канал откажет, Qnet не будет использовать другие доступные каналы.
В каких случаях может понадобиться данная политика обслуживания? Допустим, что имеется две сети, причем одна из них работает намного быстрее другой, и есть приложение, которое обменивается большими объемами данных. С помощью этой политики можно ограничить передачу только быстрой сетью, чтобы избежать перегрузки медленной сети в случае сбоев первой.
Политика обслуживания задается как часть путевого имени. Например, для того чтобы открыть доступ к /net/nodeA/dev/ser1
с QoS-политикой exclusive, можно использовать следующее имя:
/net/nodeA~exclusive:en0/dev/ser1
QoS-параметр начинается с символа ~
. Указанным способом задается не только политика, но и привязка Qnet к интерфейсу en0.
Для различных ресурсов с заданными QoS-политиками можно назначать символьные ссылки:
ln -sP /net/nodeA~preferred:en1 /remote/sql_server
Данная команда присваивает абстрактное имя /remote/sql_server
некоторому ресурсу на узле nodeA с указанной политикой обслуживания (preferred) и привязкой к сетевому интерфейсу en1.
Символьные ссылки в каталоге /net создавать нельзя. |
Благодаря возможности создавать символьные ссылки для сетевых префиксов, появляется возможность обращаться к одному и тому же сетевому сервису с помощью разных QoS-метрик. И наоборот, может существовать несколько серверов, предоставляющих один сервис. Если один сервер отказывает, абстрактное путевое имя может быть переназначено на другой сервер. Например, если узел nodeA отказал, то переназначение сервиса можно выполнить командой:
rm /remote/sql_server ln -sP /net/nodeB /remote/sql_server
В результате служба будет переназначена с узла nodeA на nodeB. Удобство состоит в том, что приложения можно разрабатывать без использования жестко заданных имен узлов.
Рассмотрим ряд примеров использования прозрачной распределенной сети Qnet.
Следует помнить, что менеджер распределенной сети Qnet представляет собой разделяемый объект, который загружается сетевым стеком. |
Если ЗОСРВ «Нейтрино» используется в небольшой локальной сети, то можно обойтись одним распознавателем en_ionet, который и используется по умолчанию. При разрешении неизвестного имени узла, распознаватель посылает широковещательный запрос имени и узел с данным именем отвечает на него идентификационным сообщением. После разрешения имени оно кешируется для последующего использования.
Поскольку распознаватель en_ionet используется по умолчанию при запуске менеджера распределенной сети Qnet, можно обратиться к нему просто набрав:
ls /net/n120/
Если в локальной сети есть машина с именем n120, то после разрешения ее имени пользователь сможет ознакомиться с содержимым ее файловой системы.
Для разрешения удаленных имен Qnet использует службу доменных имен (Domain Name System, DNS). Для включения DNS при работе распределенной сети Qnet следует задать следующий распознаватель при загрузке модуля lsm-qnet.so:
mount -T io-pkt -o "mount=:,resolve=dns,mount=.com:.net:.edu" \ /lib/dll/lsm-qnet.so
В этом случае Qnet будет использовать оба распознавателя: en_ionet (заданный первой командой "mount="), так и DNS при разрешении удаленных имен.
Необходимо отметить, что в этом примере задано несколько типов доменных имен ("mount=.com:.net:.edu") в качестве точек монтирования просто для того, чтобы сделать разрешение удаленных имен более надежным.
Таким образом, при вводе, например, инструкции:
ls /net/node154.com/repository
будет выведено содержимое каталога repository на узле node154.com
.
Предыдущий раздел: перейти