优化基于Kohana的网站以提高速度和可扩展性使用反向代理在PHP方面:在SQL方面:现在该怎么办?那么小花呢?结论?

我用Kohana建立的一个网站昨天遭到了大量流量的猛烈抨击,导致我退后一步,评估了一些设计。我很好奇优化基于Kohana的应用程序的标准技术是什么?

我也对基准测试感兴趣。我是否需要为每个控制器方法设置和操作才能查看所有页面的执行时间,或者我是否能够全局快速地应用基准测试?Benchmark::start()Benchmark::stop()

我将在未来的时间里更多地使用Cache库,但我对更多的建议持开放态度,因为我确信我还可以做很多事情,而我现在根本没有意识到。


答案 1

我在这个答案中要说的并不是Kohana所特有的,它可能适用于许多PHP项目。

以下是我在谈论性能,可扩展性,PHP,...
我在做几个项目的时候用过很多这些想法——它们也帮了上忙;所以它们可能也能帮上忙。


首先,在表演方面,有许多方面/问题需要考虑

  • 服务器的配置(Apache,PHP,MySQL,其他可能的守护进程和系统);你可能会在ServerFault上得到更多的帮助,我想,
  • PHP 代码,
  • 数据库查询,
  • 是否使用您的网络服务器?
  • 可以使用任何类型的缓存机制吗?或者您是否总是需要在网站上提供更多最新数据?


使用反向代理

可能真正有用的第一件事是在你的Web服务器前面使用反向代理,比如varnish:让它缓存尽可能多的东西,所以只有真正需要PHP / MySQL计算的请求(当然,当它们不在代理的缓存中时,还有其他一些请求)才能进入Apache / PHP / MySQL。

  • 首先,你的CSS/Javascript/Images——嗯,所有静态的东西——可能不需要总是由Apache来服务。
    • 因此,您可以让反向代理缓存所有这些内容。
    • 对于Apache来说,提供这些静态文件没什么大不了的,但是它为这些静态文件工作的越少,它就越能用PHP来做。
    • 请记住:Apache一次只能处理有限数量的请求。
  • 然后,让反向代理从缓存中提供尽可能多的PHP页面:可能有一些页面不会经常更改,并且可以从缓存中提供。与其使用一些基于PHP的缓存,为什么不让另一个更轻的服务器为这些缓存提供服务(并时不时地从PHP服务器获取它们,这样它们几乎总是最新的)
    • 例如,如果您有一些经常被请求的RSS源(在尝试优化性能时,我们通常倾向于忘记这些),那么将它们放在缓存中几分钟可以节省数百/数千个对Apache + PHP + MySQL的请求!
    • 对于您网站中访问量最大的页面也是如此,如果它们至少在几分钟内没有更改(例如:主页?),那么,每次用户请求它们时,都无需浪费CPU重新生成它们。
  • 也许为匿名用户提供的页面(所有匿名用户的页面相同)和为已识别用户提供的页面(例如,“你好X先生,你有新消息”)之间有区别?
    • 如果是这样,您可以配置反向代理以缓存为匿名用户提供的页面(通常基于 Cookie,如会话 Cookie)
    • 这意味着Apache + PHP需要处理的更少:只有已识别的用户 - 这可能只是您用户的一小部分。

关于使用反向代理作为缓存,对于PHP应用程序,您可以查看基准测试结果显示APC和Squid缓存的服务器功能提高了400%-700%
(是的,他们正在使用Squid,我说的是清漆 - 这只是另一种可能性,^^清漆是最近的,但更致力于缓存)

如果你做得足够好,并设法停止一次又一次地重新生成太多的页面,也许你甚至不必优化你的任何代码;-)
至少,也许不会急于求成...而且,当您没有太多的预设时,执行优化总是更好...


顺便说一句:你在OP中说:

我用Kohana建立的一个网站昨天遭到了大量流量的猛烈抨击,

这是一种突然出现的情况,如果您的网站可以处理到第二秒不最新的问题,那么反向代理可以节省一天的时间:

  • 安装它,配置它,让它总是 - 每平常的一天 - 运行:
    • 将其配置为不将PHP页面保留在缓存中;或仅短期;这样,您始终可以显示最新数据
  • 而且,在你采取斜杠点或挖掘效果的那一天:
    • 配置反向代理以将PHP页面保留在缓存中;或更长的时间;也许您的页面在第二秒之前不会是最新的,但它将使您的网站在挖掘效应中幸存下来!

