Встроенная распределенная сеть Qnet

Архитектура и принципы функционирования прозрачной распределенной сети Qnet, разрешение имен

Вступление
Распределенное разрешение имен
Файловый дескриптор (идентификатор соединения)
Реализация операции open()
Служба глобальных имен (GNS)
Именование сетевых ресурсов
Качество обслуживания (QoS) и резервированные соединения
Политики качества обслуживания
Балансировка нагрузки (loadbalance)
Предпочтительный канал (preferred)
Эксклюзивный канал (exclusive)
Выбор политики качества обслуживания
Символьные ссылки
Примеры
Локальные сети
Удаленные сети

Вступление

Как было показано в разделах Микроядро: реализация и сервисы и Межпроцессное взаимодействие (IPC) ключевым механизмом в микроядерной ОС является обмен сообщениями, причем рассматривался лишь вариант их использования в пределах одного узла. Одной из сильных сторон ЗОСРВ «Нейтрино» является возможность прозрачного распространения этого механизма по сети между узлами с родственными микроядерными системами.

В данной статье рассматривается собственная встроенная распределенная сеть, основанная на протоколе Qnet, которая не связана со стеком протоколов TCP/IP.

Сеть Qnet позволяет доверенным узлам эффективно обмениваться ресурсами по локальной вычислительной сети с минимальными накладными расходами. В ней можно одинаково просто использовать как стандартные утилиты ( cp, mv и т.п.) для единообразного управления файлами в любом фрагменте сети, так и типовые примитивы IPC ( MsgSend(), open() и т.п.) для взаимодействия процессов на разных узлах. Пользователь имеет возможность не только получать доступ к файлам, но и запускать или останавливать процессы (в том числе менеджеры ресурсов) на подключенных к сети Qnet узлах.


Caution: Протокол Qnet не выполняет аутентификацию удаленных запросов. Это может показаться уязвимостью, однако это не так. Сетевые объекты защищаются как стандартными дискреционными правами доступа, применяемыми для пользователей и пользовательских групп. Кроме того, на коммуникации распространяются мандатные ограничения на уровень разрешенных коммуникаций. Управление этими параметрами осуществляется как автоматически, так и путем ужесточения правил функционирования с помощью утилиты kszconfig.

Защищенный сегмент сети Qnet отделен от регулярного и коммуникация между ними не осуществляется в любом виде. Узлы, функционирующие в защищенном сегменте не имеют возможности обнаруживать остальные. В полном объеме справедливо и обратное.


Встроенная в ОС распределенная сеть позволяет эффективно решать следующие задачи:

Протокол Qnet позволяет в распределенном ключе использовать не только механизм обмена сообщениями, но также и ряд других примитивов межзадачного взаимодействия, включая, например, сигналы, очереди сообщений, именованные семафоры и т.п.

Для понимания сете-прозрачного функционирования механизмов IPC рассмотрим два процесса, которым необходимо взаимодействовать: клиентский процесс и серверный процесс, реализующий работу менеджера последовательного порта. В случае одного узла, клиент просто вызывает функции open(), read(), write() и т.д. Такие высокоуровневые POSIX функции, как, например, open(), в действительности порождают ряд низкоуровневых системных вызовов, управляющих обменом сообщениями, включая ConnectAttach(), MsgSend() и т.д. Однако, для клиента последние являются неявными, что позволяет ему заботиться лишь о параметрах функции open().

/* Открыть последовательное устройство */
fd = open( "/dev/ser1", O_RDWR, ... );

Теперь рассмотрим изменения, которые произойдут с данными процессами, если они будут исполняться на разных узлах:

13_1.png
Рисунок 1. Распределенная сеть и исполнение компонентов приложения на разных узлах

Исходный код этих двух процессов в данном случае идентичен тому, который используется в случае с одним узлом, с лишь одним исключением: имя ресурса, который открывает клиент. Это имя будет содержать префикс, определяющий узел, на котором расположен сервис (/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... );

