Rocket.rs  —  самый известный фреймворк на Rust для легкого создания производительных и типобезопасных веб-приложений. Развернем с его помощью собственный Rocket REST API на AWS.

Что понадобится

Базовые знания:

  • языка программирования Rust;
  • команд оболочки в Linux;
  • AWS Elastic Compute Cloud (EC2) и сетей;
  • учетная запись AWS.

Что будем разворачивать?

Очень простой Rocket REST API с двумя маршрутами: / и /sort. Первый маршрут  —  это индекс. После GET-запроса он отправит текст Hello from Rocket REST API!. Второй  —  POST-маршрут. По нему в приложении в ответ на заданный несортированный целочисленный массив и порядок сортировки вернется корректно отсортированный массив.

Вот пример валидного POST-запроса, отправленного в /sort:

request JSON body: {
"array": [2,6,1,5,3,4],
"sort_order": "descending"
}

response JSON: {
"sorted_array": [6,5,4,3,2,1]
}

Массив должен быть целочисленным, а порядок сортировки  —  ascending (возрастающий) или descending (убывающий). Если запрос невалидный, получаем ответ:

request JSON body: {
"array": [4.5, 1.2, 6.56, 3.709],
"sort_order": "random"
}

response JSON: {
"message": "The JSON posted is invalid. Make sure the 'array' field is an array of integers and 'sort_order' is either 'ascending' or 'descending'."
}

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

Запуск экземпляра EC2

Заходим в учетную запись AWS с полным доступом к EC2 и выбираем регион для запуска экземпляра. Переходим в консоль EC2 и нажимаем Launch instance («Запустить экземпляр»):

В окне Launch an instance вводим название экземпляра и выбираем Amazon Linux 2 AMI:

В поле Number of instances («Количество экземпляров») оставляем 1. Выбираем условно-бесплатный уровень t2.micro  —  один из самых дешевых типов экземпляров. Чтобы подключиться к EC2 по SSH, создадим/выберем пару ключей или позже воспользуемся EC2 Instance Connect:

А пока выбираем группу безопасности по умолчанию  —  свою создадим после запуска экземпляра  —  и оставляем для блочного хранилища EBS (Elastic Block Store) значение по умолчанию 8 Гб SSD-памяти gp2:

Пропускаем Advanced details («Дополнительные сведения») и нажимаем Launch instance («Запустить экземпляр»):

Переходим в Instances («Экземпляры») слева и через мгновение видим запущенный экземпляр EC2.

Создание группы безопасности

Теперь заменим группу безопасности по умолчанию на более строгую. Переходим в Network & Security («Сеть и безопасность») слева, затем в Security Groups («Группы безопасности»). Нажимаем Create security group («Создать группу безопасности»), вводим название и описание группы:

Добавляем правила для входящих подключений:

И для исходящих:

Создав группу безопасности, переходим сначала в Instances, где выбираем экземпляр, а затем в Actions («Действия») и Security («Безопасность»):

В окне Change security groups («Изменить группы безопасности») удаляем группу безопасности по умолчанию, добавляем созданную и нажимаем Save («Сохранить»):

Доступ к экземпляру по SSH

Чтобы настроить экземпляр для запуска приложения Rocket, подключимся к EC2 по SSH. Снова переходим в Instances, выбираем экземпляр и нажимаем Connect («Подключиться»):

Если вы добавили пару ключей SSH для экземпляра, подключитесь через командную строку. Или воспользуйтесь Instance Connect в браузере:

После подключения к экземпляру EC2 видим следующее:

Установка зависимостей

Сначала с помощью диспетчера пакетов yum установим git для клонирования репозитория:

~]$ sudo yum install git -y

Так же устанавливаем gcc для создания двоичного файла Rust:

~]$ sudo yum install gcc -y

Наконец, устанавливаем Rust и диспетчер пакетов Cargo:

~]$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

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

~]$ exec bash

Клонирование проекта Rocket

Клонируем гит-репозиторий в каталог /home/ec2-user:

~]$ git clone https://github.com/caleb-bender/rocket-rest-api-demo.git

Переходим в каталог проекта:

~]$ cd rocket-rest-api-demo

Сборка проекта для продакшена

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

~]$ cargo build --release

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

В Rocket для настройки различных сред, например стандартной, debug («Среды отладки»), release («Среды выпуска»), используется файл .toml, в котором указываются порт для запуска приложения и область адреса  —  общедоступного или закрытого. Чтобы корректно настроить приложение Rocket, создаем в каталоге /home/ec2-user/rocket-rest-api-demo файл Rocket.toml и добавляем следующее:

[debug]
port = 8000

[release]
address = "0.0.0.0"
port = 8000

Поле адреса address очень важно, ведь Rocket по умолчанию запускается локально. Указывая "0.0.0.0" , мы открываем доступ к приложению Rocket. Подробнее о файлах Rocket.toml см. здесь.

Запускаем Rocket:

~]$ cargo run --release

Если команда выполнена успешно, видим в терминале следующее:

