Laravel 水平扩展环境中的数据库会话

Laravel Database Sessions in Horizontally Scaled Enviornment

我在多个 frontend/application 服务器环境中使用 Laravel(即 -- 负载平衡器后面的两个 Web 服务器)。

我正在调试 Laravel 应用程序在向服务器发出几次请求后丢失其会话数据的问题。我们正在使用单个 MySQL 数据库实例的数据库会话。

我注意到每次重新加载页面时,laravel_session cookie 都会发生变化。一页刷新看起来像这样

eyJpdiI6I-mRudUNnM0ZpQzdxYmNyaWw0d21nWFE9PSIsInZhbHVlIjoiazVDQTVuZ0IzYUg5V0l3czBxaFl6bFRrXC9aTjFmT0VBeGVDYXg1REZQM2pIS1U0U1JCSVVreHprYU44ZjhKQTU4OTVUUGxpXC9qbWZpd0FcL2NtXC9ST25B-PT0iLCJtYWMiOiJ-hZWYxNTU4MDY0ODQxODViNDRjMjQzZGE1ZDQwZDA0YzQ0ZDY1YjE3YWE3YTc3ZjcwNTg4NGE3NDhhMWMzMGU0In0

然后再次重新加载页面看起来像这样

eyJpdiI6I-nFjRjN1TGp0Q3Z3VmlrOG1PQlwveDF3PT0iLCJ2YWx1ZSI6IkVRYkpuWXFIVms5YnBwRXU2b1wvMFZSbW14RkVTZm8yVEpnaHRiOEhpWnlJWm9OM0JRR1wvYUI1VWhmeGYxQm0yaEFrc25PZUVcL3NSZ0RtUytzWHR3THp3-PT0iLCJtYWMiOiJ-jNTQ1YjM0MTkwZDVmM2RlMTAxYmNkMjAzMTY1NzVjMDExNTkxODAyZDM0YmQ5ZTk5NzFiNmY1YjQxYzE3ZjY1In0

- 是我添加的,以表明有些部分保持不变。

问题:

  1. 这是更改会话 ID 标准 Laravel 行为吗?

  2. Laravel 的 4.2 数据库会话是否可以在多前端 Web 服务器环境中开箱即用?

  3. 会话实现在 Laravel 的核心中的哪个位置,以便我自己查看?

回复:#1,根据 ceejayozlaravel_session cookie 在每次服务器请求时都会重新加密,并且这种加密包括一些随机化——这意味着不断变化的 laravel_session 值是标准 Laravel 行为。

这可能有很多原因,但最有可能的是您的负载平衡器将您定向到另一台不知道您的会话 ID 的服务器,因此为您生成了一个新会话。

这个问题的解决方案是使用像 redis. Laravel has native support for redis 这样的共享密钥存储,因此应该不需要太多的努力来启动它 运行 然后您的会话缓存将在您的用户之间共享应用。 Redis 非常高效且易于设置,因此您的服务器不会因它而严重超载。根据高负载下的会话数,您可能需要考虑升级 RAM。

当然,您也可以将会话缓存目录移动到网络共享。这可能是低效和浪费精力,但你的竞争对手会大笑 ;)

编辑:还要确保两个应用程序具有相同的加密密钥

Is this changing session ID standard Laravel behavior?

是的,这是标准的 Laravel 行为 -- Illuminate\Cookie\Guard 中间件层使用从 Illuminate\Encryption\Encrypter class 实例化的 object 自动加密应用程序 cookie ],其中包括 creating an initialization vector from a random source

#File: vendor/laravel/framework/src/Illuminate/Cookie/Guard.php
public function encrypt($value)
{           
    $iv = mcrypt_create_iv($this->getIvSize(), $this->getRandomizer());
    //...
    $value = base64_encode($this->padAndMcrypt($value, $iv));
    //...
}

Will Laravel's 4.2 database sessions work out of the box in the multiple frontend web server environment?

据我所见,是的。 Laravel 的数据库 session 是基于 ID 的,假设将相同的应用程序和配置发送到每个服务器,ID 可以在服务器之间交换用户的负载平衡器中幸存下来。

Where in Laravel's core does the session implementation live so I can poke at it myself?

Laravel 的 Session 处理是在 Session 中间件

中设置的
#File: vendor/laravel/framework/src/Illuminate/Session/Middleware.php

出于好奇,sessions 在这里结束了一个红鲱鱼。问题是从安全 URL 到 post 到不安全 URL 的表单 URL 设置。发生这种情况时,浏览器会丢弃您的 cookie,这意味着 session ID 会重新生成。所以,这仍然是我们的负载平衡设置间接造成的,我们的猴子补丁 Request object 没有考虑到 Laravel 的 url->to() 生成的 url。我们的解决方案是将 URL 生成的形式切换为使用命名的 route,并仅在 app/routes.php

中将路由配置为 https