Что такое шина в программировании
Перейти к содержимому

Что такое шина в программировании

  • автор:

Что такое шина в программировании

Одно из основных требований современного клиентского программного обеспечения — синхронизация состояния между несколькими устройствами. Это как устройства в рамках концепции "Интернета вещей", так и пользовательские приложения, которые должны работать на различных устройствах одного пользователя.

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

Для организации реактивного поведения программного обеспечения используют в основном две архитектурные концепции:

  • очередь сообщений
  • шина сообщений

Очередь и шина могут использоваться не только в распределенных системах, но так же внутри приложения, как способ объединить между собой изолированные компоненты. Это позволяет управлять зацеплением и сложностью программы.

Об основных принципах построения, технических ограничениях, горизонтальном масштабировании поговорим в этом стриме.

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

Простая шина

Интересно рассмотреть следующие особенности шины, используемой в вычислительно технике:

Шина это просто провод

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

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

  • локальные
  • внешние

У шин есть два варианта реализации:

  • последовательная
  • параллельная

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

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

Под каждую задачу своя шина

В компьютере шины делят по своему назначению "шина данных", "адресная шина", "шина управления". Это позволяет упростить обработку данных, находящихся в шине и решет проблему одновременной обработки данных. параллельно можно обрабатывать данные только в нескольких шинах.

Шина не определяет когда из нее должны быть считаны данные

Для того чтобы получить корректные данные из шины клиентская часть должна определить момент, в который на шине выставлены нужные данные, в цифровой технике это решается путем использования тактовых генераторов, но для нас принципиально, что в задачи шины не входит оповещение о изменении своего состоянии или готовности данных для считывания

Очередь как расширение ограничений шины

Так как шина не хранит данные, не оповещает о изменении данных, не гарантирует целостность данных, то для в программном обеспечении как правило используется комбинация "шина" + "очередь сообщений". Очередь — это реализации классической структуры данных, функционирующей по принципу FIFO. В задачи такого решения входит и накопление сообщений, и оповещение клиентов о получении новых сообщений, и гарантии доставки сообщений.

Таким образом очередь сообщений — это усовершенствованная идея "шины" из вычислительной техники. Однако на практике реализация простой шины в реактивных приложениях может оказать сильно проще и предпочтительнее использования "очереди сообщений"

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

Так как шина не имеет истории сообщений, то в момент доставки сообщения существует два варианта поведения шины:

  • новые сообщения не принимаются в доставку;
  • доставка предыдущего сообщения прекращается и все клиенты начинают получать новое сообщение;

Общая архитектура шины

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

Очередь — это усовершенствованная идея работы шины сообщений. Для реализации вносятся следующие изменения:

  • сообщения сохраняются в очередь
  • доступ к сообщениям по принципу очереди (сообщения извлекаются из очереди)
  • информация о изменениях очереди направляется через события (опционально)

Общая архитектура очереди

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

Прием сообщения осуществляется в несколько этапов:

  • сначала сообщение принимается в буфер обмена;
  • затем сообщение обрабатывается (приводится из текстового вида в структуры данных);
  • затем отправитель уведомляется об успешной приемке сообщения.

Разные стадии отказа

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

Для проектирования необходимо принять решение о стратегии доставки сообщений. Выделяют следующие стратегии доставки сообщений:

  • Доставка без подтверждения (0, 1 или много);
  • Доставка минимум одной копии сообщений (1 или много — at most once) ;
  • Доставка максимум одной копии сообщения (0 или 1 — at least once);
  • Доставка только одной копии сообщения (только 1 — exactly once).

Для шины сообщений используется как правило доставка без подтверждения или доставка максимум одной копии, для очереди как правило используется все варианты кроме доставки без подтверждения.

Шина сообщений организуется на базе двух вариантов доставки:

  • широковещательная
  • адресная

Широковещательная

Широковещательная

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

  • простая схема;
  • хорошо масштабируется (могут быть построены гетерогенные схемы где клиенты являются пользователями или серверами);
  • Большой overhead
  • плохая безопасность (все получат сообщение, даже если оно им не предназначается)

Адресная

Широковещательная

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

  • низкий overhead
  • возможность маршрутизации сообщений

Способы получения сообщений

Разделяют активный и пассивный способ получения данных или push/pull подходы

Это активный способ, при котором сообщение не хранится на сервере (или хранится только в рамках окна синхронизации), а отправляется всем клиента, имеющим активное подключение (push).

Либо сообщение отправляется во все эндпоинты серверов, неподключенных к шине

В шине не реализуется

Сообщения

Способ рассылки оповещений не используется в шине, так как шина не хранит данные долгосрочно (кроме технологических временных окон).

Очередь поддерживает так же pull и push режимы работы, но кроме этого дополнительно может оповещать клиентов о получении сообщений.

Очередь не поддерживает широковещательный способ доставки сообщений, но на практике такой способ доставки поддерживается и в таком случае очередь функционирует как обычная шина.

Режимы работы очереди следующие:

Общий режим

