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: она лучше масштабируется при колебаниях сетевого трафика.
Читайте также:
- Тип Result в Rust
- Сравниваем REST, GraphQL и gRPC
- Как запустить и использовать файловые системы с помощью Amazon FSx
Читайте нас в Telegram, VK и Дзен
Перевод статьи Caleb Bender: Launching a Rocket REST API on AWS