При разработке теста задержки для бессерверных баз данных (DynamoDB, FaunaDB, Upstash) я хотел, чтобы был API, где я буду записывать цифры задержки и получать гистограмму. В этом уроке я создам такой API, в котором вы сможете записывать значения задержки из любого приложения. Это будет бессерверный REST API со следующими методами:
- запись: записывает числовые значения в гистограмму.
- get: возвращает объект гистограммы.
Мотивация
Я покажу, как легко разработать общий API с помощью AWS Lambda и Serverless Redis.
Step-1:
Создайте базу данных Redis (Upstash)
Создайте базу данных, как указано в разделе Начало работы.
Step-2:
Настройка бессерверного проекта
Если у вас его еще нет, установите бессерверную структуру через:
npm install -g serverless
В любой папке запустите serverless
, как показано ниже:
>> serverless Serverless: No project detected. Do you want to create a new one? Yes Serverless: What do you want to make? AWS Node.js Serverless: What do you want to call this project? histogram-api Project successfully created in 'histogram-api' folder. You can monitor, troubleshoot, and test your new service with a free Serverless account. Serverless: Would you like to enable this? No You can run the “serverless” command again if you change your mind later.
Внутри папки проекта создайте проект узла с помощью команды:
npm init
Затем установите клиент Redis и библиотеку гистограмм с помощью:
npm install ioredis npm install hdr-histogram-js
Обновите serverless.yml
, как показано ниже. Скопируйте URL-адрес Redis из консоли и замените ниже:
service: histogram-api frameworkVersion: '2' provider: name: aws runtime: nodejs12.x lambdaHashingVersion: 20201221 environment: REDIS_URL: REPLACE_YOUR_URL_HERE functions: record: handler: handler.record events: - httpApi: path: /record method: post cors: true get: handler: handler.get events: - httpApi: path: /get method: get cors: true
Шаг 3: Код
Отредактируйте handler.js, как показано ниже:
const hdr = require("hdr-histogram-js"); const Redis = require("ioredis"); if (typeof client === 'undefined') { var client = new Redis(fixUrl(process.env.REDIS_URL)); } const headers = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': true, }; const SIZE = 10000; module.exports.get = async (event) => { if (!event.queryStringParameters || !event.queryStringParameters.name) { return { statusCode: 400, headers: headers, body: JSON.stringify( { message: 'Invalid parameters. Name is needed.', } ), }; } const name = event.queryStringParameters.name; const data = await client.lrange(name, 0, SIZE); const histogram = hdr.build(); data.forEach(item => { histogram.recordValue(item); }) return { statusCode: 200, body: JSON.stringify( { histogram: histogram } ), }; }; module.exports.record = async (event) => { let body = JSON.parse(event.body) if (!body || !body.name || !body.values) { return { statusCode: 400, headers: headers, body: JSON.stringify( { message: 'Invalid parameters. Name and values are needed.', } ), }; } const name = body.name; const values = body.values; await client.lpush(name, values) return { statusCode: 200, body: JSON.stringify( { message: 'Success', name: name } ), }; }; function fixUrl(url) { if (!url) { return '' } if (url.startsWith('redis://') && !url.startsWith('redis://:')) { return url.replace('redis://', 'redis://:') } if (url.startsWith('rediss://') && !url.startsWith('rediss://:')) { return url.replace('rediss://', 'rediss://:') } return url }
У нас есть две бессерверные функции выше. get
принимает name
в качестве параметра и загружает список из Redis. Затем строит гистограмму, используя значения в списке.
Функция record
принимает name
и values
в качестве параметров. Он добавляет values
в список Redis с именем name
.
Функция get
вычисляет гистограмму по последним 10000 записям задержки. Обновите параметр SIZE, чтобы изменить это число.
fixUrl
— это вспомогательный метод, который исправляет формат URL-адреса Redis.
Шаг 4. Разверните свои функции
Разверните свои функции с помощью:
serverless deploy
Команда развернет две функции и выведет две конечные точки. Попробуйте конечные точки с настройкой параметров, как показано ниже:
Запишите значения задержки в perf-test-1
:
curl --header "Content-Type: application/json" -d "{\"name\":\"perf-test-1\", \"values\": [90,80,34,97,93,45,49,57,99,12]}" https://v7xx4aa2ib.execute-api.us-east-1.amazonaws.com/record
Получите гистограмму для perf-test-1
:
curl https://v7xx4aa2ib.execute-api.us-east-1.amazonaws.com/get?name=perf-test-1
Дозирование
Каждый раз вызывать удаленную функцию для расчета задержки может быть дорого. В вашем приложении вы должны хранить массив или очередь в качестве буфера для значений задержки, а затем отправлять их пакетами в API, когда массив достигает размера пакета. Что-то вроде ниже:
Первоначально опубликовано на https://docs.upstash.com.