Продолжая тему нарезки картинок при помощи бессерверных решений, хочу предложить вашему вниманию дополнение в виде бессерверного frontend и backend.
AWS S3 предлагает возможность загружать картинки напрямую в S3 из приложения. Архитектурно это выглядит вот так:
Я же предлагаю реализовать Frontend, Backend, а также нарезку картинок, описанную в этой статье более подробно, при помощи бессерверное решений. Итак, полная архитектура будет выглядеть вот так:
Для реализации этого для начала напишем простой backend, который будет создавать подписанную ссылку на загрузку картинок:
const {S3Client, PutObjectCommand} = require('@aws-sdk/client-s3'); const {v4} = require("uuid"); const s3 = new S3Client({ signatureVersion: 'v4', region: config.REGION }); const S3PutObjectCommand = (Key) => { return new PutObjectCommand({ ACL: 'public-read', Bucket: config.S3_BUCKET, Key, }); } const getS3SignedUrl = (name) => { const command = S3PutObjectCommand(name) return getSignedUrl(s3, command, {expiresIn: 600}) } const getFileName = (key) => `${key}.jpg`; const generateFileKey = () => { return v4() } module.exports.handler = async () => { const key = generateFileKey() const fileName = getFileName(key) const url = await getS3SignedUrl(fileName); return { statusCode: 200, // заголовки для CORS. // В реальном приложении их нужно поправить так, // чтоб загрузка была разрешена только с определенных хостов headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': true, }, body: JSON.stringify({key, url, fileName}) }; }
Обернем этот код в Lambda и ApiGateway при помощи Serverless Framework.
service: service-simple-serverless-back frameworkVersion: '2 || 3' app: simple-serverless-back package: patterns: - '!node_modules/aws-sdk' - '!node_modules/serverless' - '!node_modules/@serverless' - '!.idea' - '!images' - '!yarn.lock' - '!yarn.error.log' - '!README.md' - '!.gitignore' - '!package.json' - '!.git' custom: name: 'simple-serverless-back' environment: 'prod' region: 'us-east-1' # зададим бакет в который мы будем загружать файлы, # его также можно пробросить через переменные окружения bucket: 'service-lambda-thumb-tifig-d-sourcebucketdc914398-10oo755kbh9e8' lambda_prefix: ${self:custom.environment}-${self:custom.name} provider: name: aws lambdaHashingVersion: '20201221' environment: S3_BUCKET: ${self:custom.bucket} REGION: ${self:custom.region} region: ${self:custom.region} runtime: nodejs14.x iamRoleStatements: - Effect: Allow Action: - s3:PutObject - s3:PutObjectAcl - s3:GetObject Resource: - 'arn:aws:s3:::${self:custom.bucket}' - 'arn:aws:s3:::${self:custom.bucket}/*' functions: getS3SignedUrl: name: get-s3-signed-url handler: index.handler events: - http: method: GET path: / cors: true
Делаем sls deploy
и получаем вот такую лямбду:
Напишем простой Frontend, который берет подписанную ссылку по запросу на backend и загружает выбранный файл в с3. Создадим новое React приложение:
npx create-react-app app
Код загрузки файла:
import React, {useCallback} from 'react'; import {getSignedUrlApi, uploadToS3Api} from '../utils/api'; export const Upload = ({onSetUploadImages}) => { const onChange = useCallback(async (e) => { let files = e.target.files // берем подписанную ссылку const signedUrlResults = await getSignedUrlApi() const {url, fileName} = signedUrlResults // загружаем файл в S3 await uploadToS3Api(url, files[0]) onSetUploadImages(fileName) }, [onSetUploadImages]) return ( <div className="upload"> <div> <input type="file" onChange={onChange} /> </div> </div> ); }
Весь код приложения доступен в репозитории
Также завернем это все через Serverless Framework в статически S3 сайт при помощи супер короткого конфига:
service: service provider: name: aws plugins: - serverless-lift constructs: front: type: static-website path: 'build'
Делаем yarn build
и sls deploy
. Попробуем загрузить картинку и посмотреть на результат:
В итоге мы получили полностью бессерверное решение backend+frontend+image convertor. Давайте рассмотрим сколько будет стоит обслуживать такой проект:
Уровень бесплатного пользования AWS Lambda включает 1 млн бесплатных запросов в месяц и 400 000 ГБ-секунд вычислений в месяц
Уровень бесплатного использования API Gateway включает один миллион вызовов API HTTP, один миллион вызовов API REST, один миллион сообщений и 750 000 минут подключения в месяц на протяжении до 12 месяцев.
Новые клиенты AWS ежемесячно получают 5 ГБ хранилища Amazon S3 класса S3 Standard, 20 000 запросов GET, 2000 запросов PUT, COPY, POST, или LIST, а также 100 ГБ исходящего трафика.
Всегда бесплатно 1 ТБ исходящих данных 10 000 000 запросов HTTP или HTTPS 2 000 000 вызовов CloudFront Function
Итак, видно, что при умеренном использовании это все практически бесплатно (что подходит для большинства админ панелей и слабо нагруженных проектов).
Весь код доступен в публичных репозиториях simple-serverless-front, simple-serverless-back, lambda-ffmpeg-tifig
ссылка на оригинал статьи https://habr.com/ru/post/648847/
Добавить комментарий