В этом режиме к очереди сообщений имеют доступ все пользователи и сообщения извлекаются из очереди первым обратившимся клиентом

Приватный режим

В этом режиме для каждого клиента ведется своя очередь сообщений, при этом возможно копирование одного и того же сообщения нескольким приватным адресатам (широковещательная рассылка)

Способы получения сообщений

Варианты реализации

Может быть реализована только в приватном режиме, в таком случае все клиенты получают свои сообщения сразу после получения на сервере

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

Существует возможность ограничить время хранения сообщений и если они не были переданы в отведенный интервал времени переложить их в специальную очередь недоставленных сообщений.

События

Очередь с событиями

В случае pull режима очередь может оповещать клиентов о получении сообщений через рассылку событий.

События — это по сути облегченный вариант сообщения. Такой вариант имеет смысл, когда объем данных, передаваемый в сообщении через очередь будет слишком велик, тогда существует возможность "легкого" оповещения клиента и предоставление ему возможности длительной загрузки сообщения.

Спецификация API BUS шина

Техническая спецификация работы API. Данная документация определяет принципы, по которым работает API протокол. Эта спецификация общая для Облачных Операционных Систем и для Облачных Интеграторов.

Определения

JWT – JSON Web Token это открытый стандарт (RFC 7519) для создания токенов доступа, основанный на JSON формате. Как правило, используется для передачи данных авторизации в клиент-серверных приложениях.

Frontend – то, что выполняется в браузере клиента, отвечает за динамический HTML.

Backend – обеспечивает обработку API запросов от Frontend'a и выдачи ответа на запрос, обычно работает на стороне сервера, либо в фоне веб приложения.

Bus – универсальная шина обмена данными и событиями между разными узлами системы

BusProvider – транспорт шины, который обеспечивает обмен сообщениями

SystemBus – внутренняя шина системы между ее элементами или микросервисами.

ExternalBus – внешняя шина, взаимодействия между Backend и Frontend.

Работа шины

Принцип работы шины в следующем. Существуют приложения, облачное ПО и микросервисы. Все они должны обмениваться данными. Обмен данными происходит через брокера сообщений, либо напрямую через TCP или HTTP. Облачная система сама определяет, как она будет осуществлять обмен сообщениями.

https://amdy.su/wp-admin/options-general.php?page=ad-inserter.php#tab-8

Каждое приложение должно обладать уникальным app_name. По этому ID будут отправляться сообщения в это приложение.

У каждого приложения есть виртуальное пространство — space_id. Пространство — это логический уровень интеграции данных. У одинакового space_id данные в разных приложениях связаны между собой и представляют собой единое пространство данных. В этом пространстве определяются роли и права доступа пользователей.

Внешний gateway может проверить авторизацию или в какой конкретно экземпляр app_name нужно отправить запрос. Например, существует тестовый экземпляр для отладки. Для него создается отдельный тестовый space_id и все запросы с этим space передаются в экземпляр для отладки. space_id нужен также для того, чтобы иметь возможность запускать разные версии приложений. Один и тот же пользователь может обладать доступом к разным пространствам.

В шину можно посылать разные типы запросов: уведомления о событиях, очереди на обработку данных, RPC вызовы, потоки данных загрузки файла или медиа стримы.

Вызов происходит, направляя соответсвующий запрос к объекту. У вызова есть 3 параметра:

  • api_name — название объекта
  • interface_name — интерфейс объекта
  • method_name — метод, который должен быть вызван

Интерфейс объекта — это стандарт, который может реализовывать объект. Каждый объект должен одинаковым образом реализовывать один и тот же стандарт. Один из примером стандарта — CRUD.

Схема работы


Рисунок — Структура системной и внешней шин

В языке BAY определено две шины: системная и внешняя. Системная шина используется для общения внутри backend системы. Между внутренними компонентами, микросервисами, которые всегда доступны. Общение может происходить через различные провайдеры: TCP, RabbitMQ, D-BUS, HTTP JSON, GRPC, SOAP, Message Pack. Вариант реализации провайдера системной шины в разных бэкендах и системах может быть разный. Системная шина может обращаться к api внешней шины. При этом user_id у нее должен быть равен -1000.

Backend может состоять из нескольких микросервисов. Микросервисы связаны между собой через общую системную BUS шину. Посылая запросы, сообщения и события в шину, можно обащаться с другими микросервисами системы. К микросервисам могут быть отнесено Облачное ПО, которое является частью общей интранет системы.

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

К системной шине подключается Bus Gateway. Это API шлюз доступа к системе. API шлюз это фаервол. Он проверяет правильность входного пакета, авторизацию пользователя, сессии и в зависимости от результата отклоняет запрос или передает его в шину. API шлюз может также кэшировать некоторые API запросы, если в этом есть необходимость. Также шлюз может отвечать за раздачу статических файлов. Шлюзов в системе может быть несколько. Они могут обеспечивать балансировку нагрузку системы. Шлюзом может быть Nginx, написанный на OpenResty. С Bus Gateway общаются внешние компоненты: фронтенд пользователя, IoT устройства, внешние облачные системы.

