...

суббота, 7 сентября 2019 г.

[Перевод] Понимание брокеров сообщений. Изучение механики обмена сообщениями посредством ActiveMQ и Kafka. Глава 1

Всем привет!
Начал перевод небольшой книги:
"Understanding Message Brokers",
автор: Jakub Korab, издательство: O'Reilly Media, Inc., дата издания: June 2017, ISBN: 9781492049296.

Из введения к книге:
"… Эта книга научит вас рассуждать о системах обмена сообщениями на брокерах, сравнивая и противопоставляя две популярные технологии брокеров: Apache ActiveMQ и Apache Kafka. Здесь будут изложены примеры использования и стимулы разработки, которые привели к тому, что их разработчики использовали совершенно разные подходы к одной и той же области — обмену сообщениями между системами с промежуточным брокером. Мы рассмотрим эти технологии с нуля и выделим влияние различных вариантов дизайна на этом пути. Вы получите глубокое понимание обоих продуктов, понимание того, как их следует и не следует использовать, и понимание того, на что следует обращать внимание при рассмотрении других технологий обмена сообщениями в будущем ..."

Буду выкладывать законченные главы по мере перевода.

ГЛАВА 1


Введение


Межсистемный обмен сообщениями — это одна из наименее понимаемых областей ИТ. Как разработчик или архитектор, вы можете быть хорошо знакомы с различными фреймфорками и базами данных. Однако, вполне вероятно, что у вас есть только мимолетное знакомство с тем, как работают технологии обмена сообщениями, основанные на брокере. Если вы так себя и чувствуете, не волнуйтесь, вы в хорошей компании.
Люди обычно контактируют с инфраструктурой обмена сообщениями очень ограниченно. Нередко подключаются к системе, созданной давным-давно, или загружают дистрибутив из интернета, устанавливают его в ПРОМ и начинают писать под него код. После запуска инфраструктуры в ПРОМ, результаты могут быть неоднозначными: потеря сообщений при сбоях, отправка не работает так, как вы ожидали, или брокеры «подвешивают» ваших продьюсеров или не отправляют сообщения вашим потребителям.
Звучит знакомо?
Распространенный сценарий, когда ваш код обмена сообщениями работает отлично, до поры до времени. Пока не перестает работать. Этот период усыпляет бдительность и дает ложное чувство безопасности, что приводит к еще большему коду, основанному на ложных представлениях о фундаментальном поведении технологии. Когда что-то начинает идти не так, вы сталкиваетесь с неудобной истиной: что вы действительно не поняли базовое поведение продукта или компромиссы, выбранные авторами, такие как, производительность против надежности, или транзакционность против горизонтальной масштабируемости.
Без глубокого понимания того, как работают брокеры, люди делают, казалось бы, разумные утверждения об их системах обмена сообщениями, такие как:
  • Система никогда не потеряет сообщения
  • Сообщения будут обрабатываться последовательно
  • Добавление консьюмеров сделает систему быстрее
  • Сообщения будут доставлены только один раз

К сожалению, некоторые из этих утверждений основаны на предположениях, которые применимы только при определенных обстоятельствах, в то время как другие, просто неверны.
Эта книга научит вас рассуждать о системах обмена сообщениями, основанных на брокерах, сравнивая и противопоставляя две популярные технологии брокеров: Apache ActiveMQ и Apache Kafka. Здесь будут изложены примеры использования и стимулы разработки, которые привели к тому, что их разработчики использовали совершенно разные подходы к одной и той же области — обмену сообщениями между системами с промежуточным брокером. Мы рассмотрим эти технологии с нуля и выделим влияние различных вариантов дизайна на этом пути. Вы получите глубокое понимание обоих продуктов, понимание того, как их следует и не следует использовать, и понимание того, на что следует обращать внимание при рассмотрении других технологий обмена сообщениями в будущем.
Прежде чем мы начнем, давайте пройдемся по основам.

Что такое Система обмена сообщениями и зачем она нужна


Чтобы два приложения могли общаться друг с другом, они должны сначала определить интерфейс. Определение этого интерфейса включает выбор транспорта или протокола, такого как HTTP, MQTT или SMTP и согласование форматов сообщений, которыми будут обмениваться системы. Это может быть строгий процесс, такой как определение схемы XML с требованиями к затратам на полезную нагрузку (payload) сообщения, или это может быть гораздо менее формально, например, соглашение между двумя разработчиками о том, что некоторая часть HTTP-запроса будет содержать идентификатор клиента.
Пока формат сообщений и порядок их отправки между системами согласованы, они смогут взаимодействовать друг с другом, не заботясь о реализации другой системы. Внутренности этих систем, такие как язык программирования или использованный фреймфорк, могут со временем меняться. До тех пор, пока поддерживается сам контракт, взаимодействие может продолжаться без изменений с другой стороны. Эти две системы эффективно расцеплены (разделены) этим интерфейсом.
Системы обмена сообщениями, как правило, предусматривают участие посредника между двумя системами, которые взаимодействуют для дальнейшего расцепления (разделения) отправителя от получателя или получателей. При этом система обмена сообщениями позволяет отправителю отправить сообщение, не зная, где находится получатель, активен ли он или сколько их экземпляров.
Рассмотрим пару аналогий разновидностей проблем, которые решает система обмена сообщениями, и введем некоторые основные термины.

Point-to-Point


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

Это пример модели обмена сообщениями точка-точка. Почтовое отделение здесь действует как механизм распределения посылок, гарантируя, что каждая посылка будет доставлена один раз. Использование почтового отделения отделяет акт отправки посылки от доставки посылки.
В классических системах обмена сообщениями модель «точка-точка» реализуется через очереди. Очередь действует, как буфер FIFO (первый вошел, первый вышел), на который может подписаться один или несколько потребителей. Каждое сообщение доставляется только одному из подписанных потребителей. Очереди обычно пытаются справедливо распределять сообщения между потребителями. Только один потребитель получит данное сообщение.
К очередям применяется термин «надежные» («durable»). Надежность — это свойство сервиса, которое гарантирует, что система обмена сообщениями будет сохранять сообщения при отсутствии активных подписчиков до тех пор, пока потребитель не подпишется на очередь для доставки сообщений.
Надежность часто путают с персистентностью и, хотя эти два термина взаимозаменяемы, они выполняют разные функции. Персистентность определяет, записывает ли сообщение система обмена сообщениями в какого-либо рода хранилище между получением и отправкой его потребителю. Сообщения, отправляемые в очередь, могут быть или не быть персистентными.
Обмен сообщениями типа «Точка-точка» используется, когда вариант использования требует однократного действия с сообщением. В качестве примера можно привести внесение средств на счет или выполнение заказа на доставку. Мы обсудим позже, почему система обмена сообщениями сама по себе неспособна обеспечить однократную доставку и почему очереди могут в лучшем случае обеспечить гарантию доставки хотя бы один раз.

Издатель-Подписчик


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

Это пример модели обмена сообщениями публикация-подписка. Конференц-связь выступает, как широковещательный механизм. Говорящий человек не заботится о том, сколько людей в настоящее время присоединились к звонку — система гарантирует, что любой подключившийся в настоящий момент услышит, что говорится.
В классических системах обмена сообщениями модель обмена сообщениями «публикация-подписка» реализуется через топики. Топик предоставляет такой же способ широковещания, как и механизм конференц-связи. Когда сообщение отправляется в топик, оно распределяется по всем подписанным пользователям.
Топики обычно ненадежные (nondurable). Как и слушатель, который не слышит, что говорится на конференц-звонке, когда слушатель отключается, подписчики топика пропускают любые сообщения, которые отправляются в тот момент, когда они находятся в автономном режиме. По этой причине можно сказать, что топики предоставляют гарантию доставки не более одного раза для каждого потребителя.
Обмен сообщениями типа «публикация-подписка» обычно используется, когда сообщения носят информационный характер, и потеря одного сообщения — не особо значима. Например, топик может передавать показания температуры от группы датчиков один раз в секунду. Система, которая интересуется текущей температурой и которая подписывается на топик, не будет переживать, если она пропустит сообщение — другое поступит в ближайшее время.

Гибридные модели


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

