gpt4 book ai didi

php - Laravel 5 在 AJAX 密集型应用程序中丢失 session 和 .env 配置值

转载 作者:可可西里 更新时间:2023-10-31 22:14:06 27 4
gpt4 key购买 nike

我正在使用 Laravel 5(具体来说,“laravel/framework”版本是“v5.0.27”), session 驱动程序 = 'file'。

我正在 Windows 7 64 位机器上开发。

我注意到有时(大约一周一次)我会意外地随机退出。有时甚至在我登录后立即发生这种情况。我已将日志消息添加到我的身份验证逻辑代码中,但未触发日志代码。 Laravel 表现得好像它已经完全丢失了 session 文件。

另一个更严重的问题是,有时在调试 session (使用 xdebug 和 Netbeans)之后,Laravel 也开始丢失其他文件 - .env 设置、一些 debugbar JS 文件等。错误日志包含如下消息:

[2015-07-08 13:05:31] local.ERROR: exception 'ErrorException' with message 'mcrypt_encrypt(): Key of size 7 not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported' in D:\myproject\vendor\laravel\framework\src\Illuminate\Encryption\Encrypter.php:81
[2015-07-08 13:05:31] local.ERROR: exception 'PDOException' with message 'SQLSTATE[HY000] [1044] Access denied for user ''@'localhost' to database 'forge'' in D:\myproject\vendor\laravel\framework\src\Illuminate\Database\Connectors\Connector.php:47

这清楚地表明 Laravel 未读取 .env 文件,因此它使用默认设置:
'database'  => env('DB_DATABASE', 'forge'),
'key' => env('APP_KEY', 'somekey'),

丢失文件的情况很少发生,可能一个月左右一次,而且总是在调试 session 之后发生。我总是不得不重新启动 Apache 以使其再次工作。

为了对系统进行压力测试并可靠地重现问题,我在我的 Angular Controller 中使用了一个快速破解:
setInterval(function(){
$scope.getGridPagedDataAsync();
}, 500);

它只是一个从 Angular 到 Laravel 的基本数据请求。

就是这样 - 现在我可以在 3 分钟或更短的时间内重现 session 丢失和 .env 丢失。

我之前在同一台 PC 上使用相同的 Apache+PHP 开发了 AJAX 密集型 Web 应用程序,但没有 Laravel,没有 .env,我以前没有注意到这些问题。

在通过代码调试时,我发现 Laravel 根本没有使用 PHP 内置 session ,而是实现了自己的基于文件的 session 。显然,它不能提供与默认 PHP session 相同的可靠性,我不知道为什么。

当然,在现实生活中,我的应用程序不会是 AJAX 密集型的,但根据我的经验,在某些情况下,只有两个同时 AJAX 请求丢失 session 就足够了。

我在 Laravel 上看到了一些关于各种 session 问题的相关错误报告。不过,我还没有看到有关 dot-env 的任何信息,但它似乎遇到了同样的问题。

我的猜测是 Laravel 不使用文件锁定和等待,因此如果由于某种原因无法读取文件(可能被某些并行进程或 Apache 锁定),那么 Laravel 只会放弃并返回它所能返回的任何内容。

有什么好的解决办法吗?也许它特定于 Windows,问题会在 Linux 机器上消失?

很好奇,为什么 Laravel(或 Symfony)开发人员还没有修复他们的 session 文件驱动程序。我知道锁定/等待会减慢它的速度,但至少有一些选项可以打开“可靠 session ”会很棒。

同时,我将尝试逐步完成 Laravel 代码,看看我是否可以发明一些“快速而肮脏”的修复方法,但最好有一些可靠的“最佳实践”解决方案。

关于 .env 的更新

该问题与锁定文件无关。我找到了 .env 问题的 Laravel 错误报告,这使我找到了 Dotenv 项目的链接报告,而该报告又说这是一个核心 PHP 问题。让我感到不安的是,Dotenv 开发人员说 Dotenv 从未打算用于生产,但 Laravel 似乎依赖于 Dotenv。

https://github.com/laravel/framework/pull/8187似乎有一个解决方案应该在一个方向上起作用,但一些评论者说,在他们的情况下,问题是相反的。有人打电话 crynobone 给出了一个聪明的代码片段来尝试:
$value = array_get($_ENV, $key, getenv($key));

出现了另一个建议在 Dotenv 和 Laravel Githubs 上使用“makeMutable()”,但评论者报告说这可能会破坏测试。

所以我尝试了 crynobone 的代码,但它对我不起作用。在调试时,我发现在我的情况下,当并发请求出现故障时,在 getenv()、$_ENV 甚至 $_SERVER 中都找不到 $key。
唯一有效(quick&dirty experminet)是添加:

静态::$cached[$name] = $value;

到 Dotenv 类,然后在 helpers.php env() 方法中我看到:
Dotenv::$cached[$key]

总是好的,即使 $_ENV 和 getenv 都没有给出任何内容。

