我用 Kohana 构建的一个网站昨天遭遇了巨大的流量冲击,导致我退后一步并评估了一些设计。我很好奇优化基于 Kohana 的应用程序有哪些标准技术?

我对基准测试也很感兴趣。我需要设置吗 Benchmark::start()Benchmark::stop() 对于每个控制器方法,以便查看所有页面的执行时间,或者我是否能够在全局范围内快速应用基准测试?

我将在未来更多地使用缓存库,但我愿意接受更多建议,因为我确信我可以做很多我目前还没有意识到的事情。

有帮助吗?

解决方案

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

以下是在谈论性能、可扩展性、PHP 时我想到的一些要点……
我在处理几个项目时使用了其中的许多想法——它们很有帮助;所以他们也可能在这里提供帮助。


首先,从表演的角度来看, 需要考虑的许多方面/问题:

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


使用反向代理

真正有用的第一件事是使用 反向代理, , 喜欢 , ,在您的网络服务器前面:让它 缓存尽可能多的东西, ,所以只有真正需要PHP/MySQL计算的请求 (当然,还有一些其他请求,当它们不在代理的缓存中时) 使其成为 Apache/PHP/MySQL。

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

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

如果你做得足够好,并且设法停止一次又一次地重新生成太多页面,也许你甚至不需要优化任何代码;-)
至少,也许不着急……当您没有承受太大压力时,执行优化总是更好......


作为旁注:你在OP中说:

我与Kohana建造的一个网站昨天被大量交通撞了

这是一种 反向代理可以拯救世界的突发情况, ,如果您的网站可以处理没有及时更新的情况:

  • 安装它,配置它,让它永远存在 ——每个平常的日子—— 跑步:
    • 配置它不将 PHP 页面保留在缓存中;或仅持续很短的时间;这样,您始终可以显示最新的数据
  • 并且,在您使用斜线或挖掘效果的那天:
    • 配置反向代理以将 PHP 页面保留在缓存中;或更长的一段时间;也许您的页面不会每秒更新,但这将使您的网站能够在挖掘效应中生存下来!

关于那个, 我怎样才能发现并生存被“Slashdotted”? 可能会是一本有趣的读物。


在 PHP 方面:

首先:你用的是 PHP 的最新版本?随着新版本的出现,速度会定期提高;-)
例如,看一下 PHP 分支 3.0 到 5.3-CVS 的基准测试.

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

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

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


使用数据缓存

尽可能地,最好是 避免一遍又一遍地做同样的事情.

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

您可能会很感兴趣地确定:

  • 哪些查询运行了很多次,总是返回相同的数据
  • 还有哪一个 (重的) 计算进行了很多时间,总是返回相同的结果

并将这些数据/结果存储在某种缓存中,这样它们就更容易获取—— 快点 ——而且您不必为了“无事”而访问您的 SQL 服务器。

例如,优秀的缓存机制有:

  • APC: :除了我之前提到的操作码缓存之外,它还允许您将数据存储在内存中,
  • 和/或 内存缓存 (也可以看看), ,如果你真的有的话,这非常有用 地段 数据和/或是 使用多个服务器, ,因为它是分布式的。
  • 当然,你可以考虑文件;可能还有许多其他想法。

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


分析

现在,一件好事就是使用 调试工具 延伸至 介绍您的应用程序: :它通常可以很容易地找到一些弱点——至少,如果有任何函数需要花费大量时间的话。

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

  • K缓存研磨: :我最喜欢的,但仅适用于 Linux/KDE
  • Wincachegrind 用于窗户;不幸的是,它比 KCacheGrind 做的事情要少一些——它通常不显示调用图。
  • 网络研磨 它运行在 PHP 网络服务器上,因此可以在任何地方工作——但功能可能较少。

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

KCacheGrind : main screen
(来源: 帕斯卡·马丁.fr)
KCacheGrind : Callgraph exported as an image
(来源: 帕斯卡·马丁.fr)

(顺便说一句,如果我没记错的话,第二个屏幕截图中显示的调用图通常是 WinCacheGrind 和 Webgrind 都无法做到的事情 ^^ )


(感谢@Mikushi 的评论) 我没有太多使用的另一种可能性是 教授 扩大 :它还有助于分析,可以生成调用图——但比 Xdebug 更轻,这意味着您应该能够将它安装在生产服务器上。

你应该能够单独使用它 新华桂, ,这将有助于数据的可视化。


在 SQL 方面:

现在我们已经谈论了一些关于 PHP 的内容,请注意它是 你的瓶颈很可能不是 PHP 方面, ,但是数据库一...

这里至少有两三件事:

  • 您应该确定:
    • 您的应用程序最常执行的查询是什么
    • 这些是否优化 (使用 正确的索引, ,主要是?), , 使用 EXPLAIN 指令,如果您使用 MySQL
    • 是否可以缓存其中一些查询 (看我之前说的)
  • 你的MySQL配置好了吗?我对此了解不多,但有一些配置选项可能会产生一些影响。

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

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


