优化基于Kohana的网站以提高速度和可扩展性


80

我与Kohana一起建立的网站昨天遭到了巨大的点击量,这使我退后一步并评估了一些设计。我很好奇什么是优化基于Kohana的应用程序的一些标准技术?

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

我将在更多时间使用Cache库,但是我愿意接受更多建议,因为我敢肯定,目前我还不知道有很多事情可以做。


您是否尝试过构建Kohana Profiler以获得应用程序的一些信息?这非常好
Yasen Zhelev

Answers:


211

我将在此答案中说的并不是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每次用户请求时重新生成它们的时间。
  • 为匿名用户服务的页面(所有匿名用户的页面都相同)和为已标识用户服务的页面之间可能有所区别(例如“您好,先生,您有新消息”)
    • 如果是这样,您可能可以配置反向代理以缓存为匿名用户提供的页面(通常基于cookie,例如会话cookie)
    • 这意味着Apache + PHP的工作量更少:只有确定的用户-这可能只是您用户的一小部分。

例如,关于使用反向代理作为缓存,对于PHP应用程序,您可以看一下Benchmark结果,结果显示APC和Squid Cache的服务器功能增加了400%-700%
(是的,他们正在使用Squid,而我在讲的是清漆,这是另一种可能性^^清漆是较新的,但更致力于缓存)

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


旁注:您在OP中说:

我与Kohana一起建立的网站昨天遭到了巨大的点击量,

这是什么样的突发情况,其中一个反向代理可以从字面上保存一天,如果你的网站可以处理不是最多为第二个日期:

  • 安装,配置,让它始终(每天正常运行):
    • 配置它以不将PHP页面保留在缓存中;或仅持续很短的时间;这样,您总是可以显示最新数据
  • 而且,在您进行斜线或digg效果的那一天:
    • 配置反向代理以将PHP页面保留在缓存中;或更长的时间;也许您的页面不会在第二秒之前更新,但是它将使您的网站能够幸免于难!

关于这一点,如何发现被“斜线点缀”并使之幸存?可能是一个有趣的阅读。


在PHP方面:

首先:您是否正在使用最新版本的PHP?新版本通常会定期提高速度;-)
例如,看一下PHP Branches 3.0到5.3-CVS的Benchmark

请注意,性能是使用PHP 5.3的一个很好的理由我已经做了一些基准测试(法语),并且结果很棒) ……
另一个相当好的理由是,当然,PHP 5.2已经寿终正寝了。 ,并且不再维护!

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

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


使用数据缓存

尽可能避免一遍又一遍地做同一件事

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

您可能会很感兴趣地找出:

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

并将这些数据/结果存储在某种缓存中,因此它们更容易获得-更快-并且您不必为了任何事情而去SQL服务器。

出色的缓存机制例如:

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

我很确定您的框架中包含一些与缓存相关的内容;您可能已经知道这一点,正如您在OP中所说的:“我将在更多时间使用Cache-library”;-)


剖析

现在,要做的一件好事是使用Xdebug扩展来分析您的应用程序:它通常可以很容易地找到几个弱点-至少,如果有任何函数需要花费很多时间。

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

  • KCachegrind:我最喜欢的,但是仅在Linux / KDE上有效
  • Windows的Wincachegrind;不幸的是,它比KCacheGrind少了一些东西-通常它不显示调用图。
  • Webgrind在PHP网络服务器上运行,因此可以在任何地方使用-但可能功能较少。

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

