【问题标题】:PHP sessions, cookieless domains, and performancePHP 会话、无 cookie 域和性能
【发布时间】:2011-11-19 10:32:55
【问题描述】:

我支持整个无 cookie 域/CDN 的事情,并且我了解如何将 cookie 发送到 www.yourdomain.com,同时设置一个单独的域(如 cdn.yourdomain.com)以防止不必要的 cookie发送有助于提高性能。

我很好奇的是,使用 PHP 的本机会话是否会对性能产生负面影响,如果是,会如何?我知道会话密钥在一个很小的 ​​cookie 中被跟踪,所以这看起来很好。

系统提示我问这个问题,因为过去我编写了我的网络应用程序,并将大量用户的活动数据、偏好和身份验证信息存储在 $_SESSION 变量中。然而,我注意到一些流行的网络应用程序,比如 Wordpress,根本不使用$_SESSION。但是会话易于使用并且看起来相当安全,特别是如果您将其与跟踪用户代理/ ip 更改结合起来以防止会话劫持。那么为什么 Wordpress 和其他网络应用程序不使用 php 的会话呢?我也应该停止使用会话吗?

另外,我还要澄清一下,我确实意识到服务器必须加载会话数据来处理页面请求,但这不是我在这里要问的。我的问题是关于它是否/如何影响网络性能,特别是关于发送/接收的标头。例如,使用会话是否会阻止网站上的页面或图像从浏览器的缓存中获取? PHPSESID cookie 是唯一发送的附加标头吗?诸如此类。

【问题讨论】:

  • 我没有使用 Wordpress 的经验。出于我的好奇心,有人可以验证它确实不使用会话,即使是维护登录这样的基本目的?我可以看到使用 db 存储代替扩展会话 var 存储。
  • Wordpress 不使用会话。我知道为什么,这是有历史原因的。但我很好奇哪些其他流行的 Web 应用程序不是很好?你有更多的例子吗?
  • Michael - Worpress 绝对不使用会话,除非您使用已启动会话的插件。 @hakre - 你能分享历史原因吗?我主要使用 WP,但 Expression Engine 和 Code Ignitor 也不使用 PHP 的会话。
  • 唯一似乎有意义的例子是,如果会话 cookie 或基于 URL 的 SESSIONID 中的更改会使浏览器缓存/页面或文件缓存标头无效并触发下载。

标签: php performance session cookies dns


【解决方案1】:

$_SESSION 的标准存储是每个会话一个文件的文件系统。这是有代价的:

  • 当两个请求访问同一个会话时,一个请求将战胜另一个请求,另一个请求需要等待第一个请求完成。由文件锁定控制的竞争条件。

使用 cookie 存储会话数据(Wordpress、Codeigniter),竞争条件是相同的,但锁定不是那么固有,但浏览器可能会在 cookie 管理中进行锁定。

使用 cookie 的缺点是您无法存储那么多数据,并且数据会随每个请求和响应一起传递。这也可能引发安全问题。窃取 cookie,您就获得了数据。如果它是加密的,攻击者可以尝试对其进行解密以获取其中存储的数据。

Wordpress 的历史原因是该平台从未使用过 PHP 会话。根项目开始于 2000 年左右,在 2002 年和 2004 年获得了很大的关注。由于会话处理仅在 PHP 4 中可用,而 PHP 3 在那个时候更受欢迎。

后来,当$_SESSION 可用时,应用程序的主要设计已经完成,并且可以正常工作。此外,在 2004/2005 年,wordpress 决定启动商业多博客托管服务。这产生了跨服务器扩展应用程序的需求,并且 cookie+数据库对于会话/用户处理来说看起来比使用 $_SESSION 实现更容易。事实上,这很简单,而且可以正常工作,因此无需更改它。