Клиент всегда использует пространство имен для поиска адреса сервера (и дескриптора его узла). В случае с локальным взаимодействием результатом поиска будет набор идентификаторов сервера: дескриптор узла, идентификатор процесса и идентификатор канала. При сетевом взаимодействии результат поиска будет аналогичным с поправкой лишь на дескриптор узла:

0
ND_LOCAL_NODE
Локальный сервер (на данном узле).
≠0
Удаленный сервер.

Файловый дескриптор (идентификатор соединения)

В обоих рассмотренных случаях результатом поиска сервера и соединения с ним является файловый дескриптор. Он же является идентификатором соединения для системного вызова ConnectAttach(). Этот файловый дескриптор используется для всех последующих операций обмена сообщениями. Необходимо отметить, что для клиента файловый дескриптор идентичен как при локальном взаимодействии, так и при сетевом.

Реализация операции open()

Вернемся к рассматриваемому примеру. Допустим, что клиент на узле A хочет использовать последовательный порт /dev/ser1 на узле B. При этом, клиенту достаточно выполнить функцию open() с указанием имени /net/nodeB/dev/ser1. На следующей диаграмме показана последовательность выполняемых при этом операций:

13_2.png
Рисунок 2. Передача сообщений при установлении связи с удаленным сервером

Выполнение клиентом open() приводит к следующей последовательности операций:

  1. Клиент отправляет сообщение менеджеру процессов локального узла с вопросом о разрешении имени /net/nodeB/dev/ser1.

    Так как за обслуживание запросов к пространству имен ниже префикса /net отвечает lsm-qnet.so, менеджер процессов переадресовывает сообщение ему.

  2. Клиент отправляет второе сообщение уже локальному менеджеру распределенной сети Qnet с просьбой о разрешении имени nodeB/dev/ser1 (запрос включает лишь часть имени, ниже точки монтирования).

    Менеджер сети сообщает дескриптор узла nodeB, идентификатора удаленного процесса и идентификатора канала для удаленного менеджера процессов, что фактически перекладывает разрешение запроса на узел nodeB.

  3. Клиент создает соединение с менеджером процессов узла nodeB и еще раз отправляет первичный запрос.

    Менеджер процессов узла nodeB переадресовывает запрос драйверу на удаленном узле и возвращает клиенту дескриптора узла, идентификаторы канала и процесса драйвера последовательного порта.

  4. Клиент создает соединение с драйвером последовательного порта на узле nodeB и, в конечном счете, получает идентификатор соединения, который будет использоваться для последующих операций обмена сообщениями.

    После этого обмен сообщениями на данном соединении происходит так же, как и при локальной отправке сообщений. С этого момента все последующие операции происходят напрямую между клиентом и сервером (драйвером).

Ключевая особенность состоит в том, что клиент не знает о производимых операциях — они реализованы внутри функции open(). Клиент лишь выполняет функцию и получает файловый дескриптор, соответствующий идентификатору соединения, или код ошибки.


Note: На каждом последующем шаге из запроса клиента удаляются компоненты имени, которые были разрешены. Так, на шаге 2 запрос содержит лишь к nodeB/dev/ser1. На шаге 3 остается dev/ser1, так как это все, что должен знать удаленный менеджер процессов. И, наконец, на шаге 4 запрос содержит лишь пустую строку, так как префикс драйвера последовательного порта не является каталоговым.

Служба глобальных имен (GNS)

В приведенных примерах удаленные службы или файлы расположены на известных узлах и по известным путям. Например, последовательный порт на узле nodeB находится по известному пути /net/nodeB/dev/ser1.

Служба глобальных имен (англ. Global Name Service, GNS) позволяет определить местонахождение служб по их именам независимо от того, находятся ли они в локальной системе или на некотором удаленном узле. Например, если необходимо обнаружить модем в сети, можно просто применить поиск по имени "modem". В результате вместо использования статичного пути вроде /net/nodeB/dev/modem, GNS-сервер позволяет найти сетевую службу с именем "modem". GNS-сервер можно настроить таким образом, чтобы он обслуживал все или часть узлов в сети Qnet. Кроме того, в сети может быть несколько GNS-серверов.

