【问题标题】:Store result into cache in Play 2.2在 Play 2.2 中将结果存储到缓存中
【发布时间】:2015-11-19 11:03:41
【问题描述】:

在 Play framework 2.2 中创建当前请求的结果非常简单。我们只输入:

Ok(views.html.default.render())

然后让它工作就足够了,用Action来包装,所以最终的代码如下:

def index = Action {
  Ok(views.html.default.render())
}

没关系。但是现在,我想将响应存储在缓存中以使其更具可扩展性。我使用 EHCache。问题是,当我将它存储到缓存中时,它会抛出

NotSerializableException: play.api.mvc.ActionBuilder$$anon$1

我试图至少缓存它自己的结果,但它抛出了

ERROR net.sf.ehcache.store.disk.DiskStorageFactory Disk Write of result-key failed: 
java.io.NotSerializableException: play.api.libs.iteratee.Enumerator$$anon$18

我知道,这些值存储在缓存中,但仅存储在内存中,考虑到真正的高负载和许多不同的响应,这可能是非常不够的。

问题:

所以我的问题是,是否有任何方法可以完全缓存 Play 操作/结果,包括正确的序列化?

编辑:

我如何尝试使用缓存:我不使用Cached {},因为它的行为并不完全符合我的需要,所以我尝试以自己的方式设计它。因此,出于测试目的,我现在更详细地使用它:

Cache.set("myaction", Action {
  Ok(views.html.default.render())
})

Cache.set("myresponse", Ok(views.html.default.render()))

但这两者都会产生上述异常。

关于缓存:Play 缓存 API 对我来说是不够的,所以我通过另外几个方法和新的插件实现来扩展它。起初我尝试只复制默认插件并实现这些扩展,但有一些问题,所以我修复了它们,推荐here。这是插件修复。从那时起,它似乎实际上使用了 EHCache(从那些异常中猜测)。

【问题讨论】:

  • 如何将结果存储到缓存中?
  • @mantithetical 请看我的编辑

标签: caching playframework-2.0 ehcache


【解决方案1】:

在我看来,您不是在尝试将结果存储在缓存中,而是在包含无法序列化的闭包的操作中,我想这不是您想要做的,我想这是因为你是直接用 EHCache 吗?

如果您使用 Play 缓存 API,它应该可以帮助您做正确的事情。你可以在这里找到它的文档:http://www.playframework.com/documentation/2.2.x/ScalaCache

响应可能仍然无法序列化,如果你真的想要一个序列化到磁盘的缓存,你应该能够缓存模板生成的 HTML,因为它基本上是一个字符串,然后重新使用它,但创建一个每个请求的新响应。

(我的直觉是,每次渲染模板可能会比缓存从磁盘读取它获得更好的性能,除非你有一些非常疯狂的复杂模板)

【讨论】:

  • 感谢您的回复。我试图存储结果和动作——我说的是有问题的,关于你可能是对的动作。我不确定直接使用缓存是什么意思,但我已经稍微改进了默认实现。请查看我的问题编辑。您说缓存操作不是一个好主意。自己缓存结果呢?就像我在编辑中展示的那样。无论如何,我想知道 Play 缓存是如何工作的,因为那里支持缓存响应......它只是一些没有序列化到 FS 的内存缓存吗?
  • 它从不序列化,只是将对象保存在内存中。您可以在 play.jar/ehcache.xml 和播放分发随附的播放源中找到默认播放缓存配置,您还可以在其中仔细查看缓存实现以了解其工作原理。
  • 所以如果我还想缓存动作以快速响应,你建议我使用两个缓存吗?一种对公共数据进行序列化,另一种对结果没有序列化?
  • 我认为您应该查看 Cached 类的实现以了解它的工作原理,然后根据该理解实现您的自定义。另外,请确保进行基准测试/配置文件,也许只是缓存您的回复所需的数据就是您所需要的,并且操作逻辑无关紧要!
  • 即使对于 2.4.x,它也是一个启发性的问题和答案。使用 redis 作为缓存模块时,我遇到了(几乎)同样的问题。现在我真的对 play 的文档有疑问。
【解决方案2】:

不确定它是否适用于 2.2,但是据我报告的issue

如果您直接从 CacheApi 的实现调用 set 方法,并且该实现需要一个可序列化的对象,请使用 wrapper,它也被 @cached 助手使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-31
    • 1970-01-01
    • 2012-07-24
    • 1970-01-01
    • 2017-04-02
    • 1970-01-01
    • 2018-07-25
    相关资源
    最近更新 更多