Xitrum学习笔记16 - Server端缓存
Xitrum为快速响应提供了大量的客户端和服务器端缓存。
在web服务层,小文件被缓存在内存中,大文件通过NIO零拷贝被发送。关于零拷贝可参照https://my.oschina.net/plucury/blog/192577
Xitrum的静态文件响应速度类似于Nginx。
在Web框架层,可以以Rails的方式声明page、action和对象缓存。
Google所有的最好的经验例如 条件Get 被应用到客户端缓存。
对于动态内容,如果内容在创建后没有改变(像静态文件一样),可以通过在action中调用setClientCacheAggressively()方法设置头信息让客户端主动缓存。
有时要避免客户端缓存,可以在action中调用setNoClientCache()方法。
缓存页面或action
import xitrum.Action import xitrum.annotation.{GET, CacheActionMinute, CachePageMinute} @GET("articles") @CachePageMinute(1) class ArticlesIndex extends Action { def execute() { ... } } @GET("articles/:id") @CacheActionMinute(1) class ArticlesShow extends Action { def execute() { ... } }
处理请求的顺序: (1) request -> (2) before过滤器方法 -> (3) action的execute方法-> (4) response
对于第一个请求,Xitrum会缓存响应一段指定的时间。@CachePageMinute(1) 和@CacheActionMinute(1) 都表示缓存1分钟。
Xitrum只在响应状态为"200 OK"时缓存响应,其他如“500 Internal Server Error” or “302 Found” (redirect) 不会缓存响应。
以下对相同的action进行的请求,如果响应已缓存的时间还在指定的时间内,Xitrum会响应返回已缓存的响应:
- 对于page缓存,顺序是 (1)->(4)
- 对于action缓存,顺序是 (1) -> (2) -> (4), 或者当一个before过滤器返回false时只有 (1) -> (2)
两者区别是,对于page缓存,before过滤器不会运行。
一般地,当相同的响应可以返回给所有的用户时,可以使用page缓存;
当需要运行before过滤器从而引导到以缓存的响应时,使用action缓存。如检查用户是否已登录,已登录则返回已缓存的响应,没登录则重定向到登录页面。
缓存对象
可以使用xitrum.Config.xitrum.cache里的方法,它是 xitrum.Cache的一个实例。
没有指定TTL(time to live存活时间)时,使用put(key, value)
指定了TTL时,使用putSecond(key, value, seconds),putMinute(key, value, minutes),putHour(key, value, hours),putDay(key, value, days)
只要有缺失,putIfAbsent(key, value),putIfAbsentSecond(key, value, seconds),putIfAbsentMinute(key, value, minutes),putIfAbsentHour(key, value, hours),
putIfAbsentDay(key, value, days)
移除缓存
移除page或action缓存:removeAction[MyAction]
移除对象缓存:remove(key)
移除所有以某前缀开始的key:removePrefix(keyPrefix)
使用removePrefix,可以基于前缀组成一个层级的缓存结构。例如,你要缓存和文章相关的内容,当文章变化时你要删除所有这些内容:
import xitrum.Config.xitrum.cache // Cache with a prefix val prefix = "articles/" + article.id cache.put(prefix + "/likes", likes) cache.put(prefix + "/comments", comments) // Later, when something happens and you want to remove all cache related to the article cache.remove(prefix)
配置
Xitrum中的缓存功能由缓存引擎提供,你可以选择符合需求的引擎。
在config/xitrum.conf中,你可以通过以下两种方式的一种配置缓存引擎,这也取决于所选择的引擎:
cache = my.cache.EngineClassName #或者: cache { "my.cache.EngineClassName" { option1 = value1 option2 = value2 } }
Xitrum默认提供的是
cache { # Simple in-memory cache "xitrum.local.LruCache" { maxElems = 10000 } }
如果使用的是一个服务器集群,可以使用 Hazelcast(https://github.com/xitrum-framework/xitrum-hazelcast)。
如果想创建自己的缓存引擎,需要实现 xitrum.Cache类
缓存如何工作
Inbound:
the action response
should be cached and
request the cache already exists?
-------------------------+---------------NO--------------->
|
<---------YES----------+
respond from cache
Outbound:
the action response
should be cached and
the cache does not exist? response
<---------NO-------------+---------------------------------
|
<---------YES------------+
store response to cache
xitrum.util.LocalLruCache
以上的缓存可以在整个系统中共享,如果只想要一个小的方便的缓存,可以使用xitrum.util.LocalLruCache
import xitrum.util.LocalLruCache // LRU (Least Recently Used) cache that can contain 1000 elements. // Keys and values are both of type String. val cache = LocalLruCache[String, String](1000)
返回的cache是一个 java.util.LinkedHashMap,可以使用LinkedHashMap的方法