僅在生產環境中使用Redis進行限流的Laravel實踐
P粉541565322
P粉541565322 2024-01-10 17:54:47
0
1
415

背景

預設情況下,Laravel提供了兩個中間件用於速率限制(節流):

\Illuminate\Routing\Middleware\ThrottleRequests::class
\Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class

如文件所述,如果您使用Redis作為快取驅動程序,您可以在Kernel.php中更改映射,如下所示:

/**
 * 应用程序的中间件别名。
 *
 * 别名可用于将中间件方便地分配给路由和组,而不是使用类名。
 *
 * @var array<string, class-string|string>
 */
protected $middlewareAliases = [
    // ...
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class
    // ...
];

問題

問題在於上述內容不是動態的,而是依賴環境。例如,在我的stagingproduction環境中,我使用Redis,但在我的localdevelopment環境中,我不使用Redis。

可能的解決方案

有一個明顯的髒解決方案,類似於這樣(Kernel.php):

/**
 * 应用程序的中间件别名。
 *
 * 别名可用于将中间件方便地分配给路由和组,而不是使用类名。
 *
 * @var array<string, class-string|string>
 */
protected $middlewareAliases = [
    // ...
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class
    // ...
];

/**
 * 创建一个新的HTTP内核实例。
 *
 * @param  \Illuminate\Contracts\Foundation\Application  $app
 * @param  \Illuminate\Routing\Router  $router
 * @return void
 */
public function __construct(Application $app, Router $router)
{
    if ($app->environment('production')) {
        $this->middlewareAliases['throttle'] = \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class;
    }

    parent::__construct($app, $router);
}

是否有一種「標準」方法可以在不重寫Kernel建構子的情況下實現這一點?基本上,我希望我的應用程式可以根據環境是否設定為production(或預設快取儲存設定為redis)動態選擇相關的中間件。

更新

上述解決方案不起作用,因為在引導應用程式之前訪問內核,因此此時環境不可用。我現在正在研究的另一種解決方案是擴展基本的ThrottleRequests類,以便動態調用相關的類別。

P粉541565322
P粉541565322

全部回覆(1)
P粉043432210

經過大量的研究和測試,我得出的結論是在RouteServiceProvider中動態設定throttle中間件是最好的解決方案,程式碼如下:

class RouteServiceProvider extends ServiceProvider
{
    /**
     * 启动任何应用程序服务。
     *
     * @return void
     */
    public function boot(): void
    {
        $this->registerThrottleMiddleware();
    }

    /**
     * 注册用于限制请求的中间件。
     *
     * @return void
     */
    private function registerThrottleMiddleware(): void
    {
        $router = app()->make('router');

        $middleware = config('cache.default') !== 'redis'
            ? \Illuminate\Routing\Middleware\ThrottleRequests::class
            : \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class;

        $router->aliasMiddleware('throttle', $middleware);
    }
}
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板