Именование сетевых ресурсов

Как уже упоминалось, префикс /net используется менеджером lsm-qnet.so наиболее часто. При разрешении имен в сетевом пространстве используются определенные термины:

Имя узла (Node Name)
Последовательность символов, которая идентифицирует узел. Следует отметить, что имя узла не может содержать символы / или .. В приведенном ранее примере в качестве имени одного из узлов использовалось nodeB. Значение по умолчанию можно получить с помощью функции confstr() с параметром _CS_HOSTNAME.
Домен узла (Node Domain)
Последовательность символов, которую менеджер lsm-qnet.so "прикрепляет" к имени узла. Имя узла и домен узла вместе образуют уникальный для узла идентификатор. Значение по умолчанию можно получить с помощью функции confstr() с параметром _CS_DOMAIN.
Полностью определенное имя узла (Fully Qualified Node Name, FQNN)
Последовательность символов, состоящая из имени узла и домена узла. Например, если имя узла nodeB, а домен узла kpda.ru, то FQNN будет соответствовать nodeB.kpda.ru.
Сетевой каталог (Network Directory)
Каталог в пространстве имен, организованный lsm-qnet.so. Каждый сетевой каталог (на узле их может быть множество) связан со своим доменом узла. Каталогом по умолчанию является /net.
Разрешение имен (Name Resolution)
Процесс, с помощью которого менеджер lsm-qnet.so преобразует FQNN в список адресов назначения, которые известны транспортному уровню.
Распознаватель имен (Name Resolver)
Программный код, который реализует некоторый метод преобразования FQNN в список адресов назначения. Каждый сетевой каталог имеет список распознавателей имен, которые по очереди применяются для разрешения FQNN. По умолчанию используется en_ionet (см. далее).
Качество обслуживания (Quality of Service, QoS)
Определение степени связности между двумя узлами. По умолчанию в качестве QoS используется политика балансировки нагрузки (loadbalance).

Распознаватели имен

В сетевой менеджер интегрированы три распознавателя имен (name resolver):

en_ionet (используется по умолчанию)
Рассылает широковещательные запросы на разрешение имен по сети (протокол схож с TCP/IP ARP).
dns
Этот распознаватель действует следующим образом: берет имя узла, добавляет символ . и следом домен узла. Полученная строка становится результатом функции gethostbyname().
file
Предназначен для поиска доступных узлов, включая соответствующий сетевой адрес, в статическом файле.

Качество обслуживания (QoS) и резервированные соединения

Политика качества обслуживания (QoS) — это тот вопрос, который часто возникает в сетях высокой готовности, а также в системах управления реального времени. В сетях Qnet задача QoS по сути сводится к выбору среды передачи. В системе с несколькими сетевыми интерфейсами Qnet выберет тот, который больше соответствует заданной политике качества обслуживания.


Note: Если в системе предусмотрен только один сетевой интерфейс, то политика QoS не применяется.

Политики качества обслуживания

Qnet поддерживает передачу по нескольким сетям (интерфейсам). Для этого предусмотрены следующие политики качества обслуживания, которые позволяют определять наиболее подходящий сетевой интерфейс для передачи:

Балансировка нагрузки (loadbalance, используется по умолчанию)
Политика позволяет Qnet использовать все доступные сетевые интерфейсы и распределять трафик между ними в равной мере.
Предпочтительный канал (preferred)
Позволяет использовать выделенный канал связи и игнорировать все остальные. Кроме случаев, когда он оказывается недоступен.
Эксклюзивный канал (exclusive)
Позволяет использовать выделенный канал связи и игнорировать все остальные, даже если он оказывается недоступен.

Для получения преимуществ от использования QoS в Qnet, необходимо иметь физически отделенные сети. Например, рассмотрим конфигурацию сети с двумя узлами и общим хабом, причем, каждый узел имеет два подключения к нему:

