我使用Kohana框架构建的网站昨天遭遇了大量的访问流量,导致我不得不回头评估一些设计。我想知道有哪些标准技术可用于优化基于Kohana的应用程序?
我对基准测试也很感兴趣。我是否需要为每个控制器方法设置 Benchmark::start()
和 Benchmark::stop()
以便查看所有页面的执行时间,或者我可以全局和快速地应用基准测试?
我将在以后更多地使用Cache库,但是我对其他建议也持开放态度,因为我相信目前还有很多我不知道的东西。
我使用Kohana框架构建的网站昨天遭遇了大量的访问流量,导致我不得不回头评估一些设计。我想知道有哪些标准技术可用于优化基于Kohana的应用程序?
我对基准测试也很感兴趣。我是否需要为每个控制器方法设置 Benchmark::start()
和 Benchmark::stop()
以便查看所有页面的执行时间,或者我可以全局和快速地应用基准测试?
我将在以后更多地使用Cache库,但是我对其他建议也持开放态度,因为我相信目前还有很多我不知道的东西。
我将在这个答案中说的内容不仅适用于Kohana,也可以适用于许多PHP项目。
以下是我谈到性能、可扩展性、PHP等方面时想到的一些要点...
我在几个项目中使用了许多这些想法——它们起到了帮助作用;所以它们可能在这里也有所帮助。
首先,当涉及到性能时,有许多方面/问题需要考虑:
第一件非常有用的事情是使用反向代理,像varnish这样,在您的Web服务器前面: 让它尽可能缓存许多东西,因此只有真正需要PHP / MySQL计算(当然,还有其他请求,当它们不在代理的缓存中时)才会到达Apache / PHP / MySQL。
首先,你的CSS/Javascript/Images -- 以及所有静态内容 -- 可能不需要总是由Apache提供服务,所以你可以让反向代理缓存所有这些内容。对于Apache来说,提供这些静态文件并不是什么大问题,但是它需要处理的越少,就越能够处理PHP。请记住:Apache一次只能提供有限数量的请求。关于此,我如何检测和幸存于“Slashdot”?可能是一篇有趣的阅读。
首先:您是否使用了最新版本的PHP?新版本通常会有速度上的改进;-)
例如,看看PHP分支3.0到5.3-CVS的基准测试。
请注意,性能是使用PHP 5.3的相当好的理由(我进行了一些基准测试(用法语), 结果很棒)...
另一个非常好的理由当然是,PHP 5.2已经到达了生命周期的尽头,不再维护!
[apc.stat](https://php.net/manual/en/apc.configuration.php#ini.apc.stat)
对系统负载有好处;但这意味着除非刷新整个opcode-cache,否则不会考虑对PHP文件所做的修改;关于此问题,有关详细信息,请参见To stat() Or Not To stat()?尽可能地避免重复做同样的事情,这是最好的。
主要考虑到SQL查询:你的许多页面可能做相同的查询,其中一些结果几乎总是相同的...这意味着数据库需要花费时间一次又一次地提供相同的数据,造成了大量"无用"的查询。
当然,对于其他东西也是如此,比如Web服务调用、从其他网站获取信息、重计算等等...
你可能会发现以下内容非常有趣:
并将这些数据/结果存储在某种缓存中,以便更容易地获取——更快——而不必为"无用"的查询去访问SQL服务器。
出色的缓存机制包括:
我相信你的框架已经带有一些缓存相关的东西;你可能已经知道了,因为你在原文中说过"未来我会更多地使用缓存库";-)
现在,一个好的做法是使用Xdebug扩展来对应用程序进行性能分析:如果有任何需要花费大量时间的函数,它通常可以轻松找到一些薄弱点。
正确配置后,它将生成可由某些图形工具分析的性能分析文件,例如:
例如,这里有几张KCacheGrind的截图:
(来源: pascal-martin.fr)
(来源: pascal-martin.fr)
(顺便说一句,如果我没记错的话,第二个截图所呈现的调用图通常是WinCacheGrind和Webgrind都不能做到的 ^ ^)
(感谢@Mikushi的评论) 另一个我没怎么用过的可能性是xhprof扩展程序:它也有助于分析,可以生成调用图 - 但比Xdebug更轻量级,这意味着你应该能够在生产服务器上安装它。
您应该能够与XHGui一起使用它,这将有助于数据的可视化。
既然我们已经谈论了一些PHP的内容,需要注意的是,你的瓶颈可能不在PHP方面,而是在数据库方面...
这里至少有两三件事:
EXPLAIN
指令
log_slow_queries
以获取需要花费过多时间的请求列表,并从这些请求开始进行优化。尽管如此,最重要的两件事情是:
如果你仍在阅读,还有什么可以优化的呢?
好吧,仍然有改进的空间... 一些面向架构的想法可能是:
好吧,也许在你的情况下有些想法有点过头了^^
但是,为什么不学习一下它们,以防万一呢?;-)
你最初的问题是关于优化使用 Kohana 的应用程序... 好吧,我发布了一些适用于任何 PHP 应用程序的想法... 这意味着它们也适用于 Kohana;-)
(即使不是专门针对它 ^^)
我说过:使用缓存;Kohana 似乎支持一些缓存相关的东西 (你自己谈到过,所以没有新内容...)
如果有什么可以快速完成的事情,请尝试;-)
我还说你不应该做任何不必要的事情;Kohana 中是否启用了你不需要的任何功能?
在浏览网络时,似乎至少有一些与 XSS 过滤有关的内容;你需要它吗?
此外,以下是几个可能有用的链接:
最后,一个简单的想法:
我并不是说您不应该进行优化:您肯定应该!
但是首先要进行“快速”优化,这将为您带来巨大的回报:使用某些操作码缓存可以帮助您减少服务器的CPU负载10%至50%……设置只需几分钟;-) 另一方面,为2%花费3天......
哦,顺便说一句:在做任何事情之前:先放置一些监控工具,以便您知道已经取得了什么改进和效果!
没有监控,您将不知道您所做的效果...甚至不知道它是否是真正的优化!
例如,您可以使用RRDtool + cacti之类的工具。
向老板展示一个CPU负载下降了40%的漂亮图形总是很棒的;-)
无论如何,最后要说的是: 玩得开心!
(没错,优化也很有趣!)
(额,我没想到我会写这么多...希望至少有些部分对你有用...我应该记住这个答案:可能在其他时候也会有用...)
Kohana开箱即用非常快,除了使用数据库对象。引用Zombor的话:“通过确保使用数据库结果对象而不是结果数组,您可以减少内存使用。”这在受到冲击的网站上会产生巨大的性能差异。它不仅使用更多内存,还会减慢脚本的执行速度。
此外,你必须使用缓存。我喜欢使用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相关(您可能已经完成了这个,或者还没有):
在生产模式下:
只是我的两分钱 :)
我完全同意XDebug和缓存答案。在确定了最大的速度和规模瓶颈之前,不要考虑Kohana层的优化。
XDebug将告诉您花费最多时间的地方,并识别代码中的“热点”。保留此分析信息,以便您可以基准测试和测量性能改进。
问题和解决方案示例: 如果您发现每次从数据库中构建昂贵的对象,这些对象并不经常更改,则可以考虑使用memcached或另一种机制对它们进行缓存。所有这些性能修复都需要时间,并增加了系统的复杂性,因此在开始修复它们之前,请确保您的瓶颈。