Сценарии использования часто требуют совмещения моделей обмена сообщениями «публикация-подписка» и «точка-точка», например, когда нескольким системам требуется копия сообщения, и для предотвращения потери сообщения требуется как надежность, так и персистентность.
В этих случаях требуется адресат (destination) (общий термин для очередей и топиков), который распределяет сообщения в основном как топик, так, что каждое сообщение отправляется в отдельную систему, заинтересованную в этих сообщениях, но и также в которой каждая система может определить несколько потребителей, которые получают входящие сообщения, что больше похоже на очередь. Тип чтения в этом случае — один раз для каждой заинтересованной стороны. Эти гибридные адресаты часто требуют надежности (durability), так что, если потребитель отключается, сообщения, которые отправляются в это время, принимаются после повторного подключения потребителя.
Гибридные модели не новы и могут применяться в большинстве систем обмена сообщениями, включая как ActiveMQ (через виртуальные или составные адресаты, которые объединяют топики и очереди), так и Kafka (неявно, как фундаментальное свойство дизайна её адресата).
Теперь, когда у нас есть некоторая базовая терминология и понимание того, для чего нам могла бы пригодиться система обмена сообщениями, давайте перейдем к деталям.

Перевод выполнен: tele.gg/middle_java

Продолжение следует...

Let's block ads! (Why?)

[Из песочницы] Как два студента сделали игру под iOS и сколько заработали на этом

Ровно год назад мы с другом решили побыстрому сделать игру под iOS. Что из этого вышло и сколько нам удалось заработать я расскажу под катом.

Вообще мы C++ разработчики и уже раньше пытались сделать кросс-платформенную игру, используя известные нам инструменты — Qt и C++. Тогда мы работали над игрой в жанре Tower Defence в новогоднем сеттинге. Для погружения в атмосферу инди-разработки предлагаю посмотреть пару видео из того времени:



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

В какой-то момент мы решили изучить нативные инструменты разработки. А именно SpriteKit на iOS. Я накидал демку на Swift, в которой было 1000 движущихся спрайтов с альфа каналом. Она заняла всего пару десятков строк кода и выдавала 60 fps на iPhone 5! Это был просто восторг! Низкий порог входа и бешеные возможности встроенного движка снова разожгли в нас энтузиазм!

На этот раз мы сформулировали основную цель так: Игра должна быть в AppStore! Она просто не может отправиться ко всем остальным недоделанным проектам на задворки гитхаба! Это означало, что игра должна быть настолько простой, чтобы её нельзя было не сделать. Пора начать доделывать дела!

Мы не могли себе позволить вручную создавать уровни, так как после создания игровой механики энтузиазм мог угаснуть. Поэтому думали сделать раннер или платформер с одним бесконечным уровнем. Как Subway Surfers, Doodle Jump, Nyan Cat или Flappy Bird. Также мы хотели минимизировать количество текста, чтобы не возиться с локализацией.

Так что мы придумали? Беглое изучение инструментов разработки под iOS показало, что встроенный двумерный физический движок просто огонь! Разработка под него выглядит примерно так:


  • создать физический мир
  • добавить объект мяч в физический мир
  • добавить объект пол в физический мир
  • включить гравитацию!

Можете представить себе эмоции программиста, который до этого два месяца жонглировал указателями?

Разумеется мы решили использовать физику в качестве основного элемента игры. Какую игру с бесконечным уровнем на основе физики можно сделать с мячом? Чеканку мяча!

По задумке, игрок должен управлять ногой футболиста и чеканить (набивать) мяч. Цель игры — начеканить как можно больше. Считаются отскоки от ступни, колена и головы. При этом, обязательным фактором была монетизация. Хоть какая-нибудь! Тут дело даже не в заработке — нужно познакомиться с инструментами.

Так, цель мы сформулировали достаточно четко. Пора приступать! Мы забили на пары и ушли в отпуска с работы на неделю. За это время мы планировали сделать меню, сцену с игрой, подсчет очков и рекламу. Думаете, получилось?

Получилось! Мы реально успели сделать игру без дизайна и звуков за неделю. На инструментах, которыми. раньше никогда не пользовались (Swift + SpriteKit). Получилось нечто даже более-менее играбельное, правда с заглушками вместо нормальных текстур.


Скриншоты

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

Так, стоп! Художник? Мы что крупная корпорация? Нет, но программисты обычно рисуют не очень. Поэтому было решено отдать это дело на аутсорс. Тем более, что наша неделя на игру подошла к концу.

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

Постепенно из набросков стал вырисовываться дизайн игры.


Эскизы

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

Новые текстуры были большего разрешения и при замене в редакторе сцены Xcode постоянно вылетал! библиотеки у Apple, конечно отличные, но IDE мягко говоря могла быть и по стабильнее! Приходилось удалять 10 версию Xcode и ставить 9, чтобы хоть как-то работать с текстурами.

Кстати, на каком-то этапе обнаружился интересный баг с коленом, который мы назвали "Режим кузнечика".


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

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

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


Проверка занимает 2 суток. У нас отклонили 1 раз из-за каких-то законов Китая. Мы просто не стали там релизиться, и через двое суток наступил этот долгожданный момент! Игра в магазине! Мы шли к этому полгода! Мы довели проект до конца!

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

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


По затратам проект вышел примерно в 150 человекочасов, 2500р оплата художнику и $100 за аккаунт разработчика. Окупилось? Давайте посмотрим в дашбоард Гугл рекламы.


Да, за все время мы заработали $5.41~ 360 рублей. При затратах в 9000 рублей. Итого, доходность мероприятия: -96%. Да, заголовок немножко кликбейтный, простите)

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

А что по поводу того, что заработали мы всего $5? Я вам скажу: Зато не на дядю!

P.S. Обязательно доделывайте дела. Если не получается — упрощайте, но доделывайте. Это очень полезное умение.

Удачи в ваших проектах!

Let's block ads! (Why?)

Python + OpenCV + Keras: делаем распознавалку текста за полчаса

Привет Хабр.

После экспериментов с многим известной базой из 60000 рукописных цифр MNIST возник логичный вопрос, есть ли что-то похожее, но с поддержкой не только цифр, но и букв. Как оказалось, есть, и называется такая база, как можно догадаться, Extended MNIST (EMNIST).

Если кому интересно, как с помощью этой базы можно сделать несложную распознавалку текста, добро пожаловать под кат.


Примечание: данный пример экспериментальный и учебный, мне было просто интересно посмотреть, что из этого получится. Делать второй FineReader я не планировал и не планирую, так что многие вещи тут, разумеется, не реализованы. Поэтому претензии в стиле «зачем», «уже есть лучше» и пр, не принимаются. Наверно готовые OCR-библиотеки для Python уже есть, но было интересно сделать самому. Кстати, для тех кто хочет посмотреть, как делался настоящий FineReader, есть две статьи в их блоге на Хабре за 2014 год: 1 и 2. Ну а мы приступим.

Для примера мы возьмем простой текст. Вот такой:

HELLO WORLD


И посмотрим что с ним можно сделать.

Разбиение текста на буквы


Первым шагом разобьем текст на отдельные буквы. Для этого пригодится OpenCV, точнее его функция findContours.

Откроем изображение (cv2.imread), переведем его в ч/б (cv2.cvtColor + cv2.threshold), слегка увеличим (cv2.erode) и найдем контуры.

image_file = "text.png"
img = cv2.imread(image_file)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)
img_erode = cv2.erode(thresh, np.ones((3, 3), np.uint8), iterations=1)