13_3.png
Рисунок 3. Qnet в единой сети

Если канал, который используется в данный момент, становится недоступен, Qnet обнаруживает это, но не может переключиться на другой канал, поскольку они оба подключены к одному хабу. Приложение само должно исправить ошибку и только когда оно повторно установит соединение, Qnet переключится на рабочий канал.

Рассмотрим схожую конфигурацию сети, но включающую два хаба:

13_4.png
Рисунок 4. Qnet и физически разделенные сети

Если сети физически разделены и один из каналов становится недоступным, Qnet автоматически переключается на другое соединение, в зависимости от выбранной политики QoS. В этом случае приложение не узнаёт, что используемый канал стал недоступен.

Можно указать опцию tx_retries модуля lsm-qnet.so, чтобы ограничить количество попыток повторной передачи через сбойный канал. Это позволяет контролировать длительность ожидания со стороны Qnet перед признанием сетевого интерфейса недоступным. Следует учесть, что если количество попыток повторных передач слишком маленькое, то Qnet не будет допускать потери пакетов и может начать постоянно и преждевременно считать, что тот или иной канал стал недоступен.

Рассмотрим QoS политики подробнее.

Балансировка нагрузки (loadbalance)

Qnet решает, какие каналы связи использовать для передачи пакетов данных в зависимости от текущей нагрузки и пропускной способности сетевых интерфейсов, определенной менеджером io-pkt-*. Пакет ставится в очередь на отправку того канала, который способен быстрее других доставить пакет до пункта назначения. Такой подход эффективно обеспечивает высокую пропускную способность между узлами по корректно функционирующим каналам (пропускная способность между узлами определяется как сумма пропускных способностей всех доступных им каналов) и в случае сбоя канала — плавное ограничение передачи данных оптимальным способом.

Если канал перестает функционировать, Qnet обеспечит переключение на иной доступный канал. В первый раз такое переключение происходит в течение нескольких секунд, так как сетевой драйвер на неисправном канале связи выдерживает таймаут и лишь затем делает повторную попытку передачи. Только после этого соединения на данном канале считаются обрушенными. После этого Qnet получит уведомление о том, что данный канал не функционирует и перестанет использовать его для передачи пользовательских данных.

В процессе перебалансировки нагрузки между доступными каналами Qnet будет периодически отправлять сервисные пакеты по неисправному каналу для обнаружения факта его восстановления. Как только данное событие будет обнаружено, канал вновь помещается в список используемых.


Note: Данная политика используется по умолчанию.

Предпочтительный канал (preferred)

При использовании этой политики задается предпочтительный канал передачи. Qnet будет использовать только этот канал, при условии, что он остается работоспособным. При его сбое, Qnet переключится на другие доступные каналы и продолжит передачу данных в соответствии с политикой loadbalance.

Как только обнаружится восстановление предпочтительного канала связи, Qnet возвращается к исходной логике его использования, игнорируя все остальные.

Эксклюзивный канал (exclusive)

Эта политика используется в тех случаях, когда необходимо жестко привязать передачу данных только к одному каналу связи. Независимо от доступности других каналов, 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.


Caution: Символьные ссылки в каталоге /net создавать нельзя.

Благодаря возможности создавать символьные ссылки для сетевых префиксов, появляется возможность обращаться к одному и тому же сетевому сервису с помощью разных QoS-метрик. И наоборот, может существовать несколько серверов, предоставляющих один сервис. Если один сервер отказывает, абстрактное путевое имя может быть переназначено на другой сервер. Например, если узел nodeA отказал, то переназначение сервиса можно выполнить командой:

rm /remote/sql_server ln -sP /net/nodeB /remote/sql_server

В результате служба будет переназначена с узла nodeA на nodeB. Удобство состоит в том, что приложения можно разрабатывать без использования жестко заданных имен узлов.

Примеры

Рассмотрим ряд примеров использования прозрачной распределенной сети Qnet.


Note: Следует помнить, что менеджер распределенной сети 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.




Предыдущий раздел: перейти