runtime / bref
Bref运行时
Requires
- php: >=8.0.5
- ext-json: *
- ext-sockets: *
- clue/arguments: ^2.1
- psr/http-server-handler: ^1.0
- riverline/multipart-parser: ^2.0.9
- runtime/bref-layer: ^1.3
- symfony/runtime: ^5.4 || ^6.0 || ^7.0
Requires (Dev)
- bref/bref: ^1.3
- guzzlehttp/test-server: ^0.1
- phpunit/phpunit: ^9.5
- symfony/http-foundation: ^5.4 || ^6.0 || ^7.0
- symfony/http-kernel: ^5.4 || ^6.0 || ^7.0
README
使用Bref在AWS Lambda上部署应用程序。
我们支持所有类型的应用程序。有关详细信息,请参阅以下部分。
如果您是Symfony Runtime组件的新手,请阅读主README中的更多内容。
安装
composer require runtime/bref
要开始,我们需要在项目根目录中有一个serverless.yml
文件。我们还将使用./vendor/runtime/bref-layer
插件。现在我们可以告诉AWS我们想要使用名为${runtime-bref:php-80}
的“层”来运行我们的应用程序。
接下来,我们需要定义环境变量APP_RUNTIME
,以便Runtime组件知道要使用哪个运行时。
# serverless.yml service: my-app-name plugins: - ./vendor/runtime/bref-layer # <----- Add the extra Serverless plugin provider: name: aws region: eu-central-1 runtime: provided.al2 memorySize: 1792 environment: APP_ENV: prod APP_RUNTIME: Runtime\Bref\Runtime BREF_LOOP_MAX: 100 # Optional functions: website: handler: public/index.php layers: - ${runtime-bref:php-80} events: # Specify that we want HTTP requests - httpApi: '*'
这就是全部内容!
我们使用此文件来支持各种应用程序。我们唯一在events
中更改的事情是,假设我们想监听S3或新SQS消息的更改。或者,我们可以让此函数由系统中的另一个应用程序使用Bref\Event\Handler
来调用。
Symfony应用程序
如果您需要Bref的一些额外功能,请使用以下命令安装:
composer req bref/bref
使用标准的Symfony 5.3+ public/index.php
。
// public/index.php use App\Kernel; require_once dirname(__DIR__).'/vendor/autoload_runtime.php'; return function (array $context) { return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']); };
您不需要做任何特殊的事情。
这里有一个示例应用程序。使用此运行时,您可以在本地开发和生产中使用完全相同的应用程序。
Laravel应用程序
如果您需要Bref的一些额外功能,请使用以下命令安装:
composer req bref/bref
要运行Laravel应用程序,您需要更新您的入口控制器,使其看起来像这样
// public/index.php use Illuminate\Contracts\Http\Kernel; define('LARAVEL_START', microtime(true)); require_once dirname(__DIR__).'/vendor/autoload_runtime.php'; return function (): Kernel { static $app; if (null === $app) { $app = require dirname(__DIR__).'/bootstrap/app.php'; } return $app->make(Kernel::class); };
现在您已经在AWS Lambda上启动并运行了!
有关如何在本地运行此应用程序的信息,请参阅runtime/laravel
。
PSR-15应用程序
如果您需要Bref的一些额外功能,请使用以下命令安装:
composer req bref/bref
Bref使用nyholm/psr7
来提供PSR-7和PSR-15体验。有关如何在本地运行您的应用程序的信息,请参阅runtime/psr-nyholm
。
以下代码是一个使用Runtime组件的PSR-15应用程序示例。如果它在本地工作,它将在AWS Lambda上工作。
// public/index.php use Nyholm\Psr7\Response; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; require_once dirname(__DIR__).'/vendor/autoload_runtime.php'; return function () { return new class implements RequestHandlerInterface { public function handle(ServerRequestInterface $request): ResponseInterface { $name = $request->getQueryParams()['name'] ?? 'world'; return new Response(200, [], "Hello $name"); } }; };
控制台应用程序
使用标准的Symfony 5.3+ bin/console
。
// bin/console use App\Kernel; use Symfony\Bundle\FrameworkBundle\Console\Application; require_once dirname(__DIR__).'/vendor/autoload_runtime.php'; return function (array $context) { $kernel = new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']); return new Application($kernel); };
# serverless.yml # ... functions: console: handler: bin/console timeout: 120 layers: - ${runtime-bref:php-80} events: - schedule: rate: rate(30 minutes) input: '"app:invoice:send"'
PSR-11容器
PSR-11容器很棒。它在内部微服务中特别出色,在这些微服务中,您不需要处理HTTP或安全性。应用程序只需使用AWS Lambda API客户端(例如aws/aws-sdk-php
或async-aws/lambda
)调用微服务。它对于响应S3或SQS事件也非常出色。
我们首先需要的是一个返回PSR-11容器的文件。下面是Symfony的一个示例。
// bin/container.php use App\Kernel; require_once dirname(__DIR__).'/vendor/autoload_runtime.php'; return function (array $context) { $kernel = new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']); $kernel->boot(); return $kernel->getContainer(); };
现在我们编写一个实现Bref\Event\Handler
的类/服务。
namespace App\Lambda; use Bref\Context\Context; use Bref\Event\Handler; class HelloWorld implements Handler { public function handle($event, Context $context) { return 'Hello ' . $event['name']; } }
现在我们需要更新serverless.yml,以表示“使用bin/container.php获取容器,然后加载服务App\Lambda\HelloWorld”。
# serverless.yml # ... functions: hello: handler: bin/container.php:App\Lambda\HelloWorld layers: - ${runtime-bref:php-80}
当部署时,可以通过以下方式调用
serverless invoke --function hello --data '{"name":"Tobias"}'
本地调用处理程序
从容器中使用服务可以使处理程序非常容易进行单元测试。但是,如果您很懒,您可能希望从CLI本地调用它们。
运行以下命令以调用App\Lambda\HelloWorld
服务。
./vendor/bin/bref-local-handler.php ./bin/container.php:App\\Lambda\\HelloWorld
如果您的服务期望某些事件数据,请将其作为JSON字符串或包含JSON的文件的路径添加。
./vendor/bin/bref-local-handler.php ./bin/container.php:App\\Lambda\\HelloWorld '{"foo":"bar"}'
./vendor/bin/bref-local-handler.php ./bin/container.php:App\\Lambda\\HelloWorld example/input.json
简化serverless.yml
语法 handler: bin/container.php:App\Lambda\HelloWorld
可能有点难写,但你可以添加一个名为 FALLBACK_CONTAINER_FILE
的环境变量,其中包含我们可以获取PSR-11容器的文件。这可能有助于serverless.yml文件更加自然地读取。
# serverless.yml provider: name: aws runtime: provided.al2 # ... environment: APP_ENV: prod APP_RUNTIME: Runtime\Bref\Runtime + FALLBACK_CONTAINER_FILE: bin/container.php BREF_LOOP_MAX: 100 # Optional functions: hello: - handler: bin/container.php:App\Lambda\HelloWorld + handler: App\Lambda\HelloWorld layers: - ${runtime-bref:php-80}
类型化处理程序
为了更好地与不同的AWS事件集成,可以使用“类型化处理器”。这些是实现 Bref\Event\Handler
并提供一些辅助方法或类的类。
要使用它们,您需要安装Bref。
composer req bref/bref
我们使用与上面相同的PSR-11配置,并编写自定义处理器,如下所示:
namespace App\Lambda; use Bref\Context\Context; use Bref\Event\S3\S3Event; use Bref\Event\S3\S3Handler; class S3FileCreated extends S3Handler { public function handleS3(S3Event $event, Context $context): void { $bucketName = $event->getRecords()[0]->getBucket()->getName(); $fileName = $event->getRecords()[0]->getObject()->getKey(); // do something with the file } }
# serverless.yml # ... functions: s3_photos: handler: bin/container.php:App\Lambda\S3FileCreated layers: - ${runtime-bref:php-80} events: - s3: bucket: photos event: s3:ObjectCreated:*
有关不同类型处理器的更多信息,请参阅Bref文档。
Symfony Messenger集成
类似于上面的类型化处理器,如果您使用bref/symfony-messenger
,您可能还需要定义一个工作函数。
# serverless.yml # ... functions: worker: handler: bin/container.php:Bref\Symfony\Messenger\Service\Sqs\SqsConsumer timeout: 120 layers: - ${runtime-bref:php-80} events: - sqs: batchSize: 1 # Only 1 item at a time to simplify error handling arn: !GetAtt workqueue.Arn resources: Resources: workqueue: Type: "AWS::SQS::Queue" Properties: QueueName: ${self:service}-workqueue VisibilityTimeout: 600