Joh*_* N. 6 php ubuntu cakephp cakephp-2.4
我们有一个很大的CakePHP(目前是2.4.7)SAAS-app.它已经非常成熟,直到上周我们才对CakePHPs-core提供的功能有任何实际问题.
上周末我们遇到了一个非常惊人的情况,我们的应用程序变得非常缓慢和错误.我们查看了所有类型的服务器监控,发现在过去几个小时内i/o统计数据暴涨.经过一番调查后,我们将问题分离到了Cake的' cake_core_method_cache '文件中.平均每天,此文件的大小为200 kb.上周末,它达到了约40万桶.
部署例程的一部分是从app/tmp/cache和app/tmp/persistent文件夹中删除所有缓存文件.因为我们经常部署(每天几次),所以缓存会经常被清除.不幸的是,上周的假期暂停了我们的部署,看起来这是核心/缓存功能的问题.
所以,我的两个问题是:
a)有谁知道,为什么cake_core_method_cache会随着时间的推移变大?
b)有没有其他可能解决这个问题,以便不断删除这个文件?
CakePHP 中对 method_cache 的唯一引用位于Dbo Source中。这是一个在整个类中广泛使用的缓存,用于缓存(相对)昂贵的引用操作的结果,或者如相关文档块所示:
缓存查询解析操作的结果。DboSource::name() 和 DboSource::conditions() 的缓存结果将存储在此处。
考虑以下 shell:
<?php
class SoShell extends AppShell {
function main() {
$this->Post = ClassRegistry::init('Post');
$this->Post->find('all', array(
'conditions' => array(
'find-this-text' => 'x'
)
));
debug(DboSource::$methodCache);
}
}
Run Code Online (Sandbox Code Playgroud)
运行它会产生以下输出:
> Console/cake so
########## DEBUG ##########
array(
'name' => array(
'f5442d1f57be5d9d8ac80ae9613d5ff9' => '`database_name`',
'cfacfed443d6f30e67edf9bbcb06ce30' => '`posts`',
'e13d78515036382daf55fa083088c902' => '`Post`.`id`',
'aafd056e6d53878a75ab4ee3f18645a1' => '`Post`.`title`',
'4084e974416e3a7fb06e6a280721637b' => '`Post`.`body`',
'b4f1ad1de4cdc3a3f82e905f8dfd8673' => '`Post`.`created`',
'bfeffce70e344d7606e17c9ff24530b5' => '`Post`.`modified`',
'e42609d9744a7d1ce80c8d838b9ea07c' => '`find-this-text`', # <-
'c0a33fa0f04ac4682dcdc4b25167b3a8' => '`Post`'
),
'fields' => array(
'952d56c2bf037c8195bdd5fba57b1024' => array(
(int) 0 => '`Post`.`id`',
(int) 1 => '`Post`.`title`',
(int) 2 => '`Post`.`body`',
(int) 3 => '`Post`.`created`',
(int) 4 => '`Post`.`modified`'
)
)
)
Run Code Online (Sandbox Code Playgroud)
请注意,缓存包含“用户”(或开发人员)输入,该数组是在请求结束时写入缓存的内容。
此示例还应强调为什么缓存随时间增长 - 缓存取决于迄今为止发出的查询,并且随着时间的推移,应用程序发出更多查询排列,导致方法缓存增长(但通常不会增长很多 MB)。
对于所描述的问题有一个非常简单的修复方法:禁用方法缓存。
即,将以下内容放在应用程序中的任何位置:
DboSource::$cacheMethods = false;
Run Code Online (Sandbox Code Playgroud)
这当然意味着性能下降,因为不会使用方法缓存,因此每个请求都会发生相对昂贵的基于 preg 的引用操作。
如果缓存中充满了“模型的数据库实例” - 很可能某个地方存在应用程序问题。这是不正常的,不应该发生,并且具体取决于应用程序正在执行的操作。鉴于不可能给出具体的解决方案。
但是,如果您可以识别缓存中包含大量数据的任何特定键,则可以使用它来查找负责的查询。例如:
// anywhere
if (isset(DboSource::$methodCache['name']['e42609d9744a7d1ce80c8d838b9ea07c']) {
// a query with find-this-text has been issued somewhere
}
Run Code Online (Sandbox Code Playgroud)
您可以(暂时)将这种逻辑添加到修改 dbo methodCache 属性的位置,以便能够“原位”检测修改:
public function cacheMethod($method, $key, $value = null) {
if ($this->cacheMethods === false) {
return $value;
}
if (!$this->_methodCacheChange && empty(self::$methodCache)) {
self::$methodCache = Cache::read('method_cache', '_cake_core_');
}
if ($value === null) {
return (isset(self::$methodCache[$method][$key])) ? self::$methodCache[$method][$key] : null;
}
$this->_methodCacheChange = true;
// Added
if ($method === 'name' && $key === 'e42609d9744a7d1ce80c8d838b9ea07c') {
App::uses('Debugger', 'Utility');
$this->log("Query with find-this-text in it issued", "wat-debug");
$this->log(Debugger::trace(), "wat-debug");
}
// Added end
return self::$methodCache[$method][$key] = $value;
}
Run Code Online (Sandbox Code Playgroud)
这将使您能够识别直接负责将大量数据注入方法缓存的因素;然后更正应用程序代码,以便可以按设计启用和使用方法缓存。
归档时间: |
|
查看次数: |
745 次 |
最近记录: |