# Get contours
contours, hierarchy = cv2.findContours(img_erode, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

output = img.copy()

for idx, contour in enumerate(contours):
    (x, y, w, h) = cv2.boundingRect(contour)
    # print("R", idx, x, y, w, h, cv2.contourArea(contour), hierarchy[0][idx])
    # hierarchy[i][0]: the index of the next contour of the same level
    # hierarchy[i][1]: the index of the previous contour of the same level
    # hierarchy[i][2]: the index of the first child
    # hierarchy[i][3]: the index of the parent
    if hierarchy[0][idx][3] == 0:
        cv2.rectangle(output, (x, y), (x + w, y + h), (70, 0, 0), 1)


cv2.imshow("Input", img)
cv2.imshow("Enlarged", img_erode)
cv2.imshow("Output", output)
cv2.waitKey(0)


Мы получаем иерархическое дерево контуров (параметр cv2.RETR_TREE). Первым идет общий контур картинки, затем контуры букв, затем внутренние контуры. Нам нужны только контуры букв, поэтому я проверяю что «родительским» является общий контур. Это упрощенный подход, и для реальных сканов это может не сработать, хотя для распознавания скриншотов это некритично.

Результат:

Следующим шагом сохраним каждую букву, предварительно отмасштабировав её до квадрата 28х28 (именно в таком формате хранится база MNIST). OpenCV построен на базе numpy, так что мы можем использовать функции работы с массивами для кропа и масштабирования.

def letters_extract(image_file: str, out_size=28) -> List[Any]:
    img = cv2.imread(image_file)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)
    img_erode = cv2.erode(thresh, np.ones((3, 3), np.uint8), iterations=1)

    # Get contours
    contours, hierarchy = cv2.findContours(img_erode, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

    output = img.copy()

    letters = []
    for idx, contour in enumerate(contours):
        (x, y, w, h) = cv2.boundingRect(contour)
        # print("R", idx, x, y, w, h, cv2.contourArea(contour), hierarchy[0][idx])
        # hierarchy[i][0]: the index of the next contour of the same level
        # hierarchy[i][1]: the index of the previous contour of the same level
        # hierarchy[i][2]: the index of the first child
        # hierarchy[i][3]: the index of the parent
        if hierarchy[0][idx][3] == 0:
            cv2.rectangle(output, (x, y), (x + w, y + h), (70, 0, 0), 1)
            letter_crop = gray[y:y + h, x:x + w]
            # print(letter_crop.shape)

            # Resize letter canvas to square
            size_max = max(w, h)
            letter_square = 255 * np.ones(shape=[size_max, size_max], dtype=np.uint8)
            if w > h:
                # Enlarge image top-bottom
                # ------
                # ======
                # ------
                y_pos = size_max//2 - h//2
                letter_square[y_pos:y_pos + h, 0:w] = letter_crop
            elif w < h:
                # Enlarge image left-right
                # --||--
                x_pos = size_max//2 - w//2
                letter_square[0:h, x_pos:x_pos + w] = letter_crop
            else:
                letter_square = letter_crop

            # Resize letter to 28x28 and add letter and its X-coordinate
            letters.append((x, w, cv2.resize(letter_square, (out_size, out_size), interpolation=cv2.INTER_AREA)))

    # Sort array in place by X-coordinate
    letters.sort(key=lambda x: x[0], reverse=False)

    return letters


В конце мы сортируем буквы по Х-координате, также как можно видеть, мы сохраняем результаты в виде tuple (x, w, letter), чтобы из промежутков между буквами потом выделить пробелы.

Убеждаемся что все работает:

cv2.imshow("0", letters[0][2])
cv2.imshow("1", letters[1][2])
cv2.imshow("2", letters[2][2])
cv2.imshow("3", letters[3][2])
cv2.imshow("4", letters[4][2])
cv2.waitKey(0)

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

Нейронная сеть (CNN) для распознавания


Исходный датасет EMNIST имеет 62 разных символа (A..Z, 0..9 и пр):
emnist_labels = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122]

Нейронная сеть соответственно, имеет 62 выхода, на входе она будет получать изображения 28х28, после распознавания «1» будет на соответствующем выходе сети.

Создаем модель сети.

from tensorflow import keras
from keras.models import Sequential
from keras import optimizers
from keras.layers import Convolution2D, MaxPooling2D, Dropout, Flatten, Dense, Reshape, LSTM, BatchNormalization
from keras.optimizers import SGD, RMSprop, Adam
from keras import backend as K
from keras.constraints import maxnorm
import tensorflow as tf

def emnist_model():
    model = Sequential()
    model.add(Convolution2D(filters=32, kernel_size=(3, 3), padding='valid', input_shape=(28, 28, 1), activation='relu'))
    model.add(Convolution2D(filters=64, kernel_size=(3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    model.add(Flatten())
    model.add(Dense(512, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(len(emnist_labels), activation='softmax'))
    model.compile(loss='categorical_crossentropy', optimizer='adadelta', metrics=['accuracy'])
    return model

Как можно видеть, это классическая сверточная сеть, выделяющая определенные признаки изображения (количество фильтров 32 и 64), к «выходу» которой подсоединена «линейная» сеть MLP, формирующая окончательный результат.

Обучение нейронной сети


Переходим к самому продолжительному этапу — обучению сети. Для этого мы возьмем базу EMNIST, скачать которую можно по ссылке (размер архива 536Мб).

Для чтения базы воспользуемся библиотекой idx2numpy. Подготовим данные для обучения и валидации.

import idx2numpy

emnist_path = '/home/Documents/TestApps/keras/emnist/'
X_train = idx2numpy.convert_from_file(emnist_path + 'emnist-byclass-train-images-idx3-ubyte')
y_train = idx2numpy.convert_from_file(emnist_path + 'emnist-byclass-train-labels-idx1-ubyte')

X_test = idx2numpy.convert_from_file(emnist_path + 'emnist-byclass-test-images-idx3-ubyte')
y_test = idx2numpy.convert_from_file(emnist_path + 'emnist-byclass-test-labels-idx1-ubyte')

X_train = np.reshape(X_train, (X_train.shape[0], 28, 28, 1))
X_test = np.reshape(X_test, (X_test.shape[0], 28, 28, 1))

print(X_train.shape, y_train.shape, X_test.shape, y_test.shape, len(emnist_labels))

k = 10
X_train = X_train[:X_train.shape[0] // k]
y_train = y_train[:y_train.shape[0] // k]
X_test = X_test[:X_test.shape[0] // k]
y_test = y_test[:y_test.shape[0] // k]

# Normalize
X_train = X_train.astype(np.float32)
X_train /= 255.0
X_test = X_test.astype(np.float32)
X_test /= 255.0

x_train_cat = keras.utils.to_categorical(y_train, len(emnist_labels))
y_test_cat = keras.utils.to_categorical(y_test, len(emnist_labels))


Мы подготовили два набора, для обучения и валидации. Сами символы представляют собой обычные массивы, которые несложно вывести на экран:

Также мы используем лишь 1/10 датасета для обучения (параметр k), в противном случае процесс займет не менее 10 часов.

Запускаем обучение сети, в конце процесса сохраняем обученную модель на диск.

# Set a learning rate reduction
learning_rate_reduction = keras.callbacks.ReduceLROnPlateau(monitor='val_acc', patience=3, verbose=1, factor=0.5, min_lr=0.00001)

# Required for learning_rate_reduction:
keras.backend.get_session().run(tf.global_variables_initializer())

model.fit(X_train, x_train_cat, validation_data=(X_test, y_test_cat), callbacks=[learning_rate_reduction], batch_size=64, epochs=30)

model.save('emnist_letters.h5')

Сам процесс обучения занимает около получаса:

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

Распознавание


Для распознавания мы загружаем модель и вызываем функцию predict_classes.
model = keras.models.load_model('emnist_letters.h5')

def emnist_predict_img(model, img):
    img_arr = np.expand_dims(img, axis=0)
    img_arr = 1 - img_arr/255.0
    img_arr[0] = np.rot90(img_arr[0], 3)
    img_arr[0] = np.fliplr(img_arr[0])
    img_arr = img_arr.reshape((1, 28, 28, 1))

    result = model.predict_classes([img_arr])
    return chr(emnist_labels[result[0]])

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

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

def img_to_str(model: Any, image_file: str):
    letters = letters_extract(image_file)
    s_out = ""
    for i in range(len(letters)):
        dn = letters[i+1][0] - letters[i][0] - letters[i][1] if i < len(letters) - 1 else 0
        s_out += emnist_predict_img(model, letters[i][2])
        if (dn > letters[i][1]/4):
            s_out += ' '
    return s_out

Здесь мы используем сохраненную ранее ширину символа, чтобы добавлять пробелы, если промежуток между буквами более 1/4 символа.

Пример использования:

model = keras.models.load_model('emnist_letters.h5')
s_out = img_to_str(model, "hello_world.png")
print(s_out)


Результат:

Забавная особенность — нейронная сеть «перепутала» букву «О» и цифру «0», что впрочем, неудивительно т.к. исходный набор EMNIST содержит рукописные буквы и цифры, которые не совсем похожи на печатные. В идеале, для распознавания экранных текстов нужно подготовить отдельный набор на базе экранных шрифтов, и уже на нем обучать нейросеть.

Заключение


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

Для желающих поэкспериментировать самостоятельно, исходный код под спойлером.

keras_emnist.py
# Code source: dmitryelj@gmail.com

import os
# Force CPU
# os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
# Debug messages
# 0 = all messages are logged (default behavior)
# 1 = INFO messages are not printed
# 2 = INFO and WARNING messages are not printed
# 3 = INFO, WARNING, and ERROR messages are not printed
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'


import cv2
import imghdr
import numpy as np
import pathlib
from tensorflow import keras
from keras.models import Sequential
from keras import optimizers
from keras.layers import Convolution2D, MaxPooling2D, Dropout, Flatten, Dense, Reshape, LSTM, BatchNormalization
from keras.optimizers import SGD, RMSprop, Adam
from keras import backend as K
from keras.constraints import maxnorm
import tensorflow as tf
from scipy import io as spio
import idx2numpy  # sudo pip3 install idx2numpy
from matplotlib import pyplot as plt
from typing import *
import time


# Dataset:
# https://www.nist.gov/node/1298471/emnist-dataset
# https://www.itl.nist.gov/iaui/vip/cs_links/EMNIST/gzip.zip


def cnn_print_digit(d):
    print(d.shape)
    for x in range(28):
        s = ""
        for y in range(28):
            s += "{0:.1f} ".format(d[28*y + x])
        print(s)


def cnn_print_digit_2d(d):
    print(d.shape)
    for y in range(d.shape[0]):
        s = ""
        for x in range(d.shape[1]):
            s += "{0:.1f} ".format(d[x][y])
        print(s)


emnist_labels = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122]


def emnist_model():
    model = Sequential()
    model.add(Convolution2D(filters=32, kernel_size=(3, 3), padding='valid', input_shape=(28, 28, 1), activation='relu'))
    model.add(Convolution2D(filters=64, kernel_size=(3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    model.add(Flatten())
    model.add(Dense(512, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(len(emnist_labels), activation='softmax'))
    model.compile(loss='categorical_crossentropy', optimizer='adadelta', metrics=['accuracy'])
    return model

def emnist_model2():
    model = Sequential()
    # In Keras there are two options for padding: same or valid. Same means we pad with the number on the edge and valid means no padding.
    model.add(Convolution2D(filters=32, kernel_size=(3, 3), activation='relu', padding='same', input_shape=(28, 28, 1)))
    model.add(MaxPooling2D((2, 2)))
    model.add(Convolution2D(64, (3, 3), activation='relu', padding='same'))
    model.add(MaxPooling2D((2, 2)))
    model.add(Convolution2D(128, (3, 3), activation='relu', padding='same'))
    model.add(MaxPooling2D((2, 2)))
    # model.add(Conv2D(128, (3, 3), activation='relu', padding='same'))
    # model.add(MaxPooling2D((2, 2)))
    ## model.add(Dropout(0.25))
    model.add(Flatten())
    model.add(Dense(512, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(len(emnist_labels), activation='softmax'))
    model.compile(loss='categorical_crossentropy', optimizer='adadelta', metrics=['accuracy'])
    return model

def emnist_model3():
    model = Sequential()
    model.add(Convolution2D(filters=32, kernel_size=(3, 3), padding='same', input_shape=(28, 28, 1), activation='relu'))
    model.add(Convolution2D(filters=32, kernel_size=(3, 3), padding='same', activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))

    model.add(Convolution2D(filters=64, kernel_size=(3, 3), padding='same', activation='relu'))
    model.add(Convolution2D(filters=64, kernel_size=(3, 3), padding='same', activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
    model.add(Dropout(0.25))

    model.add(Flatten())
    model.add(Dense(512, activation="relu"))
    model.add(Dropout(0.5))
    model.add(Dense(len(emnist_labels), activation="softmax"))
    model.compile(loss='categorical_crossentropy', optimizer=RMSprop(lr=0.001, rho=0.9, epsilon=1e-08, decay=0.0), metrics=['accuracy'])
    return model


def emnist_train(model):
    t_start = time.time()

    emnist_path = 'D:\\Temp\\1\\'
    X_train = idx2numpy.convert_from_file(emnist_path + 'emnist-byclass-train-images-idx3-ubyte')
    y_train = idx2numpy.convert_from_file(emnist_path + 'emnist-byclass-train-labels-idx1-ubyte')

    X_test = idx2numpy.convert_from_file(emnist_path + 'emnist-byclass-test-images-idx3-ubyte')
    y_test = idx2numpy.convert_from_file(emnist_path + 'emnist-byclass-test-labels-idx1-ubyte')

    X_train = np.reshape(X_train, (X_train.shape[0], 28, 28, 1))
    X_test = np.reshape(X_test, (X_test.shape[0], 28, 28, 1))

    print(X_train.shape, y_train.shape, X_test.shape, y_test.shape, len(emnist_labels))

    # Test:
    k = 10
    X_train = X_train[:X_train.shape[0] // k]
    y_train = y_train[:y_train.shape[0] // k]
    X_test = X_test[:X_test.shape[0] // k]
    y_test = y_test[:y_test.shape[0] // k]

    # Normalize
    X_train = X_train.astype(np.float32)
    X_train /= 255.0
    X_test = X_test.astype(np.float32)
    X_test /= 255.0

    x_train_cat = keras.utils.to_categorical(y_train, len(emnist_labels))
    y_test_cat = keras.utils.to_categorical(y_test, len(emnist_labels))

    # Set a learning rate reduction
    learning_rate_reduction = keras.callbacks.ReduceLROnPlateau(monitor='val_acc', patience=3, verbose=1, factor=0.5, min_lr=0.00001)

    # Required for learning_rate_reduction:
    keras.backend.get_session().run(tf.global_variables_initializer())

    model.fit(X_train, x_train_cat, validation_data=(X_test, y_test_cat), callbacks=[learning_rate_reduction], batch_size=64, epochs=30)
    print("Training done, dT:", time.time() - t_start)


def emnist_predict(model, image_file):
    img = keras.preprocessing.image.load_img(image_file, target_size=(28, 28), color_mode='grayscale')
    emnist_predict_img(model, img)


def emnist_predict_img(model, img):
    img_arr = np.expand_dims(img, axis=0)
    img_arr = 1 - img_arr/255.0
    img_arr[0] = np.rot90(img_arr[0], 3)
    img_arr[0] = np.fliplr(img_arr[0])
    img_arr = img_arr.reshape((1, 28, 28, 1))

    result = model.predict_classes([img_arr])
    return chr(emnist_labels[result[0]])


def letters_extract(image_file: str, out_size=28):
    img = cv2.imread(image_file)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)
    img_erode = cv2.erode(thresh, np.ones((3, 3), np.uint8), iterations=1)

    # Get contours
    contours, hierarchy = cv2.findContours(img_erode, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

    # hierarchy[i][0]: the index of the next contour of the same level
    # hierarchy[i][1]: the index of the previous contour of the same level
    # hierarchy[i][2]: the index of the first child
    # hierarchy[i][3]: the index of the parent

    output = img.copy()

    letters = []
    for idx, contour in enumerate(contours):
        # contour, hier = component[0], component[1]
        (x, y, w, h) = cv2.boundingRect(contour)
        # print("R", idx, x, y, w, h, cv2.contourArea(contour), hierarchy[0][idx])
        if hierarchy[0][idx][3] == 0:
            cv2.rectangle(output, (x, y), (x + w, y + h), (70, 0, 0), 1)
            letter_crop = gray[y:y + h, x:x + w]
            # print(letter_crop.shape)

            # Resize letter canvas to square
            size_max = max(w, h)
            letter_square = 255 * np.ones(shape=[size_max, size_max], dtype=np.uint8)
            if w > h:
                # Enlarge image top-bottom
                # ------
                # ======
                # ------
                y_pos = size_max//2 - h//2
                letter_square[y_pos:y_pos + h, 0:w] = letter_crop
            elif w < h:
                # Enlarge image left-right
                # --||--
                x_pos = size_max//2 - w//2
                letter_square[0:h, x_pos:x_pos + w] = letter_crop
            else:
                letter_square = letter_crop

            # Resize letter to 28x28 and add letter and its X-coordinate
            letters.append((x, w, cv2.resize(letter_square, (out_size, out_size), interpolation=cv2.INTER_AREA)))

    # Sort array in place by X-coordinate
    letters.sort(key=lambda x: x[0], reverse=False)

    # cv2.imshow("Input", img)
    # # cv2.imshow("Gray", thresh)
    # cv2.imshow("Enlarged", img_erode)
    # cv2.imshow("Output", output)
    # cv2.imshow("0", letters[0][2])
    # cv2.imshow("1", letters[1][2])
    # cv2.imshow("2", letters[2][2])
    # cv2.imshow("3", letters[3][2])
    # cv2.imshow("4", letters[4][2])
    # cv2.waitKey(0)
    return letters


def img_to_str(model: Any, image_file: str):
    letters = letters_extract(image_file)
    s_out = ""
    for i in range(len(letters)):
        dn = letters[i+1][0] - letters[i][0] - letters[i][1] if i < len(letters) - 1 else 0
        s_out += emnist_predict_img(model, letters[i][2])
        if (dn > letters[i][1]/4):
            s_out += ' '
    return s_out


if __name__ == "__main__":

    # model = emnist_model()
    # emnist_train(model)
    # model.save('emnist_letters.h5')

    model = keras.models.load_model('emnist_letters.h5')
    s_out = img_to_str(model, "hello_world.png")
    print(s_out)



Как обычно, всем удачных экспериментов.

Let's block ads! (Why?)

IPO на Московской бирже: зачем это нужно, кто проводит и как купить акции

Изображение: Unsplash

В сети можно часто встретить истории о том, как компании вышли на биржу и провели IPO, по итогам которых основатели бизнеса стали миллиардерами. Почти всегда в этих рассказах фигурируют зарубежные биржи, в основном из США, однако провести IPO (а затем и SPO) можно и в России. Сегодня мы поговорим о том, как и зачем компании размещают свои акции на Московской бирже.

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

Что такое IPO


Если компания достигает этапа развития, на котором для дальнейшего роста ей необходим внешний капитал, то одним из способов его привлечения является размещение акций на бирже через механизм IPO (initial public offering). В таком случае компания становится публичной — купить акции сможет любой желающий.

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

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

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

Не только IPO: вторичные размещения


На бирже проводятся не только первичные размещения акций. Существует также понятие SPO (Secondary Public Offering), при котором проводится публичное размещение акций, принадлежащих уже существующим акционерам. Такой шаг позволяет увеличить количество акций в свободном обращении (free-float), не выпуская дополнительных акций и не обесценивая их. Таким образом повышается ликвидность акций компании и стимулируется интерес инвесторов к ним.

Зачем проводят IPO/SPO в России


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

Если же компания считает, что и на родине сможет получить достаточный объем инвестиций и каких-то особенных интересов за границей не имеет, то процесс подготовки IPO/SPO на родине может быть вполне оправданным. Одна из главных причин — стоимость всего процесса.

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

Как готовится IPO


Процесс подготовки к IPO — непростое дело, которое занимает от нескольких месяцев до года и стоит компании серьезных средств. Организовать процесс самостоятельно бизнесу довольно трудно, поэтому возникает необходимость в найме инвестиционной компании (или нескольких), которые будут заниматься подгтовкой. Такие инвесткомпании называются андеррайтерами IPO.

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

По итогам переговоров подписывается соглашение. После этого андеррайтер передает инвестиционный меморандум в регулирующий орган страны, на биржевой площадке которой будет осуществляться размещение акций. В США это комиссия по ценным бумагам (SEC), а в нашей стране — Банк России.

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

Примеры успешных размещений акций и облигаций


На Московской бирже регулярно проходят IPO и SPO в ходе которых компании предлагают инвесторам свои акции и облигации, вот несколько успешных примеров таких размещений:
  • Еще в 2014 году дополнительное размещение своих акций на Московской бирже провел «Яндекс».
  • В феврале 2017 года на Московской бирже состоялось IPO «Детского мира» — компания предложила инвесторам акций на 21,1 млрд руб
  • В том же году свои облигации на 2,7 млрд рублей разместила компания Softline (АО «Софтлайн Трейд») — IPO прошло при участии экспертов ITI Capital.
  • В 2016 году акций на 32,4 млрд руб. ($501,33 млн) разместила в ходе IPO компания ПАО НК «Русснефть», в этом случае сопровождением процесса размещение также занималась ITI Capital.

Это далеко не все примеры – деловые СМИ регулярно составляют подборки наиболее успешных российских IPO. Мы в ITI Capital помогаем компаниям организовывать IPO/SPO на российском фондовом рынке.

Не все так просто


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

Кроме того, регулирующие органы (в США – SEC, в нашей стране – Банк России) проводят аудиты и пристально следят за деятельностью публичных компаний. Затраты на соответствие таким требованиям могут быть весьма значительными.

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

Однако, несмотря на некоторые сложности, IPO (а затем и SPO) на Московской бирже – эффективный способ привлечения капитала, а значит и возможность для развития бизнеса.

Полезные ссылки по теме инвестиций и биржевой торговли:


Let's block ads! (Why?)

KOST: что входит в новый стек технологий для разработки облачных приложений

Рассказываем о его компонентах и перспективах.


/ фото Gozha Net Unsplash

Почему появился новый стек


Существует множество стеков для разработки программного обеспечения. Один из наиболее известных — LAMP (Linux, Apache HTTP server, MySQL, PHP). На нем построен сайт «Википедии» и несколько других проектов фонда Wikimedia Foundation. LAMP даже использовали в Facebook для решения ряда задач.

Но есть мнение, что LAMP, хотя и является зарекомендовавшим себя стеком, плохо подходит для построения крупных масштабируемых приложений. Поэтому сегодня, когда компании переносят рабочие нагрузки в облако, все чаще используются альтернативные наборы технологий.
Одним из популярных стеков для облака считается MEAN — MongoDB, Express.js, Angular и Node.js. Он «привязан» к JavaScript, а на этом языке можно писать как серверную, так и клиентскую часть. Этот стек применяют в Paypal, Netflix и The New York Times. Также популярными наборами технологий считаются MERN и MEVN, в которых Angular заменяют на React или Vue.js соответственно. Сегодня они используются в разработке мобильных приложений.

Недавно начал набирать обороты альтернативный стек — KOST. В него вошли Kubernetes, Operator, Spark и TiDB. Его цель — оптимизировать обработку данных в частном, публичном и гибридном облаках.

Компоненты


Kubernetes. Пожалуй, один из самых известных инструментов для управления контейнерными приложениями. Он стал частью KOST потому, что является своеобразным стандартом в ИТ-индустрии. Его поддерживают участники облачного фонда Cloud Native Computing Foundation (CNCF). Кто-то даже называет Kubernetes «операционной системой для облака». Многие крупные IaaS-провайдеры и разработчики инструментов виртуализации уже предлагают свои решения на базе Kubernetes — например, OpenShift, VMware PKS или Rancher.

Operator. Открытый набор инструментов для управления «операторами» — приложениями на базе Kubernetes. Эти приложения помогают реализовать дополнительную бизнес-логику, например, для работы с third-party ресурсами. Operator выпустили в 2016 году инженеры из CoreOS — сегодня за него отвечает Red Hat. Сам инструмент, как и Kubernetes, постепенно становится стандартом для разработки облачных приложений. Например, его уже внедрили несколько разработчиков СУБД. И число пользователей стабильно увеличивается.

Spark. Другой известный фреймворк с открытым исходным кодом для работы с неструктурированными данными. Spark использует специализированные примитивы для рекуррентной обработки в оперативной памяти. Такой подход позволяет увеличить производительность системы на некоторых задачах (стр.1). Инструмент нашел место в стеке KOST, поскольку активно используется для развертки масштабной облачной инфраструктуры, например в Netflix, Oracle, Visa и eBay.


/ фото Stephanie McCabe Unsplash

TiDB. Это — распределённая СУБД, которая совмещает транзакционную и аналитическую обработку данных (Hybrid Transactional/Analytical Processing, HTAP). Она горизонтально масштабируется, обладает высокой доступностью и следует принципам ACID: атомарность, согласованность, изолированность и долговечность. Система изначально создавалась с прицелом на работу в облаке, чтобы упростить развертку и поддержку приложений. Это одна из главных причин, по которой её выбрали в качестве «замыкающего звена» стека KOST.

TiDB — не самая распространенная СУБД на рынке (учитывая, что она появилась лишь два года назад), но у неё есть потенциал. С ней уже работают такие гиганты, как Xiaomi и крупнейшая площадка для бронирования билетов в Индии BookMyShow. Хотя есть мнение, что TiDB выбрали просто для того, чтобы сформировать красивую аббревиатуру — KOST. При желании инструмент можно заменить на Cockroach, Clickhouse и другие решения.

Перспективы


Все решения в «составе» KOST с открытым исходным кодом. Поэтому стеком могут воспользоваться компании любых размеров и с любыми бюджетами. Ожидается, что наибольшую выгоду KOST принесет ретейлерам и онлайн-магазинам. Эксперты говорят, что новые технологии упростят складской учет за счет гибкой и масштабируемой базы данных и обезопасят персональные данные клиентов (благодаря контейнерным технологиям).

Стек LAMP проложил дорогу веб-приложениям, а MEAN, MERN и MEVN — мобильным приложениям. Ожидается, что KOST или его модификации откроют новые возможности для разработчиков, использующих облака в своих проектах.



Дополнительное чтение по теме из нашего Telegram-канала:
О чем мы пишем в Первом блоге о корпоративном IaaS:

Let's block ads! (Why?)

[Перевод] Тренинг Cisco 200-125 CCNA v3.0. День 35. Динамический протокол транкинга DTP

Сегодня мы рассмотрим динамический протокол транкинга DTP и VTP – протокол транкинга VLAN. Как я говорил на последнем уроке, мы будем следовать темам экзамена ICND2 в том порядке, в котором они приведены на сайте Cisco.

В прошлый раз мы рассмотрели пункт 1.1, а сегодня рассмотрим 1.2 – настройка, проверка и неполадки соединений сетевых коммутаторов: добавление и удаление VLAN из транка и протоколы DTP и VTP версии 1 и 2.

Все порты свитча «из коробки» по умолчанию настроены на использование режима Dynamic Auto протокола DTP. Это означает, что при соединении двух портов разных свитчей между ними автоматически включается транк, если один из портов находится в режиме trunk или desirable. Если порты обоих свитчей находятся в режиме Dynamic Auto, транк не образуется.

Таким образом, все зависит от настройки режимов работы каждого из 2 свитчей. Для удобства понимания я сделал таблицу возможных комбинаций режимов DTP двух свитчей. Вы видите, что если оба свитча используют Dynamic Auto, то они не образуют транк, а останутся в режиме Access. Поэтому если вы хотите, чтобы между двумя свитчами был создан транк, то должны запрограммировать хотя бы один из свитчей на режим Trunk, или же запрограммировать транк-порт на использование режима Dynamic Desirable. Как видно из таблицы, каждый из портов свитча может находиться в одном из 4-х режимов: Access, Dynamic Auto, Dynamic Desirable или Trunk.
Если оба порта настроены на Access, соединенные свитчи будут использовать режим Access. Если один порт настроен на Dynamic Auto, а другой на Access, оба будут работать в режиме Access. Если один порт работает в режиме Access, а другой в режиме Trunk, соединить свитчи не получится, поэтому такую комбинацию режимов нельзя использовать.

Итак, для работы транкинга необходимо, чтобы один из портов свитчей был запрограммирован на Trunk, а другой – на Trunk, Dynamic Auto или Dynamic Desirable. Транк образуется также в случае, если оба порта настроены на Dynamic Desirable.

Разница между Dynamic Desirable и Dynamic Auto заключается в том, что в первом режиме порт сам инициирует транк, отсылая DTP-фреймы порту второго свитча. Во втором режиме порт свитча ждет, пока кто-либо не начнем с ним общаться, и если порты обоих свитчей настроены на Dynamic Auto, между ними никогда не образуется транк. В случае Dynamic Desirable имеется обратная ситуация – если оба порта настроены на этот режим, между ними обязательно образуется транк.
Я советую вам запомнить эту таблицу, так как она поможет вам правильно настроить свитчи, соединенные друг с другом. Давайте рассмотрим этот аспект в программе Packet Tracer. Я последовательно соединил вместе 3 свитча и сейчас отображу на экране окна консолей CLI для каждого из этих устройств.

Если я введу команду show int trunk, мы не увидим никакого транка, что совершенно естественно при отсутствии необходимых настроек, так как все свитчи настроены на режим Dynamic Auto. Если я попрошу показать параметры интерфейса f0/1 среднего свитча, вы увидите, что в режиме административных настроек значится параметр dynamic auto.

Аналогичные настройки имеются у третьего и первого свитчей – у них также порт f0/1 находится в режиме dynamic auto. Если вы помните таблицу, для транкинга все порты должны находиться в режиме trunk либо один из портов должен быть в режиме Dynamic Desirable.

Давайте зайдем в настройки первого свитча SW0 и настроим порт f0/1. После ввода команды switchport mode система выдаст подсказки возможных параметров режима: access, dynamic или trunk. Я использую команду switchport mode dynamic desirable, при этом вы можете заметить, как транк-порт f0/1 второго свитча после ввода этой команды сначала перешел в состояние down, а затем, после получения фрейма DTP первого свитча перешел в состояние up.

Если теперь в консоли CLI свитча SW1 ввести команду show int trunk, мы увидим, что порт f0/1 находится в состоянии транкинга. Я ввожу ту же команду в консоли свитча SW1 и вижу ту же информацию, то есть теперь между свитчами SW0 и SW1 установлен транк. При этом порт первого свитча находится в режиме desirable, а порт второго – в режиме auto.

Между вторым и третьим свитчем связь отсутствует, поэтому я перехожу в настройки третьего свитча и ввожу команду switchport mode dynamic desirable. Вы видите, что во втором свитче произошли те же смены состояния down-up, только теперь они касаются порта f0/2, к которому подсоединен 3 свитч. Теперь второй свитч имеет два транка: один на интерфейсе f0/1, второй на f0/2. Это можно увидеть, если использовать команду show int trunk.

Оба порта второго свитча находятся в состоянии auto, то есть для транкинга с соседними свитчами необходимо, чтобы их порты были в режиме trunk или desirable, потому что в этом случае существует всего 2 режима для установки транка. С помощью таблицы вы всегда можете настроить порты свитчей таким образом, чтобы организовать между ними транк. Вот в чем заключается суть использования динамического протокола транкинга DTP.

Давайте приступим к рассмотрению протокола транкинга VLAN, или VTP. Этот протокол обеспечивает синхронизацию баз данных VLAN разных сетевых устройств, осуществляя перенос обновленной базы VLAN с одного устройства на другое. Вернемся к нашей схеме из 3-х свитчей. VTP может работать в 3-х режимах: server, client и transparent. VTP v3 имеет ещё один режим под названием Off, однако в тематике экзамена Cisco рассматривается только VTP первой и второй версий.

Режим Server используется для создания новых VLAN, удаления или изменения сетей через командную строку свитча. В режиме клиента никаких операций над VLAN совершить нельзя, в этом режиме происходит только обновление базы данных VLAN с сервера. Режим transparent действует так, как будто бы протокол VTP отключен, то есть свитч не выдает собственных сообщений VTP, но передает обновления от других свитчей – если обновление поступило на один из портов свитча, он пропускает его через себя и отправляет дальше по сети через другой порт. В прозрачном режиме свитч просто служит передатчиком чужих сообщений, не обновляя собственную базу данных VLAN.
На этом слайде вы видите команды настроек протокола VTP, вводимые в режиме глобальной конфигурации. Первой командой можно изменить используемую версию протокола. Вторая команда выбирает режим работы VTP.

Если вы хотите создать VTP-домен, используется команда vtp domain <имя домена>, а для установки пароля VTP нужно ввести команду vtp password <ПАРОЛЬ>. Перейдем к консоли CLI первого свитча и посмотрим на состояние VTP, введя команду show vtp status.

Вы видите версию протокола VTP – вторая, максимальное число поддерживаемых VLAN — 255, количество существующих VLAN – 5 и режим работы VLAN – сервер. Всё это параметры по умолчанию. Мы уже обсуждали VTP на уроке «День 30», так что если вы что-то забыли, можете вернуться и пересмотреть это видео ещё раз.

Для того, чтобы увидеть базу данных VLAN, я ввожу команду show vlan brief. Здесь показаны VLAN1 и VLAN1002-1005. К первой сети по умолчанию подключены все свободные интерфейсы свитча – 23 порта Fast Ethernet и 2 порта Gigabit Ethernet, остальные 4 VLAN не поддерживаются. Базы данных VLAN двух других свитчей выглядят точно так же, за исключением того, что у SW1 свободными для VLAN остались не 23, а 22 порта Fast Ethernet, так как f0/1 и f0/2 заняты под транки. Еще раз напомню то, о чем говорилось на уроке «День 30» — протокол VTP поддерживает только обновление баз данных VLAN.

Если я настрою несколько портов на работу с сетями VLAN с командами switchport access и switchport mode access VLAN10, VLAN20 или VLAN30, конфигурация этих портов не будет реплицирована с помощью VTP, потому что VTP обновляет только базу данных VLAN.
Так, если один из портов SW1 будет настроен на работу с VLAN20, но этой сети не будет в базе данных VLAN, то порт будет отключен. В свою очередь, обновление баз данных происходит только при использовании протокола VTP.

C помощью команды show vtp status я вижу, что все 3 свитча сейчас находятся в режиме server. Я переведу средний свитч SW1 в прозрачный режим командой vtp mode transparent, а третий свитч SW2 – в режим клиента командой vtp mode client.

Теперь вернемся к первому свитчу SW0 и создадим домен nwking.org с помощью команды vtp domain <имя домена>. Если теперь посмотреть на состояние VTP второго свитча, который находится в прозрачном режиме, видно, что он никак не отреагировал на создание домена – поле VTP Domain Name осталось пустым. Однако третий свитч, находящийся в режиме клиента, обновил свою базу данных и у него появилось доменное имя VTP- nwking.org. Таким образом, обновление базы данных свитча SW0 прошло сквозь SW1 и отразилось на SW2.

Теперь я попробую поменять заданное доменное имя, для чего зайду в настройки SW0 и наберу команду vtp domain NetworKing. Как видим, на этот раз обновления не произошло – имя домена VTP на третьем свитче осталось прежним. Дело в том, что такое обновление доменного имени происходит всего 1 раз, когда меняется домен по умолчанию. Если после этого доменное имя VTP меняется ещё раз, на остальных свитчах его потребуется поменять вручную.

Сейчас я создам в консоли CLI первого свитча новую сеть VLAN100 и назову её именем IMRAN. Она появилась в базе данных VLAN первого свитча, но не появилась в базе данных третьего свитча, потому что это разные домены. Запомните, что обновление базы данных VLAN происходит только в том случае, если оба свитча имеют одинаковый домен, либо, как я показал ранее, новое доменное имя устанавливается вместо имени по умолчанию.

Я захожу в настройки 3 свитча и последовательно ввожу команды vtp mode и vtp domain NetworKing. Обратите внимание, что ввод имени чувствителен к регистру, поэтому написание имени домена должно полностью совпадать для обоих свитчей. Сейчас я снова перевожу SW2 в режим клиента с помощью команды vtp mode client. Давайте глянем, что произойдёт. Как видите, теперь, при совпадении имени домена, база данных SW2 обновилась и в ней появилась новая сеть VLAN100 IMRAN, причем эти изменения никак не отразились на среднем свитче, потому что он находится в режиме transparent.

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

Следующее, что мы рассмотрим – это VTP pruning, или «обрезка» неиспользуемых VLAN. Если у вас в сети имеется 100 устройств, использующих протокол VTP, то обновление базы данных VLAN одного устройства автоматически будет реплицировано на остальных 99 устройствах. Однако не все эти устройства имеют упомянутые в обновлении сети VLAN, поэтому информация о них может быть не нужна.

\

Раcсылка обновлений базы данных VLAN устройствам, использующим VTP, означает, что все порты всех устройств получат информацию о добавленных, удаленных и измененных VLAN, к которым они могут не иметь никакого отношения. При этом сеть забивается лишним трафиком. Чтобы этого не происходило, используется концепция «обрезки» VTP. Для того, чтобы включить на свитче режим «обрезки» неактуальных VLAN, используется команда vtp pruning. После этого свитчи будут автоматически сообщать друг другу о том, какие VLAN они фактически используют, тем самым предупреждая соседей, что им не нужно присылать обновления сетей, которые к ним не подсоединены.

Например, если SW2 не имеет никаких портов VLAN10, то ему не нужно, чтобы SW1 присылал ему трафик для этой сети. В то же время свитч SW1 нуждается в трафике VLAN10, потому что один из его портов подсоединен к этой сети, просто ему не нужно отсылать этот трафик свитчу SW2.
Поэтому, если SW2 использует режим vtp pruning, он сообщает SW1: «пожалуйста, не присылайте мне трафик для VLAN10, потому что эта сеть ко мне не подсоединена и не один из моих портов не настроен на работу с этой сетью». Вот что дает использование команды vtp pruning.

Существует ещё один способ фильтрации трафика для конкретного интерфейса. Он позволяет настроить порт на транк с конкретной сетью VLAN. Недостатком такого способа является необходимость ручной настройки каждого порта транка, которому потребуется указать, какие VLAN разрешены, а какие запрещены. Для этого используется последовательность 3-х команд. Первая указывает интерфейс, которого касаются эти ограничения, вторая превращает этот интерфейс в транк-порт, а третья — switchport trunk allowed vlan < все/никакая/добавить/удалить/ номер VLAN> — показывает, какая VLAN разрешена на данном порту: все, ни одной, добавляемая VLAN или удаляемая VLAN.

В зависимости от конкретной ситуации вы выбираете, что использовать: VTP pruning или Trunk allowed. Некоторые организации предпочитают не пользоваться VTP по соображениям безопасности, поэтому выбирают ручную настройку транкинга. Так как команда vtp pruning не работает в Packet Tracer, я покажу её в эмуляторе GNS3.

Если вы зайдете в настройки SW2 и введете команду vtp pruning, система тут же сообщит, что данный режим включен: Pruning switched on, то есть «обрезка» VLAN включается всего одной командой.

Если набрать команду show vtp status, мы увидим, что режим vtp pruning разрешен.

Если вы настраиваете этот режим на свитче-сервере, то заходите в его настройки и вводите команду vtp pruning. Это значит, что подключенные к серверу устройства станут автоматически использовать vtp pruning, чтобы минимизировать трафик транкинга для неактуальных VLAN.

Если вы не хотите использовать этот режим, то должны войти в конкретный интерфейс, например, e0/0, и затем набрать команду switchport trunk allowed vlan. Система выдаст вам подсказки возможных параметров этой команды:

— WORD — номер VLAN, которая будет разрешена на данном интерфейсе в режиме транка;
— add — VLAN, которую нужно добавить в список базы данных VLAN;
— all — разрешить все VLAN;
— except — разрешить все VLAN, кроме указанных;
— none – запретить все VLAN;
— remove – удалить VLAN из списка базы данных VLAN.

Например, если у нас разрешен транк для VLAN10 и мы хотим разрешить его для сети VLAN20, то нужно ввести команду switchport trunk allowed vlan add 20.

Я хочу показать вам ещё кое-что, поэтому использую команду show interface trunk. Обратите внимание, что по умолчанию для транка были разрешены все VLAN 1-1005, а теперь к ним добавилась еще и VLAN10.

Если я использую команду switchport trunk allowed vlan add 20 и снова попрошу показать статус транкинга, мы увидим, что теперь для транка разрешены две сети – VLAN10 и VLAN20.

При этом никакой другой трафик, кроме предназначенного для указанных сетей, не сможет проходить через этот транк. Разрешив трафик только для VLAN 10 и VLAN 20, мы запретили трафик для всех других VLAN. Вот как можно вручную настроить параметры транкинга для конкретной VLAN на конкретном интерфейсе свитча.

Обратите внимание, что до конца дня 17 ноября 2017 года у нас на сайте действует 90% скидка на стоимость скачивания лабораторной работы по данной теме.

Благодарю за внимание и до встречи на следующем видеоуроке!


Спасибо, что остаётесь с нами. Вам нравятся наши статьи? Хотите видеть больше интересных материалов? Поддержите нас оформив заказ или порекомендовав знакомым, 30% скидка для пользователей Хабра на уникальный аналог entry-level серверов, который был придуман нами для Вас:Вся правда о VPS (KVM) E5-2650 v4 (6 Cores) 10GB DDR4 240GB SSD 1Gbps от $20 или как правильно делить сервер? (доступны варианты с RAID1 и RAID10, до 24 ядер и до 40GB DDR4).

Dell R730xd в 2 раза дешевле? Только у нас 2 х Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 ТВ от $199 в Нидерландах! Dell R420 — 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB — от $99! Читайте о том Как построить инфраструктуру корп. класса c применением серверов Dell R730xd Е5-2650 v4 стоимостью 9000 евро за копейки?

Let's block ads! (Why?)

Общие принципы работы QEMU-KVM

image

Мое текущее понимание:

1) KVM

KVM (Kernel-based Virtual Machine) – гипервизор (VMM – Virtual Machine Manager), работающий в виде модуля на ОС Linux. Гипервизор нужен для того, чтобы запускать некий софт в несуществующей (виртуальной) среде и при этом, скрывать от этого софта реальное физическое железо, на котором этот софт работает. Гипервизор работает в роли «прокладки» между физическим железом (хостом) и виртуальной ОС (гостем).

Поскольку KVM является стандартным модулем ядра Linux, он получает от ядра все положенные ништяки (работа с памятью, планировщик и пр.). А соответственно, в конечном итоге, все эти преимущества достаются и гостям (т.к. гости работают на гипервизоре, которые работает на/в ядре ОС Linux).

KVM очень быстрый, но его самого по себе недостаточно для запуска виртуальной ОС, т.к. для этого нужна эмуляция I/O. Для I/O (процессор, диски, сеть, видео, PCI, USB, серийные порты и т.д.) KVM использует QEMU.

2) QEMU

QEMU (Quick Emulator) – эмулятор различных устройств, который позволяет запускать операционные системы, предназначенные под одну архитектуру, на другой (например, ARM –> x86). Кроме процессора, QEMU эмулирует различные переферийные устройства: сетевые карты, HDD, видео карты, PCI, USB и пр.

Работает это так:
Инструкции/бинарный код (например, ARM) конвертируются в промежуточный платформонезависимый код при помощи конвертера TCG (Tiny Code Generator) и затем этот платформонезависимый бинарный код конвертируется уже в целевые инструкции/код (например, x86).

ARM –> промежуточный_код –> x86

По сути, вы можете запускать виртуальные машины на QEMU на любом хосте, даже со старыми моделями процессоров, не поддерживающими Intel VT-x (Intel Virtualization Technology) / AMD SVM (AMD Secure Virtual Machine). Однако в таком случае, это будет работать весьма медленно, в связи с тем, что исполняемый бинарный код нужно перекомпилировать на лету два раза, при помощи TCG (TCG – это Just-in-Time compiler).

Т.е. сам по себе QEMU мега крутой, но работает очень медленно.

3) Protection rings

image

Бинарный программный код на процессорах работает не просто так, а располагается на разных уровнях (кольцах / Protection rings) с разными уровнями доступа к данным, от самого привилегированного (Ring 0), до самого ограниченного, зарегулированного и «с закрученными гайками» (Ring 3).

Операционная система (ядро ОС) работает на Ring 0 (kernel mode) и может делать с любыми данными и устройствами все, что угодно. Пользовательские приложения работают на уровне Ring 3 (user mode) и не в праве делать все, что захотят, а вместо этого каждый раз должны запрашивать доступ на проведение той или иной операции (таким образом, пользовательские приложения имеют доступ только к собственным данным и не могут «влезть» в «чужую песочницу»). Ring 1 и 2 предназначены для использования драйверами.

До изобретения Intel VT-x / AMD SVM, гипервизоры работали на Ring 0, а гости работали на Ring 1. Поскольку у Ring 1 недостаточно прав для нормального функционирования ОС, то при каждом привилегированном вызове от гостевой системе, гипервизору приходилось налету модифицировать этот вызов и выполнять его на Ring 0 (примерно так, как это делает QEMU). Т.е. гостевой бинарный код НЕ выполнялся напрямую на процессоре, а каждый раз налету проходил несколько промежуточных модификаций.

Накладные расходы были существенными и это было большой проблемой и тогда производители процессоров, независимо друг от друга, выпустили расширенный набор инструкций (Intel VT-x / AMD SVM), позволяющих выполнять код гостевых ОС НАПРЯМУЮ на процессоре хоста (минуя всякие затратные промежуточные этапы, как это было раньше).

С появлением Intel VT-x / AMD SVM, был создан специальный новый уровень Ring -1 (минус один). И теперь на нем работает гипервизор, а гости работают на Ring 0 и получают привилегированный доступ к CPU.

Т.е. в итоге:

  • хост работает на Ring 0
  • гости работают на Ring 0
  • гипервизор работает на Ring -1

4) QEMU-KVM


KVM предоставляет доступ гостям к Ring 0 и использует QEMU для эмуляции I/O (процессор, диски, сеть, видео, PCI, USB, серийные порты и т.д., которые «видят» и с которыми работают гости).

Отсюда QEMU-KVM (или KVM-QEMU) :)

CREDITS
Картинка для привлечения внимания: https://www.ionos.com
Картинка Protection rings: https://www.researchgate.net/profile/Roberto_Pietro

PS
Текст этой статьи изначально был опубликован в Telegram канале @RU_Voip в качестве ответа на вопрос одного из участников канала.

Напишите в комментариях, в каких местах я не правильно понимаю тему или если есть, что дополнить.

Спасибо!

Let's block ads! (Why?)

Робот FEDOR вернулся с МКС на Землю

Меньше недели провел антропоморфный робот FEDOR в малом исследовательском модуле «Поиск» российского сегмента МКС. Российские космонавты Александр Скворцов и Алексей Овчинин испытали систему управления роботом и провели с ним несколько экспериментов.

Ночью 7 сентября 2019 года в 00.32 МСК спускаемый аппарат корабля «Союз МС-14» совершил успешную посадку в 147 километрах юго-восточнее казахстанского города Жезказган.
Робот Федор или FEDOR (Final Experimental Demonstration Object Research) — антропоморфный робот, который разработан НПО «Андроидная техника» и Фондом перспективных исследований (ФПИ), и должен заменить человека в местах повышенного риска, а сейчас одна из его модификаций прошла курс начинающего космонавта на борту МКС и вернулась на Землю.

Продолжение этой новостной публикации "Робот FEDOR — много фото и даже видео с МКС, подготовка космонавта-оператора и первые испытания робота".

Краткая история космического путешествия робота FEDOR:

  • 22 августа 2019 года корабль «Союз МС-14» с роботом запустили на околоземную орбиту;
  • 27 августа 2019 года корабль «Союз МС-14» со второй попытки пристыковался к МКС;
  • 29 августа 2019 года робота FEDOR перенесли в российский сегмент МКС;
  • 30-31 августа и 1 сентября 2019 года проводились серии экспериментов с роботом;
  • 4 сентября 2019 года робота FEDOR перенесли обратно в корабль «Союз МС-14»;
  • 6 сентября 2019 года в 21:13 МСК корабль «Союз МС-14» отстыковался от МКС;
  • 7 сентября 2019 года робот FEDOR приземлился на Землю.

В ходе проведения экспериментов с роботом FEDOR космонавт Александр Скворцов экипировался экзоскелетом и шлемом (часть дистанционной системы управления роботом с возможностью видеть его камерами) и из модуля «Звезда» управлял роботом в режиме «аватар».

Алексей Овчинин в этот момент находился в модуле «Поиск» рядом с роботом FEDOR и контролировал выполнение им разных тестовых операций: работа с отверткой, разными ключами, стыковка электрических соединителей.

Также с роботом было проведено диалоговое общение — космонавты задавали ему вопросы, а FEDOR их распознавал и отвечал.

Конечно, роботу FEDOR доверили шуроповерт и полотенце:

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

Первый полет робота FEDOR — это только пробный шаг в большом объеме испытаний и экспериментов, связанных с разработкой и использованием антропоморфных робототехнических систем.

Кстати, на видео ниже можно посмотреть, как двигается робот в невесомости.

Робота FEDOR обратился к российским школьникам и поздравил их с Днем знаний 1 сентября.

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

4 сентября 2019 года космонавты Алексей Овчинин и Александр Скворцов перенесли робота FEDOR обратно в корабль «Союз МС-14».

«Федора мы победили, усадили в кресло. Закрепили его металлическим наколенником, притянули все локти. Там, где нужно, в пазы вставили», — передал в ЦУП Алексей Овчинин.
Космонавт также добавил, что робот не убежит, потому что надежно закреплен.

Космонавт Александр Скворцов по просьбе ЦУПа включил робота FEDOR, зафиксированного в корабле «Союз МС-14».

«Робот включен, его зеленые индикаторы горят», — доложил Скворцов в ЦУП.

При посадке корабля «Союз МС-14» робот FEDOR озвучивал параметры полета и наблюдаемые события, фиксировал значения перегрузки.

В процессе спуска на Землю было проведено испытание новой системы управления спуском. На корабле «Союз МС-14» доработана система управления движением и навигацией в части управляемого спуска: аналоговая система управления спуском на базе свободного гироскопа полностью замене на цифровую на базе прибора БИУС (блок интегрирования угловых скоростей) с использованием оптоволоконных гироскопов, это новое устройство разработано в РКК «Энергия».

Корабль «Союз МС-14» 6 сентября 2019 года в 21:13:54 МСК успешно отстыковался от агрегатного отсека служебного модуля «Звезда» российского сегмента МКС.

Трансляция NASA:

Маршевый двигатель корабля был включен на торможение 6 сентября в 23:37 МСК. Спустя почти 4 минуты двигатель завершил работу и корабль начал сход с околоземной орбиты.

В связи с тем, что все операции по посадке проходили в ночное время суток, Роскосмос не проводил прямую трансляцию с места посадки.

Приземление спускаемого аппарата «Союза МС-14» состоялось в 147 километрах юго-восточнее казахстанского города Жезказган 7 сентября в 00.32 МСК.

Все операции по сведению с орбиты и приземлению прошли в штатном режиме.

Безопасность посадки «Союза МС-14» обеспечивала поисково-спасательная группа Центрального военного округа в составе 8 вертолетов Ми-8, самолеты Ан-12 и Ан-26, 20 единиц автомобильной техники, 5 из которых – поисково-эвакуационные машины «Синяя птица», а также 130 военнослужащих.

Руководитель летно-космического центра РКК «Энергия» Александр Калери сообщил, что робота не планируется сразу извлекать из корабля на месте приземления, так как это достаточно сложная и трудоемкая операция, а вместе со спускаемым аппаратом доставят в испытательный корпус РКК «Энергия».

После возвращения на Землю робота FEDOR будут изучать, анализировать его логи и записи, модифицировать, готовить к новому полету и работе на внешнем борту МКС или участию в тестовых испытаниях на новом корабле в рамках опытно-конструкторской работы «Федерация».

Let's block ads! (Why?)