Часть 1 Веб-серверы и сервисы
Rust — отличный язык программирования, который в наши дни пользуется большой популярностью. Изначально он рекламировался как язык системного программирования, наряду с другими известными языками, такими как C или Go (lang). Действительно, он постепенно проникает в ядро Linux: в настоящее время он ограничен драйверами и модулями, но его неотъемлемые качества — в основном выразительность, безопасность памяти и производительность — несомненно, откроют двери для более важных частей операционной системы. Более медленными темпами Rust также проникает во все еще конфиденциальную область веб-сборки (WAS), в браузере или в бессерверном облаке.
Как и в случае с Go, разработчики-новаторы показали, что применимость Rust выходит за рамки системного программирования и что его можно использовать, например, для разработки эффективных серверных частей веб-приложений, поддерживаемых базами данных.
В этой первой части книги мы разработаем простое, но представительное веб-приложение с использованием веб-служб REST, поддерживаемое реляционной базой данных. Мы пока не будем рассматривать аспекты пользовательского интерфейса, они будут рассмотрены во второй части книги. В этой части книги мы создадим основы для нашего веб-приложения, думая масштабно, но начиная с малого. Затем мы рассмотрим более специализированные темы, такие как сохранение базы данных, обработка ошибок, обслуживание и рефакторинг API.
После завершения этой части вы сможете настраивать и разрабатывать надежные серверные части приложений, включая маршрутизацию и обработку ошибок, используя Rust и несколько проверенных в полевых условиях ящиков (crates). После этого вы будете готовы приступить ко второй части.
1. Почему Rust подходит для веб-приложений?
Подключенные веб-приложения, работающие через Интернет, формируют основу современного бизнеса и цифровой жизни людей. Как частные лица, мы используем ориентированные на потребителя приложения для социальных сетей и коммуникаций, для покупок в электронной коммерции, для бронирования поездок, для осуществления платежей и управления финансами, для получения образования и для развлечения — вот лишь некоторые из них. Аналогичным образом, бизнес-ориентированные приложения используются практически во всех функциях и процессах предприятия.
Современные веб-приложения представляют собой невероятно сложные распределенные системы. Пользователи этих приложений взаимодействуют через веб- или мобильные интерфейсы. Но пользователи редко видят сложную среду серверных служб и компонентов программной инфраструктуры, которые отвечают на запросы пользователей, поступающие через простые пользовательские интерфейсы приложений. Популярные потребительские приложения содержат тысячи внутренних сервисов и серверов, распределенных в центрах обработки данных по всему миру. Каждая функция приложения может быть запущена на другом сервере, реализована с использованием другого дизайна, написана на другом языке программирования и расположена в другом географическом месте. Благодаря удобному взаимодействию с пользователем в приложении все выглядит очень просто. Но разрабатывать современные веб-приложения совсем не просто.
Мы используем веб-приложения каждый раз, когда пишем в Твиттере, смотрим фильм на Netflix, слушаем песню на Spotify, бронируем поездку, заказываем еду, играем в онлайн-игру, вызываем такси или пользуемся любым из многочисленных онлайн-сервисов в повседневной жизни. Без распределенных веб-приложений бизнес и современное цифровое общество пришли бы к полной остановке.
Веб-сайты предоставляют информацию о вашем бизнесе.
Веб-приложения предоставляют услуги вашим клиентам.
Из этой книги вы узнаете о концепциях, методах и инструментах, которые понадобятся вам при использовании Rust для проектирования и разработки распределенных веб-сервисов и приложений, взаимодействующих по стандартным интернет-протоколам. Попутно вы увидите основные концепции Rust в действии на практических примерах.
Эта книга для вас, если вы являетесь инженером-программистом веб-серверной части, разработчиком приложений с полным стеком, облачным или корпоративным архитектором, техническим директором технологического продукта или просто любопытным слушателем, заинтересованным в создании распределенных веб-приложений, которые являются невероятно безопасными, эффективными, высокопроизводительными и выполняют следующие функции: не требуют непомерных затрат на эксплуатацию и техническое обслуживание. Разрабатывая рабочий пример по ходу чтения этой книги, я покажу вам, как создавать веб-сервисы и традиционные интерфейсы веб-приложений в чистом виде в Rust.
Как вы увидите из последующих глав, Rust — это язык общего назначения, который эффективно поддерживает разработку множества различных типов приложений. В этой книге представлено одно приложение, но продемонстрированные методы применимы ко многим другим ситуациям с использованием тех же или других ящиков (crates).
В этой главе мы рассмотрим ключевые характеристики распределенных веб-приложений, поймем, как и где работает Rust, и опишем пример приложения, которое мы будем создавать вместе в этой книге.
1.1. Знакомство с современными веб-приложениями
Мы начнем с рассмотрения структуры современных распределенных веб-приложений. В распределенных системах есть компоненты, которые могут быть распределены по нескольким различным вычислительным процессорам, взаимодействовать по сети и одновременно выполнять рабочие нагрузки. Технически ваш домашний компьютер напоминает сетевую распределенную систему (учитывая современные многопроцессорные и многоядерные процессоры).
К популярным типам распределенных систем относятся:
- Распределенные сети, такие как телекоммуникационные сети и Интернет.
- Распределенные клиент-серверные приложения. (Большинство веб-приложений относятся к этой категории)
- Распределенные P2P-приложения, такие как BitTorrent и Tor.
- Системы управления в режиме реального времени, такие как управление воздушным движением и промышленностью.
- Распределенные серверные инфраструктуры, такие как облачные, сетевые и другие формы научных вычислений.
- Распределенные системы в широком смысле состоят из трех частей: распределенных приложений, сетевого стека и аппаратной инфраструктуры и операционной системы.
- Распределенные приложения могут использовать широкий спектр сетевых протоколов для внутренней связи между своими компонентами. Однако сегодня HTTP является подавляющим выбором для веб-сервиса или веб-приложения, взаимодействующих с внешним миром, благодаря своей простоте и универсальности.
- Веб-приложения — это программы, использующие HTTP в качестве протокола прикладного уровня и предоставляющие функциональность, доступную обычным пользователям через стандартные интернет-браузеры.
Когда веб-приложения не являются монолитными, а состоят из десятков или сотен распределённых прикладных компонентов, которые взаимодействуют и обмениваются данными по сети, они называются распределёнными веб-приложениями.
Примеры: Facebook, X, Amazon, eBay, Uber, Airbnb, Netflix, AWS, Google Cloud, Azure.
На рисунке 1.1 представлено логическое представление стека распределённых систем для современного веб-приложения.
Рисунок 1.1 Упрощенный стек распределённых систем для приложения социальных сетей
Аппаратные компоненты и инфраструктура операционной системы — это такие компоненты, как физические серверы (в центре обработки данных или облаке), операционная система и средства виртуализации или контейнерные среды выполнения. Такие устройства, как встроенные контроллеры, датчики и периферийные устройства, также могут быть отнесены к этому уровню (представьте себе футуристический случай, когда подписчикам сети супермаркетов в социальных сетях отправляются твиты, когда товары с RFID-маркировкой добавляются на полки супермаркетов или убираются с них).
Сетевой стек — четырёхуровневый набор интернет-протоколов:
- Уровень сетевых соединений/доступа
- Уровень Интернета
- Транспортный уровень
- Прикладной уровень
- Первые три уровня обычно реализуются на аппаратном уровне или на уровне ОС. Для большинства распределённых веб-приложений HTTP является основным используемым протоколом прикладного уровня.
Подробнее: Internet Protocol suite
Распределённые приложения — подмножество распределённых систем.
- Интерфейсы приложений — мобильные приложения (iOS, Android) или веб-интерфейсы.
- Серверные части приложений — бизнес-правила, логика БД, интеграции. Развёртываются как процессы, микросервисы, контейнеры.
- Распределённая программная инфраструктура — протоколы, БД, кэши, балансировщики, сервис-дискавери, безопасность, мониторинг.
- Теперь, когда вы ознакомились с распределёнными веб-приложениями, давайте рассмотрим преимущества использования Rust для их создания.
1.2. Выбор Rust для веб-приложений
Rust можно использовать для создания всех трёх уровней распределённых приложений: интерфейсов, серверных служб и компонентов программной инфраструктуры. Каждый уровень — свой набор задач и характеристик.
Клиентские интерфейсы: дизайн UI, реакция на изменения состояния, обновление DOM.
Серверные службы: оптимизация API, высокая пропускная способность, низкая задержка, эффективное использование ресурсов, доступность.
Инфраструктура: минимальные задержки, низкоуровневое управление ресурсами, быстрый старт, эргономичные API для внутренних сервисов.
Один проект = минимум три набора характеристик и требований.
1.2.1. Характеристики веб-приложений
- Критически важные приложения (автономное управление, автоматизация, трейдинг и др.)
- Платформы для транзакций и обмена сообщениями (e-commerce, соцсети, платежи)
- Реалтайм-приложения (игры, видео, видеоконференции)
К этим приложениям предъявляется общий набор требований:
- Безопасность и отказоустойчивость
- Ресурсоэффективность
- Минимизация задержки
- Параллелизм
- Быстрый старт/завершение работы
- Простота поддержки и реорганизации
- Производительность разработчика
Все эти требования могут быть выполнены как на уровне сервисов, так и на архитектурном уровне.
1.2.2. Преимущества Rust для веб-приложений
Rust для серверных приложений и инфраструктурных служб отвечает всем критическим требованиям из предыдущего раздела.
- Безопасность типов: статическая типизация, строгая проверка компилятором, полезные сообщения об ошибках.
- Безопасность памяти: уникальная модель владения, автоматическое освобождение памяти (RAII), интеллектуальные указатели, отсутствие ручного управления памятью и сборщика мусора.
- Потокобезопасность: thread-safe по умолчанию, компилятор предотвращает гонки данных.
Важные концепции:
Владение — каждому значению есть владелец. Если значение передано, старый владелец больше не может его использовать.
Заимствование — временный доступ к значению через ссылки (&T или &mut T).
Компилятор гарантирует отсутствие dangling/invalid ссылок. Примеры кода:
// Объявление переменной с выводом типа let x = 5;
// Передача владения let s1 = String::from("hello"); let s2 = s1; // s1 больше нельзя использовать
// Неизменяемая ссылка fn print_len(s: &String) { println!("{}", s.len()); }
// Автоматическое освобождение памяти { let x = String::from("data"); } // x здесь уничтожается автоматически
Гарантии безопасности:
- Нет null- и висячих указателей
- Нет переполнения буфера
- Отсутствие гонок данных
- Неизменяемость по умолчанию
- Нет сборщика мусора → нет nondeterminism
- Полное сопоставление с образцом (
match
) - Алгебраические типы
Для погружения в безопасность:
Продуктивность:
- Замыкания (анонимные функции)
- Итераторы
- Обобщения и макросы
- Перечисления (Option, Result)
- Полиморфизм по трейтам
- Динамическая диспетчеризация
Не случайно Rust — самый любимый язык в опросе Stack Overflow с 2016 по 2025 годы.
Подробнее: Почему разработчики любят Rust
1.2.3. Чего нет в Rust?
- Высокая планка входа, особенно для новичков
- Некоторые структуры данных сложнее (например, двусвязные списки)
- Компилятор Rust пока медленнее других
- Молодая экосистема и сообщество
- Сложнее найти и нанять разработчиков
- Меньше внедрён в крупные компании
Теперь вы ознакомились с преимуществами и недостатками использования Rust для разработки внутренних сервисов приложений. В следующем разделе — пример приложения.
1.3. Визуализация примера приложения
В следующих главах мы будем использовать Rust для создания веб-серверов, веб-служб и веб-приложений и продемонстрируем концепции на подробном примере. Наша цель — не полностью функциональное приложение, а показать подходы Rust в веб-домене.
Будем разрабатывать: цифровую витрину для преподавателей EzyTutors, где преподаватели могут размещать каталоги своих курсов. Это не marketplace, а витрина для продажи собственных курсов.
- Регистрация и вход преподавателей
- Публикация курсов, связь с категориями
- Персональная страница преподавателя
- Общий сайт — поиск и просмотр курсов
Технический стек: Rust (Actix Web), SQLx, Postgres, полный async, шаблоны для SSR.
Особенности: не используется фронтенд-фреймворк, не рассматривается CI/CD, весь проект максимально универсален (кроссплатформенность, контейнеризация поддерживается).
В процессе: создаём RESTful веб-сервис, затем расширяем модель, добавляем функциональность, рефакторим код.
Бонус: интерфейс на шаблонах, отдельная архитектура, контейнеризация.
Методы и приёмы:
- Строгая типизация, тесты
- Модули и рабочие пространства
- Асинхронность, обработка ошибок
- Чистый и идиоматичный код
Что не рассматривается: DevOps-инфраструктура, прокси, балансировщики, TLS/SSL, мониторинг, CDN и т.д.
В проекте покажем: автоматизированные тесты, структурирование, отделение конфигурации от кода, документация, идиоматичный Rust.
Готовы ли вы к практическому использованию Rust в Интернете?
1.3.2. Технические рекомендации для примера приложения
- Структура проекта: используем модульную систему Rust, рабочие пространства Cargo.
- Принцип единой ответственности: каждый модуль — отдельная функциональность.
- Удобство сопровождения:
- Понятные имена переменных и функций
- Форматирование с rustfmt
- Автоматизированные тесты
- Структура и имена файлов должны быть интуитивно понятны
- Безопасность: JWT, пароли, memory-safety Rust
- Конфигурация отдельно от кода
- Минимум внешних crate’ов
- Асинхронность во всём стеке
Теперь мы можем приступить к изучению веб-серверов и веб-служб в следующей главе.
Резюме
- Современные веб-приложения — сложные, критически важные для жизни и бизнеса.
- Веб-приложения = интерфейсы + сервер + инфраструктура.
- Серверные части — слабо связанные сервисы с особыми требованиями к времени выполнения.
- Rust подходит для распределённых веб-приложений: безопасность, параллелизм, низкая задержка, ресурсоэффективность.
- В книге выбран практический пример приложения и приведены ключевые рекомендации.