KCacheGrind:主屏幕
(来源:pascal-martin.fr(来源:pascal-martin.fr
KCacheGrind:导出为图像的Callgraph

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


(感谢@Mikushi的评论)我没有使用太多的另一种可能性是xhprof扩展名:它也可以进行概要分析,可以生成调用图-但比Xdebug轻,这意味着您应该可以在其上安装生产服务器。

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


在SQL方面:

现在我们已经讨论了一些关于PHP的知识,请注意,您的瓶颈很可能不是PHP方面的东西,而是数据库方面的东西

至少有两三件事:

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

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

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


现在怎么办?

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

嗯,还有改进的余地...一些面向体系结构的想法可能是:

  • 切换到n层架构:
    • 将MySQL放在另一台服务器上(2层:一个用于PHP;另一个用于MySQL)
    • 使用多个PHP服务器(并在这些服务器之间平衡用户负载)
    • 使用较轻的网络服务器将另一台机器用于静态文件,例如:
    • 将多个服务器用于MySQL,将多个服务器用于PHP,并在其前面使用多个反向代理
    • 当然:在任何具有任何可用RAM的服务器上安装memcached守护程序,并使用它们尽可能多地缓存/有意义。
  • 使用Apache的“更有效”的工具?

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


那Kohana呢?

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

我说:使用缓存;Kohana似乎支持某些缓存内容 (您自己说过,所以这里没有新内容...。)
如果可以快速完成任何操作,请尝试;-)

我还说过,您不应做任何不必要的事情;默认情况下,Kohana是否有不需要的功能?
浏览网络,似乎至少与XSS过滤有关;你需要那个吗?

不过,这里有一些可能有用的链接:


结论?

最后,有一个简单的想法:

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

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

哦,顺便说一句:在做任何事情之前:放置一些监视内容,以便您知道已进行了哪些改进以及如何进行改进!
如果没有监控,您将不会知道自己所做的工作的效果……即使这不是真正的优化,也是如此!

例如,您可以使用RRDtool + cacti之类的东西。
向您的老板展示一些不错的图形,CPU负载下降40%总是很棒的;-)


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


虽然添加新服务器可能比让开发人员工作5天便宜,但不要忘记从多个服务器上运行时您的软件可能无法正常工作(您可能必须以某种方式在服务器之间共享文件-NFS可能会很麻烦,您使用会话?最好将其移至数据库等)。而且这本身就需要开发人员也要努力。
NSSec

16
很好的解释!你有我可以订阅的博客吗?:-)
Gray Panther

@ dnh828:我写了它,希望在其他一些场合可以重复使用(实际上我已经这样做了);@MathieuK:绝对正确(不过,关于会话,而不是DB,您也可以设想使用memcache);@ Cd-MaN:谢谢!我实际上确实有一个博客,但是它是法语的,并且我确实不经常写博客...仍然,如果您有兴趣的话:blog.pascal-martin.fr
Pascal MARTIN

考虑看一下XHProf(pecl.php.net/package/xhprof),我发现它比XDebug更好地配置我的代码,特别是在生产服务器上,并结合到XHGui(github.com/preinheimer/xhprof),这是我的荣幸跟...共事。
Mikushi 2011年

太糟糕了,不是吗?;-) ;; 但是,您可以使用stackoverflow.com/q/1260134/138475链接来共享此问题,以便更多的人可以阅读此答案(这就是为什么我写了这么长的答案的原因:被阅读^^)
Pascal MARTIN


5

XDebug的配置文件代码。

使用大量缓存。如果您的页面相对静态,那么反向代理可能是最好的方法。


5

Kohana开箱即用非常快,除了使用数据库对象外。引用Zombor:“可以通过确保使用数据库结果对象而不是结果数组来减少内存使用。” 这使被猛击的站点上的HUGEE性能有所不同。它不仅使用更多的内存,而且减慢了脚本的执行速度。

另外-您必须使用缓存。我更喜欢内存缓存,并在我的模型中使用它,如下所示:

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(google it)了解其他一些性能提示。


1

与Kohana紧密相关(您可能已经或没有这样做):

在生产模式下:

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

只是我的2美分:)


0

我完全同意XDebug和缓存的答案。在确定最大的速度和规模瓶颈之前,不要对Kohana层进行优化。

XDebug会告诉您是您花费了最多的时间,并在代码中标识了“热点”。保留此概要分析信息,以便您可以确定基准并衡量性能改进。

问题和解决方案示例:如果您发现每次都在数据库中构建昂贵的对象,并且这些对象实际上并不经常更改,那么您可以考虑使用memcached或其他机制对它们进行缓存。所有这些性能修复都需要花费时间并增加系统的复杂性,因此在开始修复它们之前,请先确定瓶颈。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.