Также системные запросы могут обрабатываться через шлюз Bus Gateway, но тогда должна:

  • производиться проверка по IP адресам.
  • проверка времени, когда был послан запрос.
  • обязательно запросы должны быть подписаны ключом. Параметр sign в теле запроса. Формат подписи определяется провайдером данных.

Чтобы подключить две системы друг к другу более тесно, лучше использовать Bus Connector.

Внешняя шина — это шина взаимодействия Шлюза (Bus Gateway) и внешних систем. К внешним системам относятся: фронтенд, мобильное приложение, IoT устройства, внешние облачные системы, интранет системы, 1С, сайты, агрегаторы и т.д. Внешняя шина может работать через разные провайдеры: HTTP JSON, GRPC, SOAP, Message Pack, XML-RPC и т.п.


Рисунок — внешняя шина

Примеры HTTP запросов к шлюзу Bus Gateway

Точка входа запроса для внешней шины:

Точка входа запроса для системной шины:

При системном вызове параметр запроса "kind" должен быть равен "system", при внешнем — "user".

Подключение двух шин друг к другу

Возможно подключение двух системных или нескольких шин друг к другу. Чтобы это сделать, нужно использовать BUS Connector. В коннекторе требуется указать адреса подключаемых шин. Коннектор сканирует шины на наличие приложений. Приложения в двух шинах должны быть уникальны. После сканирования Коннетор начинает слушать сообщения в двух шинах. И если там возникает сообщения для приложения из другой шины, то он перенаправляет запрос в другую шину и возвращает ответ. Bus Connector требует наличия постоянного соединения к шинам.


Рисунок — Подключение двух шин

Формат запроса и ответа

Запрос

  • time — время (unix time), когда было послано сообщения.
  • message_id — Уникальный идентификатор сообщения. По нему отправитель сообщения будет получать ответ.
  • case — формат сообщения (event – событие, rpc – выполнение метода, stream – потоки)
  • kind — тип сообщения (system – системное, user – пользовательское)
  • to — кому предназначено сообщение app_name
  • from — кто послал сообщение app_name
  • volume_id — слой данных (виртуальное пространство)
  • locale — в какой локали выдавать ответ
  • api_name — название объекта
  • space_name — название интерфейса объекта
  • method_name — название метода
  • data — передаваемые данные
  • jwt — токен авторизации для внешней шины
  • sign — подпись для системной шины, если провайдер не пользволяет делать авторизацию

Ответ

  • time — время (unix time), когда было послано сообщения.
  • message_id — Уникальный идентификатор сообщения. По нему отправитель сообщения будет получать ответ.
  • case — формат сообщения (answer — ответ)
  • kind — тип сообщения (system – системное, user – пользовательское)
  • to — кому предназначено сообщение (кто ранее отправил сообщение)
  • from — кто послал сообщение (кому ранее предназначалось сообщение)
  • volume_id — слой данных (виртуальное пространство)
  • locale — в какой локали выдавать ответ
  • api_name — название объекта
  • space_name — название интерфейса объекта
  • method_name — название метода
  • response — данные ответа на запрос
  • code — код ответа. > 0 – запрос успешен. < 0 – ошибка. 0 – неизвестное состояние
  • success_message — положительный результат
  • error_message — сообщение об ошибке
  • error_name — имя ошибки (Обычно название класса Exception)
  • error_trace — трассировка ошибки, если включен debug у приложения
  • have_answer — backend ответил на запрос

Пример запроса

Запрос ping — это запрос проверки состояния системы healthcheck. Посылается запрос ping с текущим временем, и система должна вернуть это время. Вместо <app_api_name> ставиться системное название приложения, или self.

Как построить надёжную шину данных на Apache Kafka

Всем привет! Я Павел Агалецкий, ведущий инженер в Авито. Мы в компании используем микросервисную архитектуру с синхронным и асинхронным обменом событиями. В какой-то момент нам стало нужно обеспечивать более надёжную передачу сообщений. Стандартной Apache Kafka нам для этого было мало. Так мы пришли к идее, что пора строить собственную шину данных.

Зачем нужна шина данных

Микросервисы можно подключить к Apache Kafka напрямую. Это быстро и просто: нужно развернуть кластер, дать продюсерам (отправителям) и консьюмерам (получателям) адрес подключения и разрешить обмениваться событиями.

У такого подхода есть весомые минусы:

Сложно менять топологию системы. Если вы захотите отказаться от Kafka или разделить её на несколько кластеров, придётся обновить клиенты для всех пользователей, поменять адреса и настройки.

Под каждый язык разработки нужен свой клиент. В Авито мы пишем на Go, PHP, Python и других, получается зоопарк из разных систем только для обмена событиями.

С ростом системы прочитать сообщения из Kafka становится сложнее из-за растущей нагрузки.