尽管 Dotenv 不适合生产,但我不想更改我们的部署和配置工作流程。

接下来我将不得不调查 session 问题...

附录

相关的 Laravel 错误报告(有些甚至来自第 4 版,而且似乎没有修复):
https://github.com/laravel/framework/issues/4576

https://github.com/laravel/framework/issues/5416

https://github.com/laravel/framework/issues/8172

和一篇旧文章,它阐明了正在发生的事情(至少在 session 问题上):
http://thwartedefforts.org/2006/11/11/race-conditions-with-ajax-and-php-sessions/

最佳答案

我个人认为使用 .env 来配置 Laravel 是一个错误的决定。拥有包含 key:value 配置样式的 .php 文件要好得多。

但是,您遇到的问题不是 PHP 的错,也不是 Apache 的错 - 这很可能是 Windows 问题。

其他一些事情: Apache 包含一个模块,该模块允许将 PHP 二进制文件集成到 Apache 的进程或线程中,称为 mod_php - 问题在于 PHP 不仅速度慢,而且将另一个二进制文件集成到现有二进制文件中非常棘手,可能会遗漏一些东西。在这种情况下,PHP 还必须使用线程安全来构建。如果不是,那么奇怪的错误可能(并且将会)发生。

为了避免将一个程序复杂地集成到另一个程序中的问题,我们可以完全避免这种情况,我们可以使用 .php通过 FastCGI 协议(protocol)提供服务。这意味着 Web 服务器(Apache 或 Nginx)将接收 HTTP 请求并将其传递给另一个“Web”服务器。在我们的例子中,这将是 PHP FastCGI 进程管理器或 PHP-FPM .
PHP-FPM是首选的服务方式.php页面 - 不仅因为它更快(比通过 mod_php 集成要快得多),而且您可以轻松扩展 HTTP 前端并让多台机器提供服务 .php页面,让您可以轻松地横向扩展您的 HTTP 前端。

然而,PHP-FPM是一种称为主管进程的东西,它依赖于进程控制。据我所知,Windows 不像 *nix 那样支持进程控制,因此 php-fpm不适用于 Windows(如果我在这里错了,请纠正我)。

这一切对你来说意味着什么?这意味着您应该使用旨在与您想做的事情完美配合的软件。
这是应该遵循的逻辑:

  • Web 服务器接受 HTTP 请求(Apache 或 Nginx)
  • Web 服务器验证请求,解析原始 HTTP 请求,确定请求是否过大,如果在这种情况下一切顺利,它将请求代理到 php-fpm .
  • php-fpm处理请求(在您的情况下它会启动 Laravel)并返回 Web 服务器向用户显示的 HTML

  • 现在,这个过程虽然很棒,但也带来了一些问题,这里的一个大问题是 PHP 如何处理 session 。默认的 PHP session 是存储在服务器上某处的文件。这意味着,如果您有 2 台物理机为您的 php-fpm 服务。 ,您将遇到 session 问题。这就是 Laravel 做得很棒的地方 - 它允许您使用基于 cookie 的加密 session 。它有一些限制(您不能在这些 session 中存储资源,并且有大小限制),但是正确构建的应用程序首先不会在 session 中存储太多信息。当然,有多种处理 session 的方法,但在我看来,加密的 cookie 是 super 、 super 简单易用且功能强大的。当使用这样的 cookie 时,携带 session 信息的是客户端,任何包含解密 key 的机器都可以读取此 session ,这意味着您可以轻松地将您的设置扩展到多个服务器 - 他们所要做的就是访问相同的解密 key (它是 APP_KEY 中的 .env )。基本上,您需要将相同的 Laravel 安装复制到您希望为项目提供服务的机器上。

    我将处理您在开发过程中遇到的问题的方式如下:
  • 使用虚拟机(比如 Oracle Virtualbox)
  • 安装 Ubuntu 14.04
  • 将网络驱动器映射到 Windows 主机(使用 Samba)
  • 使用您喜欢的编辑 PHP 文件的方式,但它们将存储在映射驱动器上
  • 启动 nginx 或 Apache,以及 php-fpm在 VM 上为您的项目提供服务

  • 现在你通过这个过程获得的是:你不会用监听端口 80/443 的程序污染你的 Windows 机器,当你完成工作时,你可以关闭 VM 而不会丢失工作,你也可以轻松地模拟您的网站在实际生产机器上的行为方式,您不会有意外,例如“它在我的开发机器上工作,但在我的生产机器上不起作用”,因为您拥有用于这两种目的的相同软件。

    这些是我的 意见 ,它们并不都是冷事实,我在这里写的东西应该持保留态度。如果您认为我写的内容可能对您有所帮助,那么请尝试以这种方式解决问题。如果没有,好吧,不要感到难过,祝你的项目好运。

    关于php - Laravel 5 在 AJAX 密集型应用程序中丢失 session 和 .env 配置值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31295126/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com