对于 Codeigniter,我不能说太多。我知道它默认将所有会话信息存储在 cookie 中。所以 session 只是 cookie 的另一个名字。可选地,它可以被加密,但这需要配置。 IIRC 据说这样做是因为“大多数用户不需要会话”。对于那些需要的人,有一个数据库后端(需要额外的配置),因此用户可以在他们的应用程序中透明地从 cookie 更改为数据库存储。还有一个可用的新实现,允许您更改为您喜欢的任何商店,例如也适用于原生 PHP 会话。这是通过所谓的驱动程序完成的。

但这并不意味着您现在无法基于$_SESSION 实现相同的目标。你可以用任何你喜欢的东西(甚至是 cookie :) 来替换 store,并且它的 PHP 实现应该被封装在一个好的程序设计中。

完成后,您可以实现一个可以更好地控制锁定的存储(例如数据库),并且可以在不支持粘性会话的负载平衡基础架构中跨服务器工作。

Wordpress 是一个很好的例子,它可以自己实现会话处理,与 PHP 提供的任何东西完全无关。这意味着轮子已被重新发明。从今天的角度来看,我不会将他们的设计称为明确的创新,因此它在非常特定的环境中完全满足了非常特定的需求,只有了解项目的根源才能理解。

Codeigniter 可能领先一步(在接口意义上),因为它为会话提供了某种(不稳定的)接口,并且可以用您喜欢的任何实现来替换它。这对新开发人员来说要好得多,但它也有点像重新发明轮子,因为 PHP 已经开箱即用了。

在应用程序设计中您可以做的最好的事情是使实现独立于系统需求,从而使会话数据的存储机制独立于程序流的其余部分。 PHP 提供了一个非常直接的接口、$_SESSION 数组和会话配置。

由于$_SESSION 是一个超全局数组,您可能希望阻止您的应用程序直接访问它,因为这会引入全局状态。所以在一个好的设计中,你应该有一个接口,能够完全抽象出超全局。

这样做,加上存储和配置的抽象(例如,所有在一个会话依赖容器中),您应该能够在任意数量的服务器上扩展和维护您的应用程序,无论出于何种原因。如果您认为这适合您,那么您的实现可以只使用 cookie。但是,您可以在需要时切换到基于数据库的会话 - 无需重写应用程序的大部分内容。

【讨论】:

  • 所以看起来内置 $_SESSION 的主要关注点实际上是可扩展性而不是网络负载。凉爽的。此外,Wordpress 的历史也很有趣。感谢分享。
  • 不,$_SESSION 的主要关注点是全局状态。 $_SESSION 扩展性很好,you can change the storage implementation,另请参阅手册:Session Handling
【解决方案2】:

我不是 100% 相信这种情况,但避免 PHP 中内置的 $_SESSION 机制的一个原因是,如果您想在高可用性网络农场场景中部署您的网络应用程序。

由于 PHP 中的默认会话行为是将会话对象存储在进程中,在内存中,因此很难(如果不是不可能的话)让多个服务器处理来自同一用户的请求。只有当您想在网络农场环境中部署您的 Web 应用程序时,您才会拥有此功能,在该环境中,您有许多 PHP Web 服务器处理您的应用程序的请求以平衡负载。

因此,虽然进程内会话状态通常比基于数据库的解决方案快得多,但当您需要处理大量请求并为使用网络农场环境的容量提供服务时,后者是有利的。

正如我一开始所说,我不能 100% 确定 PHP 是否支持将会话状态提供程序配置为数据库或会话状态服务器,而不是进程内默认值。

【讨论】:

  • 在我的工作中,我们有一个负载平衡环境(称为 DYNOFARM),其中五六台服务器共享请求。我不会说我们是真正的高负载,但我一直在使用会话并且从来没有遇到过问题。
  • @Milky Dinescu - 我明白你在说什么,这是有道理的:避免使用 php 的本机会话的一个原因是因为它可以防止在不使用一些特殊工具的情况下跨多个服务器进行扩展。我记得以前读过这个,但忘记了。谢谢你提醒我。
猜你喜欢
  • 2012-06-25
  • 1970-01-01
  • 2014-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-16
  • 2013-03-06
  • 2011-08-18
相关资源
最近更新 更多