Поэтому мы решили пойти другим путём и поставили между Kafka и микросервисами data bus, или шину данных. Она изолирует Kafka от сервисов и берет на себя получение и отправку сообщений получателям и реализует взаимодействие с Apache Kafka.

Шина отделяет микросервисы друг от друга и от Kafka

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

Микросервисы подключаются к шине по протоколу websocket, а сама шина работает с Kafka напрямую

Шина напрямую взаимодействует с Kafka и скрывает все особенности работы с ней. Разработчикам микросервисов не нужно знать ничего об офсетах, хранении событий. Команда поддержки разработала три клиента для разных языков программирования, чтобы инженерам Авито не приходилось разбираться в Kafka.

Кроме того, шина предоставляет разработчикам универсальные метрики. Например, скорость записи и чтения, количество публикуемых событий, время обработки событий, размер бэклога. Все эти данные пользователи получают из нашего сервиса сразу после подключения, без специальных действий. Это помогает разработчикам в отладке микросервисов.

Сейчас шина данных — центральная система Авито. Средняя нагрузка на неё составляет порядка 3 миллионов запросов на запись и около 10 миллионов запросов на чтение в минуту. Её постоянно используют больше 500 сервисов компании, поэтому наша главная цель — обеспечить физическую надёжность и доступность системы.

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

Архитектура шины данных на основе Apache Kafka

Сначала у нас был один большой кластер Kafka, распределенный между несколькими дата-центрами Авито. На тот момент мы полагались на возможность самой Kafka восстанавливаться после отказа части серверов, которые входят в её кластер.

Одна большая Kafka была растянута между всеми дата-центрами Авито

Этот подход оказался для нас не очень удачным. Когда все серверы и дата-центры доступны, шина работала хорошо. Но при отключении дата-центра появлялась заметная просадка Latency.

Момент отключения одного дата-центра. Время записи в нашу систему достигает 30 секунд

Это происходило, потому что на момент отключения в Kafka было довольно много топиков, которые имели больше 15 тысяч партиций. При отключении дата-центра и потери связи с частью брокеров выполнялся ребаланс, выбирался новый мастер и в это время топики становились недоступны для записи. Это сильно влияло на работу всех наших пользователей.

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

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

Общая схема архитектуры Kafka Federation

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

Микросервисы-продюсеры записывают данные в шину, которая находится в одном с ними кластере. Затем шина передает событие во Write Kafka, доступную только для записи.

Первый шаг: микросервисы могут только записывать данные локально

Затем события из Write Kafka с помощью репликатора записываются в общую центральную Kafka. Её мы реализовали по старой схеме — распределили один кластер между всеми дата-центрами.

Второй шаг: репликатор копирует событие из локальных Kafka в центральную

Центральная Kafka доступна для записи и чтения. Она подвержена тем же проблемам: медленная запись, высокий Latency. Но для пользователей это становится незаметным, потому что для них запись выполняется сначала в локальную Write Kafka.

Задержку замечает только репликатор: при возникновении проблем с дата-центром, он какое-то время не может переложить данные в большую Kafka. Но это не влияет на качество работы всех систем Авито.

Чтение с центральной Kafka тоже осуществляется репликами шины данных, расположенными в каждом из дата-центров. А уже к ним, в свою очередь, подключаются микросервисы-консьюмеры.

Третий шаг: шина данных считывает сообщение из центральной Kafka и передает его консьюмерам

Так у нас получилась система, которая всегда доступна на запись вне зависимости от отказа того или иного дата-центра. Даже если один из них недоступен, микросервисы в остальных дата-центрах продолжают работу.

Как мы обеспечили логическую надежность шины данных

Микросервисы Авито постоянно эволюционируют: у них меняются данные и наборы событий, которые они публикуют и читают. Система должна уметь проверять сообщения и сохранять консистентность данных, чтобы ничего не сломалось из-за изменений. При этом все пользователи шины должны быть уверены, что они при любых условиях смогут прочитать события и получить валидные данные. Поэтому с точки зрения логической надёжности нам нужно было реализовать схемы сообщений и их валидацию.

Схема сообщения, или контракт — это описание того, что продюсер записывает, а консьюмер читает: какие у его события есть поля, типы данных. Разработчики прямо в коде микросервиса в специальной директории указывают события, которые они публикуют или читают.

Внутри Авито мы используем для описания синхронных и асинхронных схем обменов Brief — текстовый формат строгой типизации. Он недоступен вне компании, но по структуре описания похож на gRPC.

Схема события в формате Brief:

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

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

Схема валидации данных при развертывании микросервера

Шина проверяет ряд критериев: наличие обязательных полей, совпадение полей и типов данных для продюсера и консьюмера.

Также шина запрещает микросервисам выполнять не валидные действия. Например, мы не даем возможность продюсеру удалить событие, у которого есть консьюмер. То есть сначала нужно убрать ожидание этого сообщения во всех сервисах-получателях, а затем — в сервисе-продюсере. Другой пример — нельзя поменять тип поля со строки на число или обратно.

Итоги

