本文主要是介绍Play framework 1.2.3 使用缓存、Memcached集成,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
- play框架包含一个缓存lib,这个lib是用来和Memcached集成做分布式缓存用的。
如果不配置Memcached,play框架将会使用单独的缓存(EhCache),其数据存储在JVM的堆中。把数据存储在JVM的堆中 违反了play框架“不共享任何东西”的原则,这也导致了你不能把应用程序同时部署到多个机器,即不能在多个机器上负载均衡以保证应用的可用性、高性能(即使在多个机器部署了相同的应用,但是由于不同机器的JVM是相互独立的,会导致不同机器的缓存数据不同,即不同机器对同一请求的响应可能不同!不一致性!)
理解缓存的应用环境是很重要的:当你把数据放到缓存中, 你不能期望数据在缓存中一直存在。实际上,你不应该这样想。缓存中存取数据很快,但是缓存是有有效期的、并且缓存数据是存放在内存中(并没有做持久化备份)。
因此最佳使用缓存的方式是当发现缓存的数据不存在时,直接从数据源重新抓取。
- public static void allProducts() {
- List<Product> products = Cache.get("products", List.class);
- if(products == null) {
- products = Product.findAll();
- Cache.set("products", products, "30mn");
- }
- render(products);
- }
缓存API:
play框架中的缓存类 play.cache.Cache,其包含了从缓存中取值,设值,替换值的方法。
例子:
- public static void showProduct(String id) {
- Product product = Cache.get("product_" + id, Product.class);
- if(product == null) {
- product = Product.findById(id);
- Cache.set("product_" + id, product, "30mn");
- }
- render(product);
- }
- public static void addProduct(String name, int price) {
- Product product = new Product(name, price);
- product.save();
- showProduct(product.id);
- }
- public static void editProduct(String id, String name, int price) {
- Product product = Product.findById(id);
- product.name = name;
- product.price = price;
- Cache.set("product_" + id, product, "30mn");
- showProduct(id);
- }
- public static void deleteProduct(String id) {
- Product product = Product.findById(id);
- product.delete();
- Cache.delete("product_" + id);
- allProducts();
- }
上面的delete, set等标准方法都是 非阻塞的。也就是说,当你调用
- Cache.delete("product_" + id);
时,delete方法不等缓存对象真的被删除就直接返回。所以,如果在删除缓存对象时发生错误(譬如IO错误),那么缓存对象是仍然存在的。
sateDelete方法: 阻塞的,在缓存对象真的被删除后,方法才会返回,方法有bool型的返回值来表明操作是否成功。
注意:
- 由于是阻塞方法,使用safe前缀的方法会降低应用的响应速度。因此,只在需要时才那么使用。
- 当指定参数expiration == "0s"(0秒)时,缓存实际的失效时间可能由于不同的缓存实现相差很大。
不要把Session当缓存使用!
当你用过基于内存Session实现的框架的话、如Servlet中的HTTP Session( play框架中的session是以Cookie形式存储在客户端的),你可能会对play框架中只允许在session中以String的形式存储少量数据感到不习惯。在play框架中,session并不是你存储应用数据的地方。
基于内存的Session,使用例子:
- httpServletRequest.getSession().put("userProducts", products);
- ...
- // and then in subsequent requests
- products = (List<Product>)httpServletRequest.getSession().get("use
- rProducts");
play框架等效实现:
- Cache.set(session.getId(), products);
- ...
- // and then in subsequent requests
- List<Product> products = Cache.get(session.getId(), List.class)
这里我们使用唯一的UUID来作为每个用户缓存的key。注意:和session不同的是, 缓存并不会绑定到任何一个用户中,缓存在整个应用中是共享的。
集成Memcached缓存配置(application.conf文件):
memcached:时候启用Memcached缓存,如果不配置,那么play默认使用单独的缓存EhCache,其数据存储在JVM的堆中。可能值:disabled(默认),enabled
memcached.host:启用Memcached时,指定memcached host地址,默认值:127.0.0.1:11211。
memcached.host=127.0.0.1:11211
多个host做分布式缓存时,如下配置:
memcached.1.host=127.0.0.1:11211
memcached.2.host=127.0.0.1:11212
Unmi 注: EhCachePlugin 的注册方式可以查看 play_x.x.x.jar(比如 $PLAY_HOME/repository/local/play/play_2.9.1/2.0.4/jars/play_2.9.1.jar) 包中的 play.plugins 中的内容:
1 2 3 4 5 6 7 8 | 100:play.api.i18n.MessagesPlugin 200:play.api.db.BoneCPPlugin 300:play.db.ebean.EbeanPlugin 400:play.db.jpa.JPAPlugin 500:play.api.db.evolutions.EvolutionsPlugin 600:play.api.cache.EhCachePlugin 1000:play.api.libs.concurrent.AkkaPlugin 10000:play.api.GlobalPlugin |
这是 Play2.0.4 默认注册的插件,其中就包含了 600:play.api.cache.EhCachePlugin 插件。
使用下面简单的 API,你就可以往缓存中存数据了:
1 | Cache.set( "item.key" , connectedUser) |
之后获取它:
1 | val maybeUser : Option[User] = Cache.getAs[User]( "item.key" ) |
当缓存数据不存在时,还有一个帮助方法在你获取或设置缓存数据给你带来了便利:
1 2 3 | val user : User = Cache.getOrElseAs[User]( "item.key" ) { User.findById(connectedUser) } |
缓存 HTTP 响应数据
你可以用标准的 Action 组合简单的创建一个聪明的具体缓存特性的 Action.
注: Play HTTP
Result
实例可安全的被缓存并被重用.
Play 提供了默认, 内建的方式来应对标准的情况:
1 2 3 4 5 | def index = Cached( "homePage" ) { Action { Ok( "Hello world" ) } } |
或者甚至是这样:
1 2 3 4 5 6 7 | def userProfile = Authenticated { user = > Cached(req = > "profile." + user) { Action { Ok(views.html.profile(User.find(user))) } } } |
这篇关于Play framework 1.2.3 使用缓存、Memcached集成的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!