stackkit/laravel-google-cloud-scheduler

v3.0.1 2024-03-27 21:47 UTC

README

Build Status Latest Stable Version Downloads

配套包: Cloud TasksCloud Logging

简介

此包允许您使用 Google Cloud Scheduler 来安排 Laravel 命令。

工作原理

云调度器将向您的应用程序发出 HTTP 请求。此包为您的应用程序添加了一个端点,该端点接受这些 HTTP 请求及其有效负载(Artisan 命令)并执行它们。

使用此包安排命令有两种方式

1. 安排 `schedule:run` 命令

这是使用此包的最简单方法。您可以安排 schedule:run 命令每分钟运行一次。

2. 分别安排命令

如果您的应用程序没有每分钟运行的命令,您可以选择单独安排它们。

如果命令使用 withoutOverlappingbeforeafteronSuccessthenPing 等,只要命令也安排在控制台内核中,此包将尊重这些设置。

例如,假设我们必须每天凌晨 3:00 生成报告。我们可以使用云调度器安排 reports:generate 命令在凌晨 3:00 运行。在报告生成后,应该ping OhDear。

首先,在云任务中安排命令

然后,在控制台内核中安排命令

public function schedule(Schedule $schedule)
{
    $schedule->command('report:generate')
        ->thenPing('https://ohdear.app/ping');
}

该包将自动获取已安排的设置,并在命令运行后ping OhDear。

要求

此包需要 Laravel 10 或 11。

安装

1 - 使用 Composer 需求包

composer require stackkit/laravel-google-cloud-scheduler

2 - 定义环境变量

CLOUD_SCHEDULER_APP_URL - 这应该是您 Cloud Scheduler 作业 URL 字段中定义的 URL。

CLOUD_SCHEDULER_SERVICE_ACCOUNT - 调用任务的服务的电子邮件地址。

可选,但建议发布配置文件

php artisan vendor:publish --tag=cloud-scheduler-config

3 - 确保 PHP 可执行文件在 open_basedir 中。这对于包运行 Artisan 命令是必需的。

如何找到可执行文件

php artisan tinker --execute="(new Symfony\\Component\\Process\\PhpExecutableFinder())->find()"

4 - 可选,但强烈建议:服务器配置

由于 Artisan 命令现在通过 HTTP 请求调用,您可能会遇到超时问题。以下是如何调整它们

server {
    # other server configuration ...

    location /cloud-scheduler-job {
        proxy_connect_timeout 600s;
        proxy_read_timeout 600s;
        fastcgi_read_timeout 600s;
    }

    # other locations and server configuration ...
}

5 - 可选,但强烈建议:设置应用程序 RUNNING_IN_CONSOLE

一些 Laravel 服务提供者仅在应用程序通过命令行(Artisan)访问时注册它们的命令。由于我们从 HTTP 调用中调用 Laravel 调度器,这意味着某些命令可能永远不会注册,例如 Laravel Scout 命令。

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    if ($this->app->runningInConsole()) {
        $this->commands([
            FlushCommand::class,
            ImportCommand::class,
            IndexCommand::class,
            DeleteIndexCommand::class,
        ]);

        $this->publishes([
            __DIR__.'/../config/scout.php' => $this->app['path.config'].DIRECTORY_SEPARATOR.'scout.php',
        ]);
    }
}

为了绕过此问题,请将以下内容添加到 bootstrap/app.php

Laravel 11
<?php

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

+ if (($_SERVER['REQUEST_URI'] ?? '') === '/cloud-scheduler-job') {
+     $_ENV['APP_RUNNING_IN_CONSOLE'] = true;
+ }

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        //
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();
Laravel 10
<?php

/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| The first thing we will do is create a new Laravel application instance
| which serves as the "glue" for all the components of Laravel, and is
| the IoC container for the system binding all of the various parts.
|
*/

$app = new Illuminate\Foundation\Application(
    $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);

+ if (($_SERVER['REQUEST_URI'] ?? '') === '/cloud-scheduler-job') {
+     $_ENV['APP_RUNNING_IN_CONSOLE'] = true;
+ }

6 - 可选:为维护模式白名单路由

如果您想允许作业在应用程序关闭时(php artisan down)继续运行,更新以下内容

Laravel 11
return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__ . '/../routes/web.php',
        commands: __DIR__ . '/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->preventRequestsDuringMaintenance(
            except: [
                '/cloud-scheduler-job',
            ],
        );
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();
Laravel 10
<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;

class PreventRequestsDuringMaintenance extends Middleware
{
    /**
     * The URIs that should be reachable while maintenance mode is enabled.
     *
     * @var array
     */
    protected $except = [
+        '/cloud-scheduler-job',
    ];
}

云调度器示例

以下是一个示例作业,将每分钟运行 php artisan schedule:run

以下是最重要的设置

  • 目标必须是 HTTP
  • URL 和 AUD(受众)必须是 https://yourdomainname.com/cloud-scheduler-job
  • 认证头必须是 OIDC 令牌!

安全

作业处理器要求每个请求都必须有一个 OpenID 令牌。Cloud Scheduler 将生成一个 OpenID 令牌,并将其与作业负载一起发送到处理器。

此包验证令牌是由 Google 数字签名的,并且是针对您的应用程序的。只有 Google Scheduler 才能调用您的处理器。

关于 OpenID Connect 的更多信息

https://developers.google.com/identity/protocols/oauth2/openid-connect