Шина данных способна пережить отказ отдельных серверов или даже дата-центра. В продакшене система работает уже больше трех лет. За последние полтора года не было ни одного серьезного инцидента, связанного с недоступностью или отказом.

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

Шина данных скрывает от пользователей все нюансы работы с Kafka. Нам это помогло незаметно заменить схему с одним экземпляром системы на Kafka Federation.

Сейчас мы думаем о дальнейших улучшения топологии. Одна из главных задач — уйти от единой точки отказа в виде общей для всех Apache Kafka. Если мы решим поменять топологию или даже заменить Apache Kafka на какое-то другое решение, то сможем сделать это незаметно для пользователей. Для них переход будет прозрачным, так как мы сохраняем наш API и не меняем точки входа, как бы ни менялась топология шины данных внутри.

Если решим поменять инструмент, нам не придется беспокоить пользователей — для них переход снова будет незаметным.

Что такое шина в программировании

В вычислительной системе, состоящей из множества подсистем, необходим механизм для их взаимодействия. Эти подсистемы должны быстро и эффективно обмениваться данными. Например, процессор, с одной стороны, должен быть связан с памятью, с другой стороны, необходима связь процессора с устройствами ввода/вывода. Одним из простейших механизмов, позволяющих организовать взаимодействие различных подсистем, является единственная центральная шина, к которой подсоединяются все подсистемы. Доступ к такой шине разделяется между всеми подсистемами. Подобная организация имеет два основных преимущества: низкая стоимость и универсальность. Поскольку такая шина является единственным местом подсоединения для разных устройств, новые устройства могут быть легко добавлены, и одни и те же периферийные устройства можно даже применять в разных вычислительных системах, использующих однотипную шину. Стоимость такой организации получается достаточно низкой, поскольку для реализации множества путей передачи информации используется единственный набор линий шины, разделяемый множеством устройств.

Главным недостатком организации с единственной шиной является то, что шина создает узкое горло, ограничивая, возможно, максимальную пропускную способность ввода/вывода. Если весь поток ввода/вывода должен проходить через центральную шину, такое ограничение пропускной способности весьма реально. В коммерческих системах, где ввод/вывод осуществляется очень часто, а также в суперкомпьютерах, где необходимые скорости ввода/вывода очень высоки из-за высокой производительности процессора, одним из главных вопросов разработки является создание системы нескольких шин, способной удовлетворить все запросы.

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

Традиционно шины делятся на шины, обеспечивающие организацию связи процессора с памятью, и шины ввода/вывода. Шины ввода/вывода могут иметь большую протяженность, поддерживать подсоединение многих типов устройств, и обычно следуют одному из шинных стандартов. Шины процессор-память, с другой стороны, сравнительно короткие, обычно высокоскоростные и соответствуют организации системы памяти для обеспечения максимальной пропускной способности канала память-процессор. На этапе разработки системы, для шины процессор-память заранее известны все типы и параметры устройств, которые должны соединяться между собой, в то время как разработчик шины ввода/вывода должен иметь дело с устройствами, различающимися по задержке и пропускной способности.

Как уже было отмечено, с целью снижения стоимости некоторые компьютеры имеют единственную шину для памяти и устройств ввода/вывода. Такая шина часто называется системной. Персональные компьютеры, как правило, строятся на основе одной системной шины в стандартах ISA, EISA или MCA. Необходимость сохранения баланса производительности по мере роста быстродействия микропроцессоров привела к двухуровневой организации шин в персональных компьютерах на основе локальной шины. Локальной шиной называется шина, электрически выходящая непосредственно на контакты микропроцессора. Она обычно объединяет процессор, память, схемы буферизации для системной шины и ее контроллер, а также некоторые вспомогательные схемы. Типичными примерами локальных шин являются VL-Bus и PCI.

Рассмотрим типичную транзакцию на шине. Шинная транзакция включает в себя две части: посылку адреса и прием (или посылку) данных. Шинные транзакции обычно определяются характером взаимодействия с памятью: транзакция типа "Чтение" передает данные из памяти (либо в ЦП, либо в устройство ввода/вывода), транзакция типа "Запись" записывает данные в память. В транзакции типа "Чтение" по шине сначала посылается в память адрес вместе с соответствующими сигналами управления, индицирующими чтение. Память отвечает, возвращая на шину данные с соответствующими сигналами управления. Транзакция типа "Запись" требует, чтобы ЦП или устройство в/в послало в память адрес и данные и не ожидает возврата данных. Обычно ЦП вынужден простаивать во время интервала между посылкой адреса и получением данных при выполнении чтения, но часто он не ожидает завершения операции при записи данных в память.

Разработка шины связана с реализацией ряда дополнительных возможностей (рисунок 5.43). Решение о выборе той или иной возможности зависит от целевых параметров стоимости и производительности. Первые три возможности являются очевидными: раздельные линии адреса и данных, более широкие (имеющие большую разрядность) шины данных и режим групповых пересылок (пересылки нескольких слов) дают увеличение производительности за счет увеличения стоимости.

