ИТ Блог. Администрирование серверов на основе Linux (Ubuntu, Debian, CentOS, openSUSE)
Четверг, 20 февраля, 2025

Микросервисы и философия UNIX: сходства и различия

Микросервисы и философия UNIX

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

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

Но действительно ли все принципы микросервисов и философии UNIX схожи? Давайте рассмотрим это подробнее, начав с более классического подхода — философии UNIX.

 

Философия UNIX

История UNIX началась в 1969 году, когда Кен Томпсон и Деннис Ритчи начали разрабатывать операционную систему в Bell Labs. Кен Томпсон, известный как один из создателей UNIX, внёс значительный вклад не только в саму систему, но и в её философию.

В 1973 году UNIX был переписан с языка программирования B на C, что обеспечило независимость от аппаратного обеспечения и различные важные функции, с которыми мы знакомы сегодня, такие как разные типы переменных (intcharfloat и т. д.) и необходимость их объявления (статическая типизация). На протяжении 1970-х и 1980-х годов UNIX развивался, распространяясь в академических кругах и коммерческих организациях, постепенно формируя свои ключевые принципы.

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

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

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

  1. Пишите программы, которые делают что-то одно, и делают это хорошо.
  2. Пишите программы для совместной работы.
  3. Пишите программы, которые обрабатывают текстовые потоки, потому что это универсальный интерфейс.

 

Хотя мы обсуждаем принципы и философию UNIX, в качестве практических примеров мы будем использовать Linux, в частности Debian. Этот выбор обусловлен бесплатной доступностью Debian, простотой доступа (в том числе на платформе Hostman) и его статусом классического примера системы Linux.

Хотя Linux не является прямым потомком UNIX, он наследует все его принципы. Большинство рассмотренных команд и концепций применимы как к UNIX, так и к Linux. Также стоит отметить, что популярный дистрибутив Ubuntu создан на основе Debian, что подчёркивает важность последнего в мире Linux.

 

Принцип 1: Пишите программы, которые делают что-то одно, и делают это хорошо

Если вы работали с системами Linux, то, вероятно, знакомы с командой cat (сокращение от «concatenate»). Хотя она выглядит как команда в bash (командной строке), на самом деле это отдельная программа, написанная на C, скомпилированная и обычно находящаяся по адресу /usr/bin/cat. Её исходный код доступен в интернете как часть проекта GNU coreutils.

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

$ cat /etc/passwd

 

Результатом выполнения этой команды будет список системных пользователей, похожий на этот:

root:x:0:0:root:/root:/bin/bash
alice:x:1000:1000:Alice Smith,,,:/home/alice:/bin/bash
bob:x:1001:1001:Bob Johnson,,,:/home/bob:/bin/zsh
mysql:x:112:120:MySQL Server,,,:/nonexistent:/bin/false
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

 

Каждая строка содержит имя пользователя, UID, GID, полное имя, домашний каталог и другие параметры, разделённые двоеточиями.

Вы можете поэкспериментировать с cat и другими командами, выполнив:

 

cat имеет множество дополнительных опций, например:

 

Вы можете изучить другие варианты, запустив cat --help или прочитав полную документацию с помощью man cat.

Одной из важных особенностей cat является его способность объединять содержимое нескольких файлов. Это результат его основной функции: cat последовательно считывает указанные файлы и отправляет их содержимое на стандартный вывод (stdout). Отсюда и его название — «объединять» означает «связывать» или «соединять в цепочку». По сути, отображение содержимого на экране — это комбинация содержимого файла и потока stdout в Linux.

Пример использования cat для объединения файлов:

cat /etc/hostname /etc/hosts

 

Результат может выглядеть примерно так:

myserver
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback

 

В этом примере cat сначала выводит содержимое /etc/hostname, а затем содержимое /etc/hosts.

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

 

Принцип 2: Пишите программы для совместной работы

Этот принцип демонстрирует одну из ключевых особенностей UNIX — возможность комбинировать простые инструменты для решения сложных задач. Благодаря Дугу Макилрою, который ввёл в UNIX концепцию каналов, команды можно объединять в цепочки. Вывод одной команды может быть входом для другой. Давайте рассмотрим пример:

cat /etc/passwd | grep user

Команда grep это ещё одна программа (команда), которая фильтрует текстовый поток и возвращает только строки, содержащие указанный текст — в данном случае user. Здесь cat выводит все строки файла /etc/passwd. Затем grep проверяет каждую строку; если текст user присутствует, программа выводит эту строку.

Результатом будет строка, соответствующая user счету:

user:x:1000:1000:,,,:/home/user:/bin/bash

 

Мы можем расширить этот процесс, добавив дополнительные команды:

cat /etc/passwd | grep user | awk '{print $6}'

 

Эта команда выводит домашний каталог пользователя.

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

/home/user

 

В UNIX команды можно объединять в длинные цепочки для выполнения сложных операций. Такой модульный подход позволяет каждому инструменту сосредоточиться на конкретной задаче и слаженно работать вместе для достижения сложных результатов.

 

Принцип 3: пишите программы, которые работают с текстовыми потоками, потому что это универсальный интерфейс

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

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

Пример обработки текстового потока:

du -h /var/log | sort -rh | head -n 5 | awk '{print $2 " - " $1}'

 

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

  1. du -h /var/log — Отображает размеры файлов и каталогов в /var/log в удобном для восприятия человеком формате.
  2. sort -rh — Сортирует выходные данные по размеру в обратном порядке.
  3. head -n 5 — Выбирает только первые пять строк.
  4. awk '{print $2 " - " $1}' — Переформатирует вывод, отображая только первые два столбца в обратном порядке и добавляя тире между ними.

 

Пример вывода:

/var/log/syslog - 200M
/var/log/auth.log - 150M
/var/log/kern.log - 100M
/var/log/dpkg.log - 50M
/var/log/faillog - 10M

 

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

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

 

Микросервисы

Термин «микросервисы» впервые был упомянут на конференции по архитектуре программного обеспечения в Венеции в 2011 году. С тех пор микросервисы стали неотъемлемой частью современной архитектуры программного обеспечения. К 2015 году такие гиганты индустрии, как Netflix и Amazon, успешно внедрили этот подход. С тех пор популярность микросервисов в сфере ИТ неуклонно растёт.

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

 

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

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

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

 

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

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

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

Микросервисы позволяют использовать различные языки программирования, такие как:

 

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

 

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

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

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

Эти задачи ложатся на плечи специалистов по DevOps. Они разрабатывают и внедряют стратегии эффективного управления распределённой системой, включая мониторинг, ведение журналов и автоматизацию развёртывания.

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

 

Современные инструменты для работы с микросервисами

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

 

Контейнеризация и докер

Контейнеризация — это метод виртуализации на уровне операционной системы, который позволяет изолированным процессам работать в общей среде. Docker, выпущенный в 2013 году, стал синонимом контейнеризации, произведя революцию в разработке и развёртывании приложений.

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

Стандартизация контейнеров привела к созданию в 2015 году Open Container Initiative (OCI), обеспечивающей совместимость различных инструментов контейнеризации.

 

Управление контейнерами и Kubernetes

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

Kubernetes, изначально разработанный компанией Google и выпущенный в 2014 году, стал стандартом де-факто для оркестрации контейнеров. Это платформа для автоматизации развёртывания, масштабирования и управления контейнерными приложениями.

Ключевые особенности Kubernetes:

 

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

 

Современные инструменты для разработки микросервисов

Современная разработка микросервисов опирается на множество инструментов и сервисов, которые упрощают создание, развёртывание и управление распределёнными системами. Российские облачные провайдеры, такие как Hostman, предлагают комплексные решения для работы с микросервисами:

 

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

 

Микросервисы против монолитной архитектуры

Монолитная архитектура

Монолитная архитектура имеет ряд преимуществ, особенно на ранних стадиях разработки:

 

Микросервисная архитектура

Однако по мере роста проекта микросервисная архитектура начинает демонстрировать свои преимущества:

 

Сравнительная таблица

Аспект Монолит Микросервисы
Развитие Легче на ранних стадиях Более сложный, но более гибкий по мере роста проекта
Развертывание Простой, но требует полного обновления Более сложный, но допускающий частичные обновления
Масштабируемость Вертикальное, целостное применение Горизонтальные, индивидуальные услуги
Надежность Один сбой может повлиять на всю систему Сбои изолированы в рамках отдельных служб
Технологический Стек Унифицированный для всего приложения Может варьироваться в зависимости от различных сервисов
Производительность Потенциально выше для небольших приложений Может быть оптимизирован для больших систем
Командное Сотрудничество Вся команда работает над одной кодовой базой Команды могут работать над отдельными сервисами

 

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

 

Решение должно основываться на конкретных потребностях и долгосрочных целях проекта.

 

Пример разработки архитектуры микросервисов

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

Например:

 

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

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

 

Ключевые микросервисы в Системе

  1. Служба управления движением: Управляет рулевым управлением, торможением и ускорением.
  2. Служба компьютерного зрения: Обрабатывает данные с камер, распознает объекты и дорожные ситуации.
  3. Навигационный сервис: Планирует маршрут и принимает решения о вождении.
  4. Служба связи: Обеспечивает связь с другими транспортными средствами и инфраструктурой.
  5. Служба государственного мониторинга: Отслеживает техническое состояние транспортного средства.

 

Каждый микросервис работает автономно и взаимодействует с другими через чётко определённые интерфейсы, что даёт несколько преимуществ:

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

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

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

Кроме того, обновление может быть установлено «по воздуху» (OTA), поскольку обновляется только один микросервис, а объём передаваемых данных относительно невелик.

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

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

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

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

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

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

 

Сравнение микросервисов и философии UNIX

Несмотря на десятилетия, разделяющие концепции UNIX и микросервисов, между ними можно провести параллели. Сравнение микросервисов с UNIX выявляет как общие принципы, так и уникальные особенности каждого подхода. Оба подхода стремятся к модульности и специализации компонентов. Микросервисы, как и утилиты UNIX, часто выполняют одну конкретную задачу, будь то управление пользователями, доступом или абстракция базы данных. Однако микросервисы, как правило, более сложны и могут развиваться, приобретая дополнительные функции.

Взаимодействие компонентов реализовано по-разному: в UNIX используется встроенное перенаправление stdin и stdout через каналы, а микросервисы требуют специальных протоколов (REST, RPC) с чётко документированными интерфейсами. Это усложняет взаимодействие между сервисами по сравнению с простым подходом UNIX.

Однако оба подхода часто используют текстовый формат для обмена данными. В микросервисах это обычно JSON или YAML, что соответствует принципу текстовых потоков в UNIX.

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

 

Сходства

Модульность и единая ответственность:

 

Взаимодействие компонентов:

 

Текстовый формат данных:

Различия

Сложность компонентов:

Механизм взаимодействия:

Контекст выполнения:

Цели и применение:

Сложность разработки и внедрения:

 

Заключение

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

Основные сходства, которые мы обнаружили, включают:

 

Однако мы также выявили существенные различия:

 

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

Принципы, лежащие в основе философии UNIX и архитектуры микросервисов, также отражены в других методологиях разработки программного обеспечения. Объектно-ориентированное программирование (ООП) с его концепцией инкапсуляции и принципами SOLID подчеркивает важность модульности и специализации. Принцип единой ответственности (SRP) из SOLID перекликается с идеей UNIX «хорошо делать что-то одно». Такие шаблоны проектирования, как фасад, адаптер и синглтон, способствуют созданию модульных и эффективно взаимодействующих компонентов. Функциональное программирование, ориентированное на чистые функции и неизменяемость, также разделяет идею создания небольших, чётко определённых компонентов, что соответствует принципам как UNIX, так и архитектуры микросервисов.

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

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

Exit mobile version