Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 730|回复: 0

[jsp学习]给WEB应用加JCS缓存系统

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-1 10:08:40 | 显示全部楼层 |阅读模式
    我想把一个基于数据库的WEB应用程序加上缓存,以提高性能,开源的java缓存系统不少,先拿JCS( Java Caching System)试试。      关于JCS的介绍,小红帽的文章已写得非常清楚了,附后。
          先到http://jakarta.apache.org/jcs/Downloads.HTML
    下载jcs-1.2.6.jar,找了半天也没有找到它的源码和API文档,不知为什么? 在这个站点有:
    Using JCS: Some basics for the web ,不错,就用它练习。

    一、创建值对象
    假设有一BOOK,它在数据库中的表为:
    Table BOOK
       BOOK_ID_PK
       TITLE
       AUTHOR
       ISBN
       PRICE
       PUBLISH_DATE

      
      
      
      
       
      
    创建值对象如下:
    1. package com.genericbookstore.data;
    2. import java.io.Serializable;
    3. import java.util.Date;
    4. public class BookVObj implements Serializable
    5. {
    6.     public int bookId = 0;
    7.     public String title;
    8.     public String author;
    9.     public String ISBN;
    10.     public String price;
    11.     public Date publishDate;
    12.     public BookVObj()
    13.     {
    14.     }
    15. }
    16.         
    复制代码
    二、创建缓存管理器
    应用中对book数据的访问都通过缓存管理器。
    1. package com.genericbookstore.data;
    2. import org.apache.jcs.JCS;
    3. // in case we want to set some special behavior
    4. import org.apache.jcs.engine.behavior.IElementAttributes;
    5. public class BookVObjManager
    6. {
    7.     private static BookVObjManager instance;
    8.     private static int checkedOut = 0;
    9.     public static JCS bookCache;
    10.     private BookVObjManager()//构造函数
    11.     {
    12.         try
    13.         {
    14.             bookCache = JCS.getInstance("bookCache");
    15.         }
    16.         catch (Exception e)
    17.         {
    18.             // Handle cache region initialization failure
    19.         }
    20.         // Do other initialization that may be necessary, such as getting
    21.         // references to any data access classes we may need to populate
    22.         // value objects later
    23.     }
    24.     /**
    25.      * Singleton access point to the manager.
    26.      */
    27.     public static BookVObjManager getInstance()
    28.     {
    29.         synchronized (BookVObjManager.class)
    30.         {
    31.             if (instance == null)
    32.             {
    33.                 instance = new BookVObjManager();
    34.             }
    35.         }
    36.         synchronized (instance)
    37.         {
    38.             instance.checkedOut++;
    39.         }
    40.         return instance;
    41.     }
    42. /**
    43.      * Retrieves a BookVObj.  Default to look in the cache.
    44.      */
    45.     public BookVObj getBookVObj(int id)
    46.     {
    47.         return getBookVObj(id, true);
    48.     }
    49.     /**
    50.      * Retrieves a BookVObj. Second argument decides whether to look
    51.      * in the cache. Returns a new value object if one can"t be
    52.      * loaded from the database. Database cache synchronization is
    53.      * handled by removing cache elements upon modification.
    54.      */
    55.     public BookVObj getBookVObj(int id, boolean fromCache)
    56.     {
    57.         BookVObj vObj = null;
    58.         // First, if requested, attempt to load from cache
    59.         if (fromCache)
    60.         {
    61.             vObj = (BookVObj) bookCache.get("BookVObj" + id);
    62.         }
    63.         // Either fromCache was false or the object was not found, so
    64.         // call loadBookVObj to create it
    65.         if (vObj == null)
    66.         {
    67.             vObj = loadBookVObj(id);
    68.         }
    69.         return  vObj;
    70.     }
    71.     /**
    72.      * Creates a BookVObj based on the id of the BOOK table.  Data
    73.      * access could be direct JDBC, some or mapping tool, or an EJB.
    74.      */
    75.     public BookVObj loadBookVObj(int id)
    76.     {
    77.         BookVObj vObj = new BookVObj();
    78.         vObj.bookId = id;
    79.         try
    80.         {
    81.             boolean found = false;
    82.             // load the data and set the rest of the fields
    83.             // set found to true if it was found
    84.             found = true;
    85.             // cache the value object if found
    86.             if (found)
    87.             {
    88.                 // could use the defaults like this
    89.                 // bookCache.put( "BookVObj" + id, vObj );
    90.                 // or specify special characteristics
    91.                 // put to cache
    92.                 bookCache.put("BookVObj" + id, vObj);
    93.             }
    94.         }
    95.         catch (Exception e)
    96.         {
    97.             // Handle failure putting object to cache
    98.         }
    99.         return vObj;
    100.     }
    101.     /**
    102.      * Stores BookVObj"s in database.  Clears old items and caches
    103.      * new.
    104.      */
    105.     public void storeBookVObj(BookVObj vObj)
    106.     {
    107.         try
    108.         {
    109.             // since any cached data is no longer valid, we should
    110.             // remove the item from the cache if it an update.
    111.             if (vObj.bookId != 0)
    112.             {
    113.                 bookCache.remove("BookVObj" + vObj.bookId);
    114.             }
    115.             // put the new object in the cache
    116.             bookCache.put("BookVObj" + vObj.bookId, vObj);
    117.         }
    118.         catch (Exception e)
    119.         {
    120.             // Handle failure removing object or putting object to cache.
    121.         }
    122.     }
    123. }
    124.         
    复制代码
    三、配置文件cache.ccf,它定义你配置何种类型的缓存、缓存的大小、过期时间等。

    #WEB-INF/classes/cache.ccf(以下内容不要换行)
    jcs.default=
    jcs.default.cacheattributes=org.apache.jcs.engine.CompositeCacheAttributes
    jcs.default.cacheattributes.MaxObjects=1000
    jcs.default.cacheattributes.MemoryCacheName=org.apache.jcs.engine.memory.lru.LRUMemoryCache jcs.default.cacheattributes.UseMemoryShrinker=true
    jcs.default.cacheattributes.MaxMemoryIdleTimeSeconds=3600
    jcs.default.cacheattributes.ShrinkerIntervalSeconds=60
    jcs.default.cacheattributes.MaxSpoolPerRun=500
    jcs.default.elementattributes=org.apache.jcs.engine.ElementAttributes
    jcs.default.elementattributes.IsEternal=false
      四、测试的JSP文件
    <%@page import="com.genericbookstore.data.*,java.util.*" %> <% BookVObjManager cache = BookVObjManager.getInstance();  
    BookVObj bv1=cache.getBookVObj(8,true); out.println(bv1.bookId);
    %>
      五、测试:http://127.0.0.1:8080/jcs/testjcs.jsp 所有源文件请下载。 附: JCS(Java Caching System)简介以及相关文档
    作者:小红帽 概述
    JCS是Jakarta的项目Turbine的子项目。它是一个复合式的缓冲工具。可以将对象缓冲到内存、硬盘。具有缓冲对象时间过期设定。还可以通过JCS构建具有缓冲的分布式构架,以实现高性能的应用。
    对于一些需要频繁访问而每访问一次都非常消耗资源的对象,可以临时存放在缓冲区中,这样可以提高服务的性能。而JCS正是一个很好的缓冲工具。缓冲工具对于读操作远远多于写操作的应用性能提高非常显著。
    JCS的详细说明在 http://jakarta.apache.org/turbine/jcs/    JCS的特性
    JCS除了简单的将对象缓冲在内存中以外,还具有几个特性,以适应企业级缓冲系统的需要。这些特性包括时间过期、索引式硬盘缓冲、并行式的分布缓冲等。
    内存缓冲
    JCS现在支持两种内存缓冲算法LRU和MRU。通常都是使用LRU算法。
    org.apache.stratum.jcs.engine.memory.lru.LRUMemoryCache
    使用内存缓冲区需要定义缓冲区大小,当超过缓冲区限制时,会将缓冲内容抛弃掉。如果有配硬盘缓冲,则将挤出来的缓冲内容写入硬盘缓冲区。   时间过期
    JCS对于缓冲的对象,可以设定缓冲过期时间,一个对象在缓冲区中停留的时间超过这个时间,就会被认为是“不新鲜”而被放弃。   索引式硬盘缓冲
    一方面,为了避免缓冲区过大,撑爆虚拟机的内存,另一方面又希望能够缓冲更多的对象,JCS可以将超出缓冲区大小的对象缓存到硬盘上。配置上也比较方便,只需要指定缓冲临时文件的存放目录位置。硬盘缓冲将缓冲对象的内容写到文件上,但是将访问索引保存在内存中,因此也能够达到尽可能高的访问效率。   并行式的分布缓冲(Lateral)
    通常,将对象缓冲在内存中,一方面提高了应用的性能,而另一方面却使得应用不可以分布式发布。因为假设一个应用配置在两台服务器上并行运行,而两台服务器单独缓冲,则很容易导致两个缓冲区内容出现版本上的不一致而出错。一个机器上修改了数据,这个动作会影响到本地内存缓冲区和数据库服务器,但是却不会通知到另一台服务器,导致另一台上缓冲的数据实际上已经无效了。
    并行式的分布缓冲就是解决这个问题。可以通过配置,将几台服务器配成一个缓冲组,组内每台服务器上有数据更新,会横向将更新的内容通过TCP/IP协议传输到其他服务器的缓冲层,这样就可以保证不会出现上述情况。这个的缺点是如果组内的并行的服务器数量增大后,组内的数据传输量将会迅速上升。这种方案适合并行服务器的数量比较少的情况。   Client/Server式的缓冲(Remote)
    客户/服务端式的缓冲集群。这种方式支持一个主服务器和最高达到256个客户端。客户端的缓冲层会尝试连接主服务器,如果连接成功,就会在主服务器上注册。每个客户端有数据更新,就会通知到主服务器,主服务器会将更新通知到除消息来源的客户端以外的所有的客户端。
    每个客户端可以配置超过一个服务器,第一个服务器是主服务器,如果与第一个服务器连接失败,客户端会尝试与备用的服务器连接,如果连接成功,就会通过备用服务器与其他客户端对话,同时会定期继续尝试与主服务器取得连接。如果备用服务器也连接失败,就会按照配置顺序尝试与下一个备用服务器连接。
    这种方式下,更新通知是一种轻量级的,一个机器上的数据更新,不会把整个数据传输出去,而只是通知一个ID,当远程的其他机器收到更新通知后,就会把对应ID的缓冲对象从本地的内存缓冲区中移除,以保证不会在缓冲区内出现错误数据。
    这种构造需要分别配置客户端和服务器,配置比较麻烦。
       配置方法
    JCS的好处之一,就是应用在开发的时候,可以不用去构思底层的缓冲配置构架。同一个应用,只需要修改配置,就可以改变缓冲构架,不需要修改应用的源代码。配置方法也比较简单,就是修改配置文件cache.ccf。这个文件放置在WEB-INF/classes目录下。配置格式类似log4j的配置文件格式。下面介绍一下使用各种缓冲结构的配置方法。   内存缓冲
    #WEB-INF/classes/cache.ccf(以下内容不要换行)
    jcs.default=
    jcs.default.cacheattributes=org.apache.jcs.engine.CompositeCacheAttributes
    jcs.default.cacheattributes.MaxObjects=1000
    jcs.default.cacheattributes.MemoryCacheName=org.apache.jcs.engine.memory.lru.LRUMemoryCache
    上面配置了默认缓冲属性。一个应用中,由于对象类型的不同,可能会使用多个缓冲区,每个缓冲区都会有一个名字,如果在配置文件中没有指明特定的缓冲区的属性,所有的缓冲区都会根据默认属性来构建。上面的内容,指明缓冲区的大小为存放1000个对象,内存缓冲器使用LRUMemoryCache对象。可选的还有MRUMemoryCache,应该可以自定义新的内存缓冲区。1000个缓冲对象这个容量,是指每个缓冲区都缓冲1000个,而不是指所有缓冲区总容量。以上配置,就可以让应用运行起来。   时间过期
    如果需要引入时间过期机制,则需要加上
    jcs.default.cacheattributes.cacheattributes.UseMemoryShrinker=true
    jcs.default.cacheattributes.cacheattributes.MaxMemoryIdleTimeSeconds=3600
    jcs.default.cacheattributes.cacheattributes.ShrinkerIntervalSeconds=60
    这里指明对象超过3600秒则过期,每隔60秒检查一次。  
    索引式硬盘缓冲
    索引式硬盘缓冲是辅助缓冲的一种,使用时需要做以下事情
    #定义一个硬盘缓冲区产生器(Factory),取名为DC
    jcs.auxiliary.DC=org.apache.stratum.jcs.auxiliary.disk.indexed.IndexedDiskCacheFactory
    jcs.auxiliary.DC.attributes=org.apache.stratum.jcs.auxiliary.disk.indexed.IndexedDiskCacheAttributes
    jcs.auxiliary.DC.attributes.DiskPath=g:/dev/jakarta-turbine-stratum/raf
    #这里其实就是指明了缓冲文件存放到那里去。
    然后,做以下修改
    jcs.default=DC
    这样,所有未特别指定属性的缓冲区都会自己使用一个硬盘缓冲区,缓冲文件会以缓冲区的名字来命名。存放在指定的目录下。  
    横向式的并行缓冲
    并行式的配置如下
    jcs.auxiliary.LTCP=org.apache.jcs.auxiliary.lateral.LateralCacheFactory
    jcs.auxiliary.LTCP.attributes=org.apache.jcs.auxiliary.lateral.LateralCacheAttributes
    jcs.auxiliary.LTCP.attributes.TransmissionTypeName=TCP
    jcs.auxiliary.LTCP.attributes.TcpServers=192.168.10.129:1121,192.168.10.222:1121
    jcs.auxiliary.LTCP.attributes.TcpListenerPort=1121
    jcs.auxiliary.LTCP.attributes.PutOnlyMode=false
    这里的配置是在41,129,221三台机器上实现并行缓冲的。
    大家都在1121端口上监听,同时与另外两台机器连接。如果连接失败,就会等待一个时间后再连接一次,直到连接成功为止。三台机器中任意一台的缓冲区发生更新,比如put和remove动作,就会把更新传递给另外两台。  
    单独指明某个缓冲区的属性
    如果,针对某个缓冲区,比如叫做TestCache1,需要单独配置属性,可以如下配置。
    jcs.region.testCache1=DC,LTCP
    jcs.region.testCache1.cacheattributes=org.apache.stratum.jcs.engine.CompositeCacheAttributes
    jcs.region.testCache1.cacheattributes.MaxObjects=1000
    jcs.region.testCache1.cacheattributes.MemoryCacheName=org.apache.stratum.jcs.engine.memory.lru.LRUMemoryCache
    jcs.region.testCache1.cacheattributes.UseMemoryShrinker=true
    jcs.region.testCache1.cacheattributes.MaxMemoryIdleTimeSeconds=3600
    jcs.region.testCache1.cacheattributes.ShrinkerIntervalSeconds=60
       system.GroupIdCache
    这个概念我也不是很清楚。不过JCS文档中指出配置以下内容会比较好。
    jcs.system.groupIdCache=DC
    jcs.system.groupIdCache.cacheattributes=org.apache.stratum.jcs.engine.CompositeCacheAttributes
    jcs.system.groupIdCache.cacheattributes.MaxObjects=10000   jcs.system.groupIdCache.cacheattributes.MemoryCacheName=org.apache.stratum.jcs.engine.memory.lru.LRUMemoryCache
    这可能是JCS自己的组管理体系上的缓冲区。  
    Client/Server式的缓冲(Remote)
    这种构架需要单独配置客户端和服务端,如果要研究,可以查看 http://jakarta.apache.org/turbine/jcs/RemoteAuxCache.html

      
      
       
       

         
       

         
       
      



    源码下载:http://file.javaxxz.com/2014/10/1/100839719.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-3 19:18 , Processed in 0.321601 second(s), 38 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表