Следующий термин, указанный в таблице, — количество главных устройств шины (bus master). Главное устройство шины — это устройство, которое может инициировать транзакции чтения или записи. ЦП, например, всегда является главным устройством шины. Шина имеет несколько главных устройств, если имеется несколько ЦП или когда устройства ввода/вывода могут инициировать транзакции на шине. Если имеется несколько таких устройств, то требуется схема арбитража, чтобы решить, кто следующий захватит шину. Арбитраж часто основан либо на схеме с фиксированным приоритетом, либо на более "справедливой" схеме, которая случайным образом выбирает, какое главное устройство захватит шину.

В настоящее время используются два типа шин, отличающиеся способом коммутации: шины с коммутацией цепей (circuit-switched bus) и шины с коммутацией пакетов (packet-switched bus), получившие свои названия по аналогии со способами коммутации в сетях передачи данных. Шина с коммутацией пакетов при наличии нескольких главных устройств шины обеспечивает значительно большую пропускную способность по сравнению с шиной с коммутацией цепей за счет разделения транзакции на две логические части: запроса шины и ответа. Такая методика получила название "расщепления" транзакций (split transaction). (В некоторых системах такая возможность называется шиной соединения/разъединения (connect/disconnect) или конвейерной шиной (pipelined bus). Транзакция чтения разбивается на транзакцию запроса чтения, которая содержит адрес, и транзакцию ответа памяти, которая содержит данные. Каждая транзакция теперь должна быть помечена (тегирована) соответствующим образом, чтобы ЦП и память могли сообщить что есть что.

Шина с коммутацией цепей не делает расщепления транзакций, любая транзакция на ней есть неделимая операция. Главное устройство запрашивает шину, после арбитража помещает на нее адрес и блокирует шину до окончания обслуживания запроса. Большая часть этого времени обслуживания при этом тратится не на выполнение операций на шине (например, на задержку выборки из памяти). Таким образом, в шинах с коммутацией цепей это время просто теряется. Расщепленные транзакции делают шину доступной для других главных устройств пока память читает слово по запрошенному адресу. Это, правда, также означает, что ЦП должен бороться за шину для посылки данных, а память должна бороться за шину, чтобы вернуть данные. Таким образом, шина с расщеплением транзакций имеет более высокую пропускную способность, но обычно она имеет и большую задержку, чем шина, которая захватывается на все время выполнения транзакции. Транзакция называется расщепленной, поскольку произвольное количество других пакетов или транзакций могут использовать шину между запросом и ответом.

Рис. 5.43. Основные возможности шин

Асинхронная шина, с другой стороны, не тактируется. Вместо этого обычно используется старт-стопный режим передачи и протокол "рукопожатия" (handshaking) между источником и приемником данных на шине. Эта схема позволяет гораздо проще приспособить широкое разнообразие устройств и удлинить шину без беспокойства о перекосе сигналов синхронизации и о системе синхронизации. Если может использоваться синхронная шина, то она обычно быстрее, чем асинхронная, из-за отсутствия накладных расходов на синхронизацию шины для каждой транзакции. Выбор типа шины (синхронной или асинхронной) определяет не только пропускную способность, но также непосредственно влияет на емкость системы ввода/вывода в терминах физического расстояния и количества устройств, которые могут быть подсоединены к шине. Асинхронные шины по мере изменения технологии лучше масштабируются. Шины ввода/вывода обычно асинхронные.

Стандарты шин

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

Иногда широкое распространение и популярность конкретных машин становятся причиной того, что их шина ввода/вывода становится стандартом де факто. Примерами таких шин могут служить PDP-11 Unibus и IBM PC-AT Bus. Иногда стандарты появляются также в результате определенных достижений по стандартизации в некотором секторе рынка устройств ввода/вывода. Интеллектуальный периферийный интерфейс (IPI — Intelligent Peripheral Interface) и Ethernet являются примерами стандартов, появившихся в результате кооперации производителей. Успех того или иного стандарта в значительной степени определяется его принятием такими организациями как ANSI (Национальный институт по стандартизации США) или IEEE (Институт инженеров по электротехнике и радиоэлектронике). Иногда стандарт шины может быть прямо разработан одним из комитетов по стандартизации: примером такого стандарта шины является FutureBus.

Рис. 5.44. Примеры стандартных шин

Одной из популярных шин персональных компьютеров была системная шина IBM PC/XT, обеспечивавшая передачу 8 бит данных. Кроме того, эта шина включала 20 адресных линий, которые ограничивали адресное пространство пределом в 1 Мбайт. Для работы с внешними устройствами в этой шине были предусмотрены также 4 линии аппаратных прерываний (IRQ) и 4 линии для требования внешними устройствами прямого доступа к памяти (DMA). Для подключения плат расширения использовались специальные 62-контактные разъемы. При этом системная шина и микропроцессор синхронизировались от одного тактового генератора с частотой 4.77 МГц. Таким образом теоретическая скорость передачи данных могла достигать немногим более 4 Мбайт/с.

Системная шина ISA (Industry Standard Architecture) впервые стала применяться в персональных компьютерах IBM PC/AT на базе процессора i286. Эта системная шина отличалась наличием второго, 36-контактного дополнительного разъема для соответствующих плат расширения. За счет этого количество адресных линий было увеличено на 4, а данных — на 8, что позволило передавать параллельно 16 бит данных и обращаться к 16 Мбайт системной памяти. Количество линий аппаратных прерываний в этой шине было увеличено до 15, а каналов прямого доступа — до 7. Системная шина ISA полностью включала в себя возможности старой 8-разрядной шины. Шина ISA позволяет синхронизировать работу процессора и шины с разными тактовыми частотами. Она работает на частоте 8 МГц, что соответствует максимальной скорости передачи 16 Мбайт/с.

С появлением процессоров i386, i486 и Pentium шина ISA стала узким местом персональных компьютеров на их основе. Новая системная шина EISA (Extended Industry Standard Architecture), появившаяся в конце 1988 года, обеспечивает адресное пространство в 4 Гбайта, 32-битовую передачу данных (в том числе и в режиме DMA), улучшенную систему прерываний и арбитраж DMA, автоматическую конфигурацию системы и плат расширения. Устройства шины ISA могут работать на шине EISA.

Шина EISA предусматривает централизованное управление доступом к шине за счет наличия специального устройства — арбитра шины. Поэтому к ней может подключаться несколько главных устройств шины. Улучшенная система прерываний позволяет подключать к каждой физической линии запроса на прерывание несколько устройств, что снимает проблему количества линий прерывания. Шина EISA тактируется частотой около 8 МГц и имеет максимальную теоретическую скорость передачи данных 33 Мбайт/с.

Шина MCA также обеспечивает 32-разрядную передачу данных, тактируется частотой 10 МГц, имеет средства автоматического конфигурирования и арбитража запросов. В отличие от EISA она не совместима с шиной ISA и используется только в компьютерах компании IBM.

Шина VL-bus, предложенная ассоциацией VESA (Video Electronics Standard Association), предназначалась для увеличения быстродействия видеоадаптеров и контроллеров дисковых накопителей для того, чтобы они могли работать с тактовой частотой до 40 МГц. Шина VL-bus имеет 32 линии данных и позволяет подключать до трех периферийных устройств, в качестве которых наряду с видеоадаптерами и дисковыми контроллерами могут выступать и сетевые адаптеры. Максимальная скорость передачи данных по шине VL-bus может составлять около 130 Мбайт/с. После появления процессора Pentium ассоциация VESA приступила к работе над новым стандартом VL-bus версии 2, который предусматривает использование 64-битовой шины данных и увеличение количества разъемов расширения. Ожидаемая скорость передачи данных — до 400 Мбайт/с.

Шина PCI (Peripheral Component Interconnect) также, как и шина VL-bus, поддерживает 32-битовый канал передачи данных между процессором и периферийными устройствами, работает на тактовой частоте 33 МГц и имеет максимальную пропускную способность 120 Мбайт/с. При работе с процессорами i486 шина PCI дает примерно те же показатели производительности, что и шина VL-bus. Однако, в отличие от последней, шина PCI является процессорно независимой (шина VL-bus подключается непосредственно к процессору i486 и только к нему). Ee легко подключить к различным центральным процессорам. В их числе Pentium, Alpha, R4400 и PowerPC.

Шина VME приобрела большую популярность как шина ввода/вывода в рабочих станциях и серверах на базе RISC-процессоров. Эта шина высоко стандартизована, имеется несколько версий этого стандарта. В частности, VME32 — 32-битовая шина с производительностью 30 Мбайт/с, а VME64 — 64-битовая шина с производительностью 160 Мбайт/с.

В однопроцессорных и многопроцессорных рабочих станциях и серверах на основе микропроцессоров SPARC одновременно используются несколько типов шин: SBus, MBus и XDBus, причем шина SBus применяется в качестве шины ввода/вывода, а MBus и XDBus — в качестве шин для объединения большого числа процессоров и памяти.

Шина SBus (известная также как стандарт IEEE-1496) имеет 32-битовую и 64-битовую реализацию, работает на частоте 20 и 25 МГц и имеет максимальную скорость передачи данных в 32-битовом режиме равную соответственно 80 или 100 Мбайт/с. Шина предусматривает режим групповой пересылки данных с максимальным размером пересылки до 128 байт. Она может работать в двух режимах передачи данных: режиме программируемого ввода/вывода и в режиме прямого доступа к виртуальной памяти (DVMA). Последний режим особенно эффективен при передаче больших блоков данных.

Шина MBus работает на тактовой частоте 50 МГц в синхронном режиме с мультиплексированием адреса и данных. Общее число сигналов шины равно 100, а разрядность шины данных составляет 64 бит. По шине передаются 36-битовые физические адреса. Шина обеспечивает протокол поддержания когерентного состояния кэш-памяти нескольких (до четырех) процессоров, имеет максимальную пропускную способность в 400 Мбайт/с, а типовая скорость передачи составляет 125 Мбайт/с. Отличительными свойствами шины MBus являются: возможность увеличения числа процессорных модулей, поддержка симметричной мультипроцессорной обработки, высокая пропускная способность при обмене с памятью и подсистемой ввода/вывода, открытые (непатентованные) спецификации интерфейсов.

Шина MBus была разработана для относительно небольших систем (ее длина ограничивается десятью дюймами, что позволяет объединить до четырех процессоров с кэш-памятью второго уровня и основной памятью). Для построения систем с большим числом процессоров нужна большая масштабируемость шины. Одна из подобного рода шин — XDBus, используется в серверах SPARCserver 1000 (до 8 процессоров) и SPARCcenter 2000 (до 20 процессоров) компании Sun Microsystems и SuperServer 6400 компании Cray Research (до 64 процессоров). XDBus представляет собой шину, работающую в режиме расщепления транзакций. Это позволяет ей, имея пиковую производительность в 400 Мбайт/с, поддерживать типовую скорость передачи на уровне более 310 Мбайт/с.

В современных компьютерах часто применяются и фирменные (запатентованные) шины, обеспечивающие очень высокую пропускную способность для построения многопроцессорных серверов. Одной из подобных шин является системная шина POWERpath-2, которая применяется в суперсервере Chellenge компании Silicon Graphics. Она способна поддерживать эффективную работу до 36 процессоров MIPS R4400 (9 процессорных плат с четырьмя 150 МГц процессорами на каждой плате) с общей расслоенной памятью объемом до 16 Гбайт (коэффициент расслоения памяти равен восьми). POWERpath-2 имеет разрядность данных 256 бит, разрядность адреса 40 бит, и работает на частоте 50 МГц с пониженным напряжением питания. Она поддерживает методику расщепления транзакций, причем может иметь до восьми отложенных транзакций чтения одновременно. При этом арбитраж шины адреса и шины данных выполняется независимо. POWERpath-2 поддерживает протокол когерентного состояния кэш-памяти каждого процессора в системе.

Одной из наиболее популярных шин ввода-вывода в настоящее время является шина SCSI.

Под термином SCSI — Small Computer System Interface (Интерфейс малых вычислительных систем) обычно понимается набор стандартов, разработанных Национальным институтом стандартов США (ANSI) и определяющих механизм реализации магистрали передачи данных между системной шиной компьютера и периферийными устройствами. На сегодняшний день приняты два стандарта (SCSI-1 и SCSI-2). Стандарт SCSI-3 находится в процессе доработки.

Начальный стандарт 1986 года, известный теперь под названием SCSI-1, определял рабочие спецификации протокола шины, набор команд и электрические параметры. В 1992 году этот стандарт был пересмотрен с целью устранения недостатков первоначальной спецификации (особенно в части синхронного режима передачи данных) и добавления новых возможностей повышения производительности, таких как "быстрый режим" (fast mode), "широкий режим" (wide mode) и помеченные очереди. Этот пересмотренный стандарт получил название SCSI-2 и в настоящее время используется большинством поставщиков вычислительных систем.

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

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

Стандарт SCSI-2 определяет в частности различные режимы: Wide SCSI, Fast SCSI и Fast-and-Wide SCSI. Стандарт SCSI-1 определяет построение периферийной шины на основе 50-жильного экранированного кабеля, описывает методы адресации и электрические характеристики сигналов. Шина данных SCSI-1 имеет разрядность 8 бит, а максимальная скорость передачи составляет 5 Мбайт/сек. Fast SCSI сохраняет 8-битовую шину данных и тем самым может использовать те же самые физические кабели, что и SCSI-1. Он отличается только тем, что допускает передачи со скоростью 10 Мбайт/сек в синхронном режиме. Wide SCSI удваивает либо учетверяет разрядность шины данных (либо 16, либо 32 бит), допуская соответственно передачи со скоростью либо 10, либо 20 Мбайт/сек. В комбинации Fast-and-Wide SCSI возможно достижение скоростей передачи 20 и 40 Мбайт/сек соответственно.

Однако поскольку в обычном 50-жильном кабеле просто не хватает жил, комитет SCSI решил расширить спецификацию вторым 66-жильным кабелем (так называемый B-кабель). B-кабель имеет дополнительные линии данных и ряд других сигнальных линий, позволяющие реализовать режим Fast-and-Wide.

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

Реализация режимов Wide-SCSI и Fast-and-Wide SCSI до 1994 года редко использовалась, поскольку эффективность их применения не была достаточно высокой. Однако широкое распространение дисковых массивов и дисковых накопителей со скоростью вращения 7200 оборотов в минуту делают эту технологию весьма актуальной.

Следует отметить некоторую путаницу в терминологии. Часто стандартный 50-контактный разъем также называют разъемом SCSI-1, а более новый микроразъем — разъемом SCSI-2. Стандарт SCSI определяет только количество жил в кабеле, и вообще не определяет тип разъема.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *