我正在撰写Catalyst应用程序,我有Model代表一个小的设置表,其值不会发生变化。我不是每次都要查询数据库,而是要缓存响应。在我使用DBIx::Class的模型中,我确实看到了DBIx::Class::Cursor::Cached,这看起来像一个选项。
但是,我最终做的是使用Memoize来缓存模型中的返回值。关于这个解决方案我有两个问题:
Catalyst模型是否只创建一次,然后用于应用程序的生命周期?或者$c->model()
每次都创建一个新的Model类?
如果我使用fastcgi运行我的应用程序并且有6个线程,这意味着我的应用程序的每个线程都将获得自己的模型类,并且必须进行查询并且需要6个单独的缓存,正确?
这是一个糟糕的解决方案吗?我应该做些什么吗?
答案 0 :(得分:2)
Catalyst模型是否只创建一次,然后用于应用程序的生命周期?或者
$c->model()
每次都创建一个新的Model类吗?
这取决于您对模型的实施。如果模型中有ACCEPT_CONTEXT
方法,则每次调用$c->model()
时,Catalyst都会生成一个新对象。如果没有,它将在应用程序启动期间实例化一次。这在初始化下的Catalyst::Manual::Internals中有记录。
在YAPC::EU 2016 in Cluj,Catalyst的当前维护者John Napiorkowski发表了关于Catalyst的(远程)谈话,解释了从from about 53 minutes into the talk开始的这个方面。整个事情以及他的其他演讲值得关注。
如果我使用fastcgi运行我的应用程序并且有6个线程,这意味着我的应用程序的每个线程都将获得自己的模型类,并且必须进行查询并且需要6个单独的缓存,对吗?
我不确定那个。我相信它会启动一次,然后分叉。所以它会创建一个实例并将其复制到fork。
使用DBIx :: Class :: Cursor :: Cached为您的方法看起来会起作用。如果你需要DBIx :: Class ResultSet对象,那很好。如果没有,您可以将结果作为惰性属性附加到模型中。它可能看起来像这样:
package My::Model;
use Mooose;
use My::DB::Schema;
extends 'Catalyst::Model';
has stuff => (
is => 'ro',
isa => 'HashRef',
traits => ['Hash'],
handles => {
has_stuff => 'exists',
get_stuff => 'get',
# ...
},
lazy => 1,
builder => '_build_stuff',
);
sub _build_stuff {
my ($self) = @_;
# get stuff from the DB here, convert it to a config hash
# or whatever you need and store it in our stuff attribute
# that works well if your config looks something like this:
# {
# color => 'red',
# price => 13.37,
# things => [ qw/ foo bar baz / ],
# # ...
# }
# you can then use the Hash trait on your attribute to access it
}
1;
这样它会在你第一次使用它时加载它,然后你就完成了。它只会存储在对象中。
如果您想调查实际上是否有效并且不执行更多查询,可以使用DBIC_TRACE=1
环境变量启用DBIC 's tracing output。它会将彩色查询转储到您的Catalyst日志中。
或者,CHI非常适合构建缓存的东西,虽然这里可能有点矫枉过正。