[Программирование, Symfony] Развертывание приложения Symfony в AWS Lambda (перевод)

Автор Сообщение
news_bot ®

Стаж: 6 лет 2 месяца
Сообщений: 27286

Создавать темы news_bot ® написал(а)
12-Июн-2021 02:35


Сначала давайте разберемся, что такое бессерверная архитектура и когда она нужна.Бессерверная архитектура позволяет выполнять фрагменты кода без мороки с инфраструктурой: в этом случае управлением веб-сервером, физическим оборудованием и администрированием занимается облачный провайдер, позволяя вам сосредоточиться исключительно на коде.AWS Lambda обеспечивает высокую доступность, причем плата взимается только за фактически затрачиваемое время вычислений. Этот сервис может быть весьма полезен для таких задач, как запуск cron-заданий, отправка уведомлений в режиме реального времени, предоставление доступа к API, обработка каких-нибудь событий при выполнении различных операций и т. д. В сети можно найти массу примеров использования сервиса.Наш сценарий использования Предоставить доступ к API, созданному с помощью Symfony, который публикует сообщения в LinkedIn. Процесс разработки будет включать этапы от написания до развертывания кода.Пишем код В Symfony 5-й версии появился новый компонент под названием Notifier, который дает возможность отправлять уведомления через разные сервисы (Slack, Twitter, Twilio и др.).В Symfony нет встроенной поддержки LinkedIn, поэтому несколько месяцев назад я создал поверх Notifier шлюз для публикации контента в этой социальной сети. Исходный код шлюза можно посмотреть по ссылке, его же мы будем использовать и в этой демонстрации.Приступаем
$ symfony new --full aws-lambda-linkedin-notifier
$ cd aws-lambda-linkedin-notifier
$ composer require eniams/linkedin-notifier
Включаем шлюз (см. документацию)
<?php
// config/bundles.php
return [
// others bundles,
Eniams\Notifier\LinkedIn\LinkedInNotifierBundle::class => ['all' => true]];
// .env
LINKEDIN_DSN=
Логика публикации контента
<?php
class PostContentController
{
    /**
     * @Route("/contents", name="post_content", methods="POST")
     */
    public function __invoke(NotifierInterface $notifier, Request $request)
    {
        if(null !== $message = (\json_decode($request->getContent(), true)['message'] ?? null)) {
            $notifier->send(new Notification($message, ['chat/linkedin']));
            return new JsonResponse('message posted with success', 201);
        }
        throw new BadRequestException('Missing "message" in body');
    }
}
Логика проста: мы предоставляем доступ к API через маршрут /contents, который принимает запрос POST с сообщением message в его теле.В 11-й строке мы отправляем публикуемое сообщение в LinkedIn — благодаря Symfony и шлюзу это делается очень просто!Будучи профессиональными разработчиками, покроем этот код автотестами:
<?php
class PostContentControllerTest extends WebTestCase
    /**
     * @dataProvider methodProvider
     */
    public function testANoPostRequestShouldReturnA405(string $method)
    {
        $client = static::createClient();
        $client->request($method, '/contents');
        self::assertEquals(405, $client->getResponse()->getStatusCode());
    }
    public function testAPostRequestWithoutAMessageInBodyShouldReturnA400()
    {
        $client = static::createClient();
        $client->request('POST', '/contents');
        self::assertEquals(400, $client->getResponse()->getStatusCode());
    }
    public function testAPostRequestWithAMessageInBodyShouldReturnA201()
    {
        $request = new Request([],[],[],[],[],[], json_encode(['message' => 'Hello World']));
        $notifier = new class implements NotifierInterface {
            public function send(Notification $notification, Recipient ...$recipients): void
            {
            }
        };
        $controller = new PostContentController();
        $response = $controller->__invoke($notifier, $request);
        self::assertEquals(201, $response->getStatusCode());
    }
    public function methodProvider()
    {
        return [
            ['GET'],
            ['PUT'],
            ['DELETE'],
        ];
    }
view rawTestPostContentController.php hosted with ​ by GitHub
Код готов! Пришло время его развернуть Стоп! Что?! AWS Lambda не поддерживает PHP!Именно так: AWS Lambda поддерживает не все языки программирования, а только некоторые, в том числе Go, Java, Python, Ruby, NodeJS и .NET.Теперь надо учить новый язык и переписывать код? Надеюсь, нет!Ничего переписывать не придется благодаря Матье Напполи (Matthieu Nappoli), создателю Bref.sh, и замечательной команде, помогающей ему поддерживать этот проект с открытым исходным кодом. Bref позволяет развертывать PHP-приложения в AWS и запускать их на AWS Lambda.Конфигурация развертыванияДобавим в kernel.php обработку логов:
<?php
    // Kernel.php
    public function getLogDir(): string
    {
        if (getenv('LAMBDA_TASK_ROOT') !== false) {
            return '/tmp/log/';
        }
        return parent::getLogDir();
    }
    public function getCacheDir()
    {
        if (getenv('LAMBDA_TASK_ROOT') !== false) {
            return '/tmp/cache/'.$this->environment;
        }
        return parent::getCacheDir();
    }
Подготовим фреймворк Serverless (см. документацию):
$ npm install -g serverless
$ serverless config credentials --provider aws --key  --secret
$ composer require bref/bref
Зададим конфигурацию в файле serverless.yaml:
service: notifier-linkedin-api
provider:
    name: aws
    region: eu-west-3
    runtime: provided
    environment: # env vars
        APP_ENV: prod
        LINKEDIN_DSN: YOUR_DSN
plugins:
    - ./vendor/bref/bref
functions:
    website:
        handler: public/index.php # bootstrap
        layers:
            - ${bref:layer.php-73-fpm} # https://bref.sh/docs/runtimes/index.html#usage
        timeout: 28 # Timeout to stop the compute time
        events:
            - http: 'POST /contents' # Only POST to /contents are allowed
package:
    exclude:
        - 'tests/**'
view rawserverless.yaml hosted with ​ by GitHub
Развертываем!
$ serverless deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service notifier-linkedin-api.zip file to S3 (10.05 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
....................
Serverless: Stack update finished...
Service Information
service: notifier-linkedin-api
stage: dev
region: eu-west-3
stack: notifier-linkedin-api-dev
resources: 15
api keys:
  None
endpoints:
  POST - https://xxx.execute-api.eu-west-3.amazonaws.com/dev/contents
functions:
  website: notifier-linkedin-api-dev-website
layers:
  None
Serverless: Removing old service artifacts from S3...
Serverless: Run the "serverless" command to setup monitoring, troubleshooting and testing.
Теперь наш код развернут в AWS Lambda, а API доступен по адресу https://xxx.execute-api.eu-west-3.amazonaws.com/dev/contents.Попробуем:
Перевод материала подготовлен в рамках курса "Symfony Framework". Если интересно узнать о курсе больше, приглашаем на день открытых дверей онлайн, где преподаватель расскажет о формате и программе обучения.

===========
Источник:
habr.com
===========

===========
Автор оригинала: Smaine Milianni
===========
Похожие новости: Теги для поиска: #_programmirovanie (Программирование), #_symfony, #_symfony_framework, #_aws_lambda, #_serverless, #_solution_architect, #_php, #_blog_kompanii_otus (
Блог компании OTUS
)
, #_programmirovanie (
Программирование
)
, #_symfony
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 27-Апр 20:54
Часовой пояс: UTC + 5