关于这一点,我如何才能检测并生存下来被“斜杠点”?可能是一个有趣的阅读。


在PHP方面:

首先:您是否在使用最新版本的PHP?速度会定期提高,有新版本;-)
例如,看看PHP分支3.0到5.3-CVS的基准测试

请注意,性能是使用 PHP 5.3 的一个很好的理由我已经做了一些基准测试(法语),结果很棒)...
当然,另一个很好的理由是,PHP 5.2 已经达到了它的生命周期,不再维护了!

您是否正在使用任何操作码缓存?

  • 例如,我正在考虑APC - Alternative PHP Cachepeclmanual),这是我见过使用最多的解决方案 - 并且在我工作过的所有服务器上使用。
  • 在某些情况下,它确实可以大大降低服务器的CPU负载(我已经看到某些服务器上的CPU负载从80%增加到40%,只需安装APC并激活其操作码缓存功能!
  • 基本上,PHP脚本的执行分为两个步骤:
    • 将PHP源代码编译为操作码(相当于JAVA的字节码)
    • 执行这些操作码
    • APC将这些保留在内存中,因此每次执行PHP脚本/文件时要完成的工作量更少:仅从RAM中提取操作码并执行它们。
  • 顺便说一句,您可能需要查看APC的配置选项
    • 其中有相当多的,有些可以对速度/CPU负载/易用性产生很大影响
    • 例如,禁用可能对系统负载有好处;但这意味着对PHP文件所做的修改不会被考虑在内,除非你刷新整个操作码缓存;关于这一点,有关更多详细信息,请参阅例如 To stat() or Not To stat()?[apc.stat](https://php.net/manual/en/apc.configuration.php#ini.apc.stat)


对数据使用缓存

尽可能避免一遍又一遍地做同样的事情

当然,我考虑的主要事情是SQL查询:您的许多页面可能执行相同的查询,其中一些查询的结果可能几乎总是相同的......这意味着对数据库进行大量“无用”查询,这必须花时间一遍又一遍地提供相同的数据。
当然,对于其他事情也是如此,例如Web服务调用,从其他网站获取信息,繁重的计算......。

对于您来说,确定以下内容可能会非常有趣:

  • 哪些查询运行了很多次,始终返回相同的数据
  • 哪些其他(繁重的)计算需要花费大量时间,始终返回相同的结果

并将这些数据/结果存储在某种缓存中,这样它们就更容易获得 - 更快 - 并且您不必去SQL服务器“一无所获”。

例如,出色的缓存机制是:

  • APC:除了我之前谈到的操作码缓存之外,它还允许您将数据存储在内存中,
  • 和/或memcached另请参阅),如果您确实拥有大量数据和/或使用多个服务器,这是非常有用的,因为它是分布式的。
  • 当然,您可以考虑文件;可能还有许多其他想法。

我很确定你的框架附带了一些与缓存相关的东西;您可能已经知道,正如您在OP中所说的那样“我将更及时地使用缓存库”;-)


分析

现在,一个很好的做法是使用Xdebug扩展来分析你的应用程序:它通常允许很容易地找到一些弱点 - 至少,如果有任何需要花费大量时间的功能。

配置正确后,它将生成可以使用某些图形工具进行分析的分析文件,例如:

  • KCachegrind:我的最爱,但只能在 Linux/KDE 上运行
  • 用于窗户的Wincachegrind;不幸的是,它比KCacheGrind少了一点 - 它通常不显示呼号。
  • Webgrind运行在PHP Web服务器上,因此可以在任何地方工作 - 但可能具有较少的功能。

例如,以下是KCacheGrind的几个屏幕截图:

KCacheGrind : main screen
(来源:pascal-martin.fr
KCacheGrind : Callgraph exported as an image
(来源:pascal-martin.fr

(顺便说一句,如果我没记错的话,第二张截图上显示的来电图通常是WinCacheGrind和Webgrind都无法做到的,^^)


(感谢@Mikushi的评论)我没有使用过的另一种可能性是xhprof扩展:它也有助于分析,可以生成调用法 - 但比Xdebug更轻,这意味着您应该能够将其安装在生产服务器上。

您应该能够使用它 alonside XHGui,这将有助于数据的可视化。


在SQL方面:

现在我们已经谈到了一些关于PHP的问题,请注意,你的瓶颈很可能不是PHP方面的问题,而是数据库方面的瓶颈......

至少两三件事,在这里:

  • 您应该确定:
    • 应用程序最常执行的查询是什么
    • 这些是否经过优化(主要使用正确的索引?),使用 EXPLAIN 指令,如果您使用的是 MySQL
    • 您是否可以缓存其中一些查询(请参阅我之前所说的内容)
  • 您的 MySQL 是否配置良好?我对此知之甚少,但有一些配置选项可能会产生一些影响。

尽管如此,最重要的两件事是:

  • 如果您不需要,请不要去数据库:尽可能多地缓存
  • 当您必须转到数据库时,请使用有效的查询:使用索引;和个人资料!


现在该怎么办?

如果您仍在阅读,还有什么可以优化的?

好吧,还有改进的余地...一些面向架构的想法可能是:

  • 切换到 n 层体系结构:
    • 将MySQL放在另一台服务器上(2层:一层用于PHP;另一层用于MySQL)
    • 使用多个 PHP 服务器(并在这些服务器之间对用户进行负载平衡)
    • 使用另一台计算机处理静态文件,使用更轻的Web服务器,例如:
      • 光标
      • 或者nginx - 顺便说一句,这个越来越受欢迎。
    • 为MySQL使用多个服务器,为PHP使用多个服务器,并在这些服务器前面使用多个反向代理
    • 当然:在任何具有任意可用RAM的服务器上安装memcached守护程序,并使用它们尽可能多地缓存/有意义。
  • 使用Apache“更有效”的东西?
    • 我越来越频繁地听到关于nginx的消息,当涉及到PHP和高容量网站时,它应该很棒。我自己从未使用过它,但您可能会在网上找到一些关于它的有趣文章;

好吧,也许其中一些想法在你的情况下有点过分^^
但是,仍然......为什么不研究一下,以防万一?;-)


那么小花呢?

您最初的问题是关于优化使用Kohana的应用程序...好吧,我已经发布了一些适用于任何PHP应用程序的想法...这意味着它们对Kohana也是正确的;-)
(即使不是特定于它^^)

我说:使用缓存;Kohana似乎支持一些缓存的东西(你自己也说过,所以这里没有什么新东西......)
如果有什么可以快速完成的,请尝试一下;-)

我还说过,你不应该做任何不必要的事情。在Kohana中,默认情况下是否启用了您不需要的任何功能?
浏览网络,似乎至少有一些关于XSS过滤的东西;你需要那个吗?

不过,这里有几个链接可能很有用:


结论?

最后,一个简单的想法:

  • 您的公司需要花费多少钱才能向您支付5天?- 考虑到这是一个合理的时间来做一些伟大的优化
  • 您的公司购买(支付?)第二台服务器及其维护费用是多少?
  • 如果必须扩大规模,该怎么办?
    • 花费10天需要多少钱?更多?优化应用程序的每一个可能位?
    • 再多几台服务器多少钱?

我并不是说你不应该优化:你绝对应该!
但是,进行“快速”优化,首先会给您带来丰厚的回报:使用一些操作码缓存可能会帮助您将服务器的CPU负载降低10%到50%...而且只需几分钟即可设置;-)另一方面,花3天2%的时间...

哦,顺便说一句:在做任何事情之前:把一些监控的东西放在适当的位置,这样你就知道已经做了哪些改进,以及如何!
没有监控,您将不知道您所做的事情的影响...即使是否是真正的优化,也不会!

例如,您可以使用像RRDtool + cacti这样的东西。
向你的老板展示一些漂亮的图形,CPU负载下降40%总是很棒;-)


无论如何,并真正得出结论:玩得开心!
(是的,优化很有趣!)
(呃,我没想到我会写那么多......希望至少其中某些部分是有用的...我应该记住这个答案:在其他时候可能会有用...)


答案 2

使用 XDebugWinCacheGrindWebCacheGrind 来分析执行缓慢的代码。

WebCacheGrind
(资料来源:jokke.dk
WinCacheGrind


推荐