首页 > 解决方案 > 从 HttpKernel 获取对 url 的响应,并行化

问题描述

我正在使用https://github.com/JosephSilber/page-cache来缓存页面。为了事先准备好页面(大约 100,000 个),我曾经通过 GuzzleHttp 并行运行 8 个 http 请求。它工作,但很慢,因为开销。

我正在寻找一种Illuminate\Http\Request直接通过应用程序实例处理实例的方法,以防止真正的 http 请求。我注意到,这要快得多。但是,将其与https://github.com/amphp/parallel-functions并行会带来一些问题。

基本代码是这样的:

    wait(parallelMap($urlChunks->all(), function($urls) {
            foreach($urls as $url) {
                //handle the request
            }
        }, $pool));

我尝试了几种变体来处理请求。

1.

$request = \Illuminate\Http\Request::create($url, 'GET');
$response = app()->handle($request);

在这种情况下,app()返回 的实例Illuminate\Container\Container,而不是 app 的实例。所以它没有方法handle()等等。

2.

$request = \Illuminate\Http\Request::create($url, 'GET');
$response = $app->handle($request);

这里唯一的区别:变量$app被注入到闭包中。它的值是app()闭包外调用的正确返回值。是应用程序,但是amp失败,因为Application实例中包含的PDO连接不能被序列化。

3.

$request = \Illuminate\Http\Request::create($url, 'GET');
$app = require __DIR__.'/../../../bootstrap/app.php';
$app->handle($request);

这在短时间内有效。但是随着应用程序的每次实例化,一个或两个 mysql 连接开始在“睡眠”状态下徘徊。它们只有在脚本结束时才会关闭。重要提示:这与并行化无关。我实际上用顺序循环尝试了同样的方法,并注意到了同样的效果。对我来说,这看起来像是框架中的一个错误,因为人们应该期望 Application 实例在它被销毁时会关闭所有连接。或者我可以手动执行此操作吗?这将是让这件事发挥作用的一种方法。

有任何想法吗?

标签: laravellaravel-5.4amphp

解决方案


第三个版本是我推荐的方法。PHP 中的资源通常在 PHP 存在时被清理,但这不适用于长时间运行的应用程序。要改变这一点,我会在 Laravel 存储库或创建该数据库连接的任何内容中提交问题。


推荐阅读