现在怎么办?

如果您仍在阅读,还有哪些可以优化的地方?

嗯,还有改进的空间……一些面向架构的想法可能是:

  • 切换到n层架构:
    • 将MySQL放在另一台服务器上 (2 层:一个用于 PHP;另一个用于 MySQL)
    • 使用多个 PHP 服务器 (并在这些用户之间进行负载平衡)
    • 使用另一台机器存储静态文件,使用更轻量级的网络服务器,例如:
      • 轻量级
      • 或者 nginx ——顺便说一句,这个正变得越来越流行。
    • 使用多个 MySQL 服务器、多个 PHP 服务器以及在这些服务器前面的多个反向代理
    • 当然:安装 内存缓存 任何有任意数量的可用 RAM 的服务器上的守护进程,并使用它们来缓存尽可能多的/有意义的。
  • 使用比 Apache “更高效”的东西?
    • 我越来越频繁地听到 nginx, ,这对于 PHP 和大容量网站来说应该是很棒的;我自己从未使用过它,但您可能会在网上找到一些关于它的有趣文章;

好吧,也许其中一些想法在你的情况下有点矫枉过正^^
但是,还是……为什么不研究一下它们,以防万一呢?;-)


那么科哈纳呢?

您最初的问题是关于优化使用 Kohana 的应用程序......嗯,我已经发了一些 适用于任何 PHP 应用程序的想法...这意味着它们也适用于 Kohana ;-)
(即使没有具体说明^^)

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

我还说,没有必要的事情不要做,不要做。Kohana 中是否有默认启用但您不需要的功能?
浏览网络,似乎至少有一些关于XSS过滤的内容;你需要那个吗?

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


结论?

最后,一个简单的想法:

  • 贵公司支付你 5 天的工资需要多少钱? -- 考虑到进行一些重大优化是合理的时间
  • 贵公司购买要花多少钱 (付费?) 第二台服务器及其维护?
  • 如果你必须扩大规模怎么办?
    • 花10天要花多少钱?更多的?优化应用程序的每一个可能的部分?
    • 如果再加几个服务器要多少钱?

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

哦,还有,顺便说一句:在做任何事情之前: 放置一些监控东西, ,这样您就知道进行了哪些改进以及如何改进!
如果没有监控,你将不知道你所做的事情的效果......即使它是不是真正的优化也不是!

例如,你可以使用类似的东西 RRD工具 + 仙人掌.
向你的老板展示一些漂亮的图形并且 CPU 负载下降了 40% 总是很棒;-)


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

其他提示

使用 X调试WinCacheGrind 或者 Web缓存研磨 分析和分析缓慢的代码执行。

WebCacheGrind
(来源: jokke.dk)
WinCacheGrind

的XDebug

资料代码

使用很多缓存。如果您的网页是相对静态的,那么反向代理可能是做到这一点的最好办法。

Kohana的是开箱非常非常快,只是使用的数据库对象。引述Zombor“你可以确保你正在使用的数据库结果对象,而不是结果阵列减少内存的使用。”这使得对正在抨击一个网站HUGEE性能差异。它不仅使用更多的存储器,它减慢脚本的执行。

此外 - 你必须使用缓存。我喜欢的memcache,并用它在我的模型是这样的:

public function get($e_id)
{
    $event_data = $this->cache->get('event_get_'.$e_id.Kohana::config('config.site_domain'));

    if ($event_data === NULL)
    {
        $this->db_slave
            ->select('e_id,e_name')
            ->from('Events')
            ->where('e_id', $e_id);

        $result = $this->db_slave->get();
        $event_data = ($result->count() ==1)? $result->current() : FALSE;

        $this->cache->set('event_get_'.$e_id.Kohana::config('config.site_domain'), $event_data, NULL, 300); // 5 minutes
    }

    return $event_data;
}

这也将显着提高性能。上述两种技术由80%提高了网站的性能。

如果你给什么地方你认为瓶颈是一些更多的信息,我敢肯定,我们可以提供一些更好的想法。

还检查了YSlow的(谷歌它),用于其它一些性能的提示。

与 Kohana 密切相关(您可能已经这样做过,也可能没有):

在生产模式下:

  1. 启用内部缓存(这只会缓存 Kohana::find_file 结果,但这实际上有很大帮助。
  2. 禁用分析器

只是我的 2 美分:)

我完全的XDebug和缓存的答案一致。不要直视Kohana的层进行优化,直到你确定你的最大速度和规模的瓶颈。

XDebug的会告诉你,是你花大部分的时间在你的代码识别“热点”。保持这个分析信息,以便您可以基线和衡量性能的提升。

实施例和问题的解决方案: 如果你发现你建立了每次从数据库昂贵的对象,没有真正改变的时候,那么你可以看看用的memcached或其他机制缓存他们。所有这些性能的修复需要时间和复杂性添加到您的系统,所以要确保您的系统瓶颈的你开始修复之前。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top