Laravel 5在AJAX密集型应用程序中丢失会话和.env配置值 [英] Laravel 5 losing sessions and .env configuration values in AJAX-intensive applications

查看:45
本文介绍了Laravel 5在AJAX密集型应用程序中丢失会话和.env配置值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用带有会话驱动程序='file'的Laravel 5(具体来说,"laravel/framework"版本为"v5.0.27").

I am using Laravel 5 (to be specific, "laravel/framework" version is "v5.0.27"), with session driver = 'file'.

我正在Windows 7 64位计算机上进行开发.

I'm developing on Windows 7 64 bit machine.

我注意到有时(一周左右)我会出乎意料地随机退出.有时甚至在我登录后立即发生.我已将日志消息添加到我的auth逻辑代码中,但是未触发该日志代码.Laravel表现得好像完全丢失了会话文件.

I noticed that sometimes (once a week or so) I get unexpectedly and randomly logged out. Sometimes this happens even immediately after I log in. I have added log messages to my auth logic code, but the log code was not triggered. Laravel behaved as if it has completely lost the session file.

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

Another, more serious issue, was that sometimes after debugging sessions (using xdebug and Netbeans) Laravel started losing also other files - .env settings, some debugbar JS files etc. The error log had messages like:

[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文件,因此它使用的是默认设置:

This clearly signals that .env file was not read by Laravel, so it is using default settings:

'database'  => env('DB_DATABASE', 'forge'),
'key' => env('APP_KEY', 'somekey'),

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

Losing files happened rarely, maybe once a month or so, and it always happened after debugging sessions. I always had to restart Apache to make it work again.

为了对系统进行压力测试并可靠地重现问题,我在Angular控制器中使用了快速技巧:

To stress-test the system and reproduce the issues reliably, I used a quick hack in my Angular controller:

setInterval(function(){
    $scope.getGridPagedDataAsync();
}, 500);

这只是从Angular到Laravel的基本数据请求.

It is just a basic data request from Angular to Laravel.

就是这样-现在,我可以在3分钟或更短的时间内重现会话丢失和.env丢失的情况.

And that was it - now I could reproduce the session losing and .env losing in 3 minutes or less.

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

I have developed AJAX-intensive web applications earlier on the same PC with the same Apache+PHP, but without Laravel, without .env, and I hadn't noticed such issues before.

通过代码进行调试时,我发现Laravel根本不使用PHP内置会话,而是实现了自己的基于文件的会话.显然,它没有提供与默认PHP会话相同的可靠性,我不确定为什么.

While debugging through code, I found out that Laravel is not using PHP built-in sessions at all, but has implemented their own files-based session. Obviously, it does not provide the same reliability as default PHP sessions and I'm not sure why.

当然,在现实生活中,我的应用程序不会占用大量的AJAX,但是根据我的经验,有时仅两个同时的AJAX请求就可以丢失会话.

Of course, in real life scenarios my app won't be that AJAX-intensive, but in my experiences on some occasions it is enough with just two simultaneous AJAX requests to lose the session.

我在Laravel上看到了一些有关各种会话问题的相关错误报告.虽然我还没有看到任何关于dot-env的信息,但是似乎也遇到了同样的问题.

I have seen some related bug reports on Laravel for various session issues. I haven't yet seen anything about dot-env, though, but it seems suffering from the same issue.

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

My guess is that Laravel does not use file locks and waiting, thus if a file cannot be read for some reason (maybe locked by some parallel process or Apache) then Laravel just gives up and returns whatever it can.

对此有什么好的解决方案?也许它特定于Windows,而问题将在Linux机器上消失?

很好奇,为什么Laravel(或Symfony)开发人员尚未修复其会话文件驱动程序.我知道锁定/等待会降低它的速度,但是最好至少要有一些选择来打开可靠的会话".

Curious, why Laravel (or Symfony) developers haven't fixed their session file driver yet. I know that locking/waiting would slow it down, but it would be great to at least have some option to turn on "reliable sessions".

同时,我将尝试逐步浏览Laravel代码,看看是否可以发明一些快速而肮脏的"修复程序,但是拥有一些可靠的最佳实践"解决方案会更好.

Meanwhile I'll try to step through Laravel code and see if I can invent some "quick&dirty" fix, but it would be much better to have some reliable and "best practices" solution.

该问题与锁定文件无关.我发现了.env问题的Laravel错误报告,这使我找到了Dotenv项目的链接报告,该报告又说这是PHP的核心问题.令我感到困扰的是,Dotenv开发人员说过,Dotenv从来都不打算用于生产,但是Laravel似乎依赖于Dotenv.

The issue turned to be not related to locking files. I found the Laravel bug report for .env issue, which lead me to a linked report for Dotenv project which, in turn, says that it is a core PHP issue. What disturbs me is that Dotenv devs say that Dotenv was never meant to be used for production, but Laravel seems to rely upon Dotenv.

https://github.com/laravel/framework/pull/8187 解决方案应该在一个方向上起作用,但是一些评论者说,在他们的情况下,问题恰恰相反.名为 crynobone 的人提供了一个聪明的代码段来尝试:

In https://github.com/laravel/framework/pull/8187 there seems to be a solution which should work in one direction but some commenter says that in their case the issue was the opposite. Someone called crynobone gave a clever code snippet to try:

$value = array_get($_ENV, $key, getenv($key));

还有另一种建议在Dotenv和Laravel Githubs上都使用"makeMutable()",但是评论者报告这可能会破坏测试.

There appeared another suggestion to use "makeMutable()" on both Dotenv and Laravel Githubs, but commenters report that this might break tests.

所以我尝试了 crynobone 的代码,但是它对我不起作用.调试时,我发现对于并发请求而言,当发生故障时,无法在getenv()中,在$ _ENV中甚至在$ _SERVER中都找不到$ key.唯一有效的方法(快速而肮脏的专家)是添加:

So I tried the crynobone's code but it did not work for me. While debugging, I found out that in my case when things break down for concurrent requests, the $key cannot be found nor in getenv(), nor in $_ENV and not even in $_SERVER. The only thing that worked (quick&dirty experminet) was to add:

static :: $ cached [$ name] = $ value;

static::$cached[$name] = $value;

转到Dotenv类,然后在helpers.php env()方法中看到:

to Dotenv class and then in helpers.php env() method I see that:

Dotenv::$cached[$key]

始终是好的,即使$ _ENV和getenv都什么都不给.

is always good, even when $_ENV and getenv both give nothing.

尽管Dotenv并非用于生产,但我不想更改我们的部署和配置工作流程.

Although Dotenv was not meant for production, I don't want to change our deployment and configuration workflow.

下一步,我将不得不调查会话问题...

Next I'll have to investigate the session issues...

相关的Laravel错误报告(甚至从版本4开始也存在一些报告,而且似乎没有固定): https://github.com/laravel/framework/issues/4576

Related Laravel bug reports (some even from version 4. and it seems, not fixed): https://github.com/laravel/framework/issues/4576

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

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

以及一篇旧文章,它阐明了正在发生的事情(至少与会议问题有关): http://thwartedefforts.org/2006/11/11/race-ajax和php-sessions条件/

and an old article which sheds some light on what's going on (at least with session issues): http://thwartedefforts.org/2006/11/11/race-conditions-with-ajax-and-php-sessions/

推荐答案

经过两天的密集调试,我有一些变通办法可能对其他人有用:

After two days of intensive debugging I have some workarounds which might be useful to others:

这是我的Dotenv 1.1.0和Laravel 5.0.27补丁,用于解决.env问题: https://gist.github.com/progmars/db5b8e2331e8723dd637

Here is my patch for Dotenv 1.1.0 and Laravel 5.0.27 to fix .env issues: https://gist.github.com/progmars/db5b8e2331e8723dd637

这是我的变通办法修补程序,用于减少会话问题的发生频率(或者,如果您不是在每个请求中都不自己写会话,则可以完全解决这些问题): https://gist.github.com/progmars/960b848170ff4ecd580a

And here is my workaround patch to make session issues much less frequent (or fix them completely, if you don't write to session yourself on every request): https://gist.github.com/progmars/960b848170ff4ecd580a

我使用Laravel 5.0.27和Dotenv 1.1.0对它们进行了测试.

I tested them with Laravel 5.0.27 and Dotenv 1.1.0.

最近还为Laravel 5.1.1和Dotenv 1.1.1重新创建了补丁: https://gist.github.com/progmars/e750f46c8c12e21a10ea https://gist.github.com/progmars/76598c982179bc335ebb

Also recently recreated patches for Laravel 5.1.1 and Dotenv 1.1.1: https://gist.github.com/progmars/e750f46c8c12e21a10ea https://gist.github.com/progmars/76598c982179bc335ebb

确保添加

'metadata_update_threshold' => 1,

到您的config/session.php,此补丁生效.

to your config/session.php for this patch to become effective.

所有修补程序每次重新创建时都应应用于 vendor 文件夹.

All the patches should be applied to vendor folder each time it gets recreated.

此外,您可能希望将会话补丁分开,因为您只更新一次 session.php ,但是补丁的其他部分应分别应用于 vendor 文件夹在部署之前重新创建它的时间.

Also you might want to separate the session patch out because you update session.php just once, but the other parts of the patch should be applied to vendor folder each time it gets recreated before deployment.

被警告:它可以在我的机器上工作".我真的希望Laravel和Dotenv开发人员能够提出更好的建议,但与此同时,我也可以使用这些修复程序.

Be warned: "It works on my machine". I really hope Laravel and Dotenv developers will come up with something better, but meanwhile I can live with these fixes.

这篇关于Laravel 5在AJAX密集型应用程序中丢失会话和.env配置值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