Открываем в браузере вкладку/окно и в поле URL-адреса вставляем общедоступные IPv4-адрес или DNS IPv4. Порт должен быть 8000. Например:

http://13.57.226.189:8000/

Нажимаем Enter и видим следующее сообщение:

А еще с помощью Postman или curl по маршруту /sort отправляется POST-запрос, на который в компьютере возвращается ответ:

~]$ curl --header "Content-Type: application/json" \
--request POST \
--data '{"array":[5,6,1,3,2,4],"sort_order":"ascending"}' \
http://13.57.226.189:8000/sort

Вот ответ на запрос команды curl:

Однако когда подключение к экземпляру EC2 по SSH закрывается, работа приложения Rocket прекращается. Можно ли даже в этом случае продолжить ее в фоновом режиме?

Создание службы systemd

Systemd  —  это диспетчер Linux для создания различных служб и управления ими. Чтобы запустить приложение Rocket как службу, создадим файл службы systemd.

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

Запускаем этой командой:

~]$ sudo touch /etc/systemd/system/Rocket.service

Используя Vim (с префиксом sudo), открываем файл и вставляем этот текст:

[Unit]
Description=Rocket
After=network-online.target

[Service]
ExecStart=/home/ec2-user/.cargo/bin/cargo run --manifest-path /home/ec2-user/rocket-rest-api-demo/Cargo.toml --release
KillSignal=SIGINT
Restart=always
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=Rocket
User=ec2-user
Environment="ROCKET_ADDRESS=0.0.0.0"

Пробежимся по содержимому файла. В поле After ниже [Unit] службе systemd указывается, что сеть должна быть запущена до этой службы.

В разделе [Service] указывается команда, выполняемая при запуске службы. В ExecStart выполняется cargo run --release, но с абсолютными путями команды и местосположением файла Cargo.toml.

В поле Environment адрес Rocket делается глобальным. Это необходимо, ведь systemd «не знает» о созданном ранее файле Rocket.toml.

Сохраняемся и выходим из Vim.

Запуск Rocket как службы systemd

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

~]$ sudo systemctl daemon-reload

Посмотрим статус службы Rocket:

~]$ sudo systemctl status Rocket

В выводе должно указываться: служба загружена, но неактивна.

Запускаем ее:

~]$ sudo systemctl start Rocket

Теперь в выводе статуса должно указываться: служба запущена.

Покажем, что приложение выполняется в фоновом режиме: закрываем SSH-подключение к экземпляру и пробуем получить в браузере доступ к пути /, не забывая о порте 8000. Приветствие приложения Rocket останется.

Другие команды службы

Снова подключаемся к экземпляру EC2 по SSH.

~]$ sudo systemctl enable Rocket

Этой командой службе systemd указывается на автоматический запуск Rocket при загрузке вместе с любыми другими управляемыми ею службами. Применяется для временного отключения экземпляра EC2 с последующим перезапуском.

Так отменяем запуск службы при загрузке:

~]$ sudo systemctl disable Rocket

Этой командой службе systemd указывается на нежелательность автоматического запуска Rocket при загрузке экземпляра.

Так отменяем выполнение службы:

~]$ sudo systemctl stop Rocket

Этой командой работа приложения Rocket завершается: снова проверьте статус службы.

Очистка экземпляра

Во избежание лишних затрат работа экземпляра EC2 завершается либо прерывается. Завершение  —  все равно что выключить компьютер: запустите экземпляр снова, и все сохраненное останется.

Когда работа экземпляра завершается, затраты очень медленно образуются только по то́му EBS. Но будьте осторожнее с прерыванием работы экземпляра: все настроенное здесь будет потеряно, не останется ни экземпляра, ни тома EBS.

Чтобы завершить/прервать работу экземпляра, выбираем экземпляр в Instances, переходим в Instance state («Состояние экземпляра») и выбираем соответствующий вариант:

Заключение

Цель этого руководства  —  поэтапно развернуть приложение Rocket Rust на AWS. Выбранный метод несовершенен для реального, пригодного для промышленной эксплуатации приложения: доступ к API по HTTP/HTTPS обычно осуществляется через порты 80/443 соответственно, а не 8000.

А это уже за рамками данного руководства. Чтобы конечные пользователи имели доступ к приложению через стандартные HTTP-порты, при развертывании реального приложения Rocket для продакшена пришлось бы настроить балансировщик нагрузки или обратный прокси-сервер с nginx.

Приложение Rocket запускается через порт 8000, хотя лучше было бы использовать балансировщик нагрузки или nginx для перенаправления HTTP-запросов. Не помешало бы и создание группы автомасштабирования для экземпляра EC2: она лучше масштабируется при колебаниях сетевого трафика.

Читайте также:

Читайте нас в TelegramVK и Дзен


Перевод статьи Caleb Bender: Launching a Rocket REST API on AWS

Предыдущая статьяОбъекты данных в Kotlin
Следующая статья5 библиотек JavaScript, которые повысят вашу эффективность