Бессерверные системы легко запускаются, но на более поздних этапах их жизненного цикла могут возникнуть некоторые проблемы. По своей природе они не имеют статических данных, и уследить за всеми движущимися частями не так-то просто. Пусть ваши бессерверные функции вызывают друг друга или помещают между своими функциями другой сервис, например очередь или базу данных. Оба решения в прошлом были неоптимальными.
Если вы вызываете бессерверную функцию из другой бессерверной функции, вы платите за обе, даже если первая просто ждет вторую и ничего не делает.
Предположим, вы используете другой сервис для создания моста между функциями. В таком случае это может стоить денег, даже если сервис простаивает, поскольку многие бессерверные сервисы, связанные с данными, являются бессерверными во всех отношениях, кроме ценообразования.
Высокоинтегрированные облачные провайдеры, такие как AWS или Google, могут предложить очереди с ценой по требованию, но это не всегда возможно.
Именно здесь в игру вступает qStash — новый сервис очередей от Upstash. Это бессерверная очередь, в которой вы платите только за то, что используете. Она поддерживает доставку на одну или несколько конечных точек HTTP, дедупликацию на основе идентификаторов или хэша контента, а также доставку по расписанию.
В этой статье мы проверим, на что способен qStash, создав на его основе планировщик электронной почты. В качестве облачного провайдера в этом учебнике будет выбран Vercel. Итак, поехали!
Предварительные условия
Чтобы следовать этому руководству, вам понадобятся учетные записи для трех сервисов:
- GitHub
- Upstash
- [Vercel(https://vercel.com/signup)
Настройка приложения Next.js
Первым шагом будет создание проекта Next.js. Для этого выполните следующую команду:
$ npx create-next-app@latest
Затем перейдите в папку нового проекта.
Установка зависимостей
Хотя сервис qStash используется через HTTP API, пакет TypeScript делает работу с ним более доступной. Для отправки писем вы будете использовать пакет nodemailer. Установите их с помощью NPM:
$ npm i @upstash/qstash nodemailer
Создание маршрута API расписания
Next.js поставляется с превосходной интеграцией для функций Vercel. Создание маршрута API будет автоматически выполняться внутри бессерверной функции Vercel без дополнительных изменений кода. Для этого создайте новый файл JavaScript по адресу pages/api/schedule.js
со следующим содержимым:
import { Client } from "@upstash/qstash"
const qstashClient = new Client({
token: process.env.QSTASH_TOKEN
})
export default async function handler(request, response) {
if (request.method !== "POST")
return response.status(404).end()
const qstashResponse = await qstashClient.publishJSON({
url: `https://${request.headers.host}/api/notify`,
body: request.body,
notBefore: request.query.timestamp,
})
response.status(201).send(qstashResponse)
}
Сначала вы инициализируете клиент qStash с помощью токена из Upstash. Лучшая практика предлагает поместить токен в переменные окружения, которые зашифрованы в Vercel. (Вы установите эти переменные позже, когда закончите часть кода).
Далее идет собственно функция handler
. Она проверяет, что функция была вызвана через метод POST
, и приступает к извлечению содержимого из запроса, чтобы использовать его в qStash.
qStash использует поле url
в качестве цели для запланированного сообщения. Мы хотим, чтобы оно вызывало другой маршрут API из нашего приложения Next.js, но домен может меняться между развертываниями Vercel; мы будем использовать поле заголовка Host, чтобы получить правильный URL.
Поле body
— это просто то, что содержит наш API-запрос в своем теле.
Поле notBefore
принимает временную метку Unix в качестве даты, когда мы хотим отправить письмо.
Чтобы связать все вместе, пользователь отправляет запрос с текстовым телом и параметром запроса timestamp в наш API-маршрут, а функция Vercel передает его в qStash.
Создание маршрута API Notify
Теперь, когда мы получили наши сообщения, запланированные в qStash, нам нужен маршрут для преобразования их в электронные письма и их рассылки. Для этого создайте файл по адресу pages/api/notify.js
, который будет содержать:
import nodemailer from "nodemailer"
import { verifySignature } from "@upstash/qstash/nextjs"
export const config = {
api: { bodyParser: false },
}
export default verifySignature(handler, {
currentSigningKey: process.env.QSTASH_CURRENT_SIGNING_KEY,
nextSigningKey: process.env.QSTASH_NEXT_SIGNING_KEY,
})
async function handler(request, response) {
const emailAccount = await nodemailer.createTestAccount()
const transport = nodemailer.createTransport({
host: "smtp.ethereal.email",
auth: emailAccount,
})
await transport.sendMail({
from: '"qStash" <qstash@upstash.com>',
to: "jane.doe@example.com",
subject: "Notification from qStash",
text: request.body,
})
response.send()
}
Сначала мы экспортируем объект config
, чтобы сообщить Next.js, что он не должен разбирать тело. Next.js разбирает тело по умолчанию, но для проверки подписи запроса qStash нам нужно сырое/неразобранное тело.
Служба qStash подписывает все запросы, чтобы гарантировать, что вы обрабатываете только действительные сообщения. Промежуточному ПО нужны ключи подписи из Upstash. Опять же, мы предполагаем, что они будут находиться в переменных окружения.
Функция обработчика создает тестовый аккаунт на ethereal.email, простой тестовый сервис для nodemailer, и пытается отправить с него письмо. В своем собственном приложении вы можете заменить этот сервис на почтовый сервис по вашему выбору.
Отправка кода на GitHub
Vercel будет собирать и развертывать ваше приложение каждый раз, когда вы будете отправлять новый коммит на GitHub, но для этого оно должно быть сначала размещено на GitHub. Создание репозиториев GitHub и размещение в них кода выходит за рамки данной статьи, но в Интернете можно найти хорошие объяснения.
Создание проекта Vercel
Вам нужно создать новый проект на Vercel, импортировав репозиторий GitHub из предыдущего шага.
При создании проекта не забудьте внести учетные данные qStash в нужные переменные окружения. На рисунке 1 показано, где их можно найти в Upstash Console.
Напоминаем, что переменные должны иметь следующие имена:
QSTASH_TOKEN
QSTASH_CURRENT_SIGNING_KEY
QSTASH_NEXT_SIGNING_KEY
После создания проекта Vercel загрузит последнюю версию с GitHub, соберет ваше приложение и развернет его на своей инфраструктуре.
Тестирование приложения
Чтобы протестировать приложение, вы должны получить правильный домен от Vercel после завершения развертывания. На рисунке 2 показано, где его можно найти.
Чтобы отправить запрос к вашему приложению, вы можете использовать инструмент cURL CLI:
$ curl -X POST
-H "Content-Type: text/plain"
-d "Hello!"
"https://<APP_DOMAIN>.vercel.app/api/schedule?timestamp=<TIMESTAMP>"
Замените APP_DOMAIN и TIMESTAMP соответствующим образом.
Вы можете проверить доставку вашего сообщения в Upstash Console, как показано на рисунке 3.
Резюме
Бессерверная разработка приложений — это склеивание сервисов вместе. Либо вы позволяете своим функциям напрямую вызывать другие функции, либо вам нужно поместить между ними другой сервис.
Новый сервис бессерверной очереди Upstash приходит на помощь с простым интерфейсом и платной ценой.
Он на 100% построен на безэталонных HTTP-запросах и предназначен для:
- Бессерверных функций (AWS Lambda …)
- Cloudflare Workers
- Fastly Compute@Edge
- Next.js, включая edge
- Deno
- Клиентские веб-/мобильные приложения
- WebAssembly
- другие среды, где HTTP предпочтительнее TCP.
Я вызвал у вас интерес?
Попробуйте; первые 50 запросов в день — за счет заведения!