• EJB+memcache


    首先我们通过下图 了解到memcache在系统中处于大概什么的位置


    然后我们了解下Memcached简介
    1.1. 什么是Memcached  Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。
    它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。
    Memcached基于一个存储键/值对的HashMap,它并不提供冗余(复制其HashMap条目),当某个服务器停止运行或崩溃了,所有存放在服务器上的键/值对都将丢失。
    但目前Memcached的客户端和代理程序可以提供多服务器的并联方式,可以提供一定的处理能力。
    1.2. Memcached与其他分布式缓存的区别  Memcached与其它常用的分布式缓存(例如EhCache、OSCache、JBoss Cache)最主要的区别在于Memcached采用集中式缓存方式(即一台或多台缓存服务器为所有应用系统提供缓存能力),自身不提供集群能力,不提供缓存复制功能;而其他分布式缓存系统采用分布式缓存方式,各个应用系统内部提供数据缓存的能力,
    多个缓存间采用组播或点对点的方式进行缓存同步。 

    在性能上来看,Memcached比其它分布式缓存系统低一半以上(未考虑大量数据在其它缓存系统进行复制的影响);但从管理方面来看,Memcached的缓存采用集中管理的模式,应用系统可以水平扩展,

    而其它分布式缓存在水平扩展的同时,必须同时调整缓存复制策略,一旦应用服务器节点大量扩展,对于缓存服务器间的数据复制将成几何数增加。

    然后我们从官网http://memcached.org/下载 适合自身系统的memcache安装包

    下载好之后解压

    因为我是windows 操作

    所以解压后 直接CMD到改目录

    到memcached根目录 
    1、安装 
    memcached.exe –d install  

    2、启动 
    memcached.exe -d start 

    现在来试试是否可以连接: 

    使用方法为“telnet ip 端口号”,登录后使用“stats”命令 
    cmd下 
    telnet 192.168.1.135 11211(注意:这里只能用IP 不能用 localhost 或127.0.0.1  11211端口默认的) 

    然后使用:stats命令可以看到memcached的使用情况如下: 

    time: 1255537291 服务器当前的unix时间戳 
    total_items: 54 从服务器启动以后存储的items总数量 
    connection_structures: 19 服务器分配的连接构造数 
    version: 1.2.6 memcache版本 
    limit_maxbytes: 67108864 分配给memcache的内存大小(字节) 
    cmd_get: 1645 get命令(获取)总请求次数 
    evictions: 0 为获取空闲内存而删除的items数(分配给memcache的空间用满后需 要删除旧的items来得到空间分配给新的items) 
    total_connections: 19 从服务器启动以后曾经打开过的连接数 
    bytes: 248723 当前服务器存储items占用的字节数 
    threads: 1 当前线程数 
    get_misses: 82 总未命中次数 
    pointer_size: 32 当前操作系统的指针大小(32位系统一般是32bit) 
    bytes_read: 490982 总读取字节数(请求字节数) 
    uptime: 161 服务器已经运行的秒数
    curr_connections: 18 当前打开着的连接数 
    pid: 2816 memcache服务器的进程ID 
    bytes_written: 16517259 总发送字节数(结果字节数)
    get_hits: 1563 总命中次数 
    cmd_set: 54 set命令(保存)总请求次数 
    curr_items: 28 服务器当前存储的items数量

    3.一些常用命令

    -p 监听的端口
    -l 连接的IP地址, 默认是本机
    -d start 启动memcached服务
    -d restart 重起memcached服务
    -d stop|shutdown 关闭正在运行的memcached服务
    -d install 安装memcached服务
    -d uninstall 卸载memcached服务
    -u 以的身份运行 (仅在以root运行的时候有效)
    -m 最大内存使用,单位MB。默认64MB
    -M 内存耗尽时返回错误,而不是删除项
    -c 最大同时连接数,默认是1024
    -f 块大小增长因子,默认是1.25
    -n 最小分配空间,key+value+flags默认是48
    -h 显示帮助

    到此整个的memcache安装结束

    那么该怎么样集成到EJB呢?

    客户端调用有两种

    一种是java_memcached-release_2.6.3依赖于此包

    二种是alisoft-xplatform-asf-cache-2.5.1依赖于此包

    我选择的是第二种原因是阿里软件的架构师岑文初进行封装的。里面的注释都是中文的,比较好详情http://www.infoq.com/cn/articles/memcached-java

    重点我就讲这种结合EJB的使用

    首先对xxxEJB引入alisoft-xplatform-asf-cache-2.5.1.jar

    然后配置memcache.xml文件 记住一定要放在classpath下否则找不到

    <memcached>
        <!--memcached Client的配置,也就是一个IMemcachedCache的配置。Name必须填,表示Cache的名称,socketpool必须填,
        表示使用的远程通信连接池是哪一个,参看后面对于socketpool的定义。后面都是可选的,第三个参数表示传输的时候是否压缩,第四个参数表示默认的编码方式 -->
     <client name="mclient1" socketpool="pool1" compressEnable="true" defaultEncoding="UTF-8" >
            <!--errorHandler></errorHandler可定义错误处理类,一般不需要定义 -->
        </client>
        <client name="mclient2" socketpool="pool2" compressEnable="true" defaultEncoding="UTF-8" >
        </client> 
         <!--socketpool是通信连接池定义,每一个memcached Client要和服务端交互都必须有通信连接池作为底层数据通信的支持,name必填,表示名字,
         同时也是memcached client指定socketpool的依据,failover表示对于服务器出现问题时的自动修复。
         initConn初始的时候连接数,minConn表示最小闲置连接数,maxConn最大连接数,maintSleep表示是否需要延时结束(最好设置为0,如果设置延时的话那么就不能够立刻回收所有的资源,
         如果此时从新启动同样的资源分配,就会出现问题),nagle是TCP对于socket创建的算法,socketTO是socket连接超时时间,aliveCheck表示心跳检查,确定服务器的状态。
         Servers是memcached服务端开的地址和ip列表字符串,weights是上面服务器的权重,必须数量一致,否则权重无效  -->
        <socketpool name="pool1" failover="true" initConn="10" minConn="5" maxConn="250" maintSleep="0"
            nagle="false" socketTO="3000" aliveCheck="true">
            <servers>192.168.1.137:11211</servers>
            <weights>5</weights>
        </socketpool> 
        <socketpool name="pool2" failover="true" initConn="10" minConn="5" maxConn="250" maintSleep="0"
            nagle="false" socketTO="3000" aliveCheck="true">
            <servers>192.168.0.53:11211</servers>
            <weights>5</weights>
        </socketpool>
         <!--虚拟集群设置,这里将几个client的cache设置为一个虚拟集群,当对这些IMemcachedCache作集群操作的时候,就会自动地对集群中所有的Cache作插入,寻找以及删除的操作,做一个虚拟交互备份  -->
        <cluster name="cluster1">
            <memCachedClients>mclient1,mclient2</memCachedClients>
        </cluster>           
    </memcached>

    然后创建一个类进行对象初始化

     //缓存管理器变量 
        private ICacheManager manager; 
        //缓存变量 
        private IMemcachedCache cache; 
         
        //缓存名称 
        /********************************单例模式(饿汉式)  begin***********************************************/ 
         
        private  static CacheHandler cacheHandler=new CacheHandler(); 
        /**
         * 私有构造函数
         */ 
        private CacheHandler(){ 
            System.out.println("---------------创建单例 begin--------------"); 
            initCache(); 
            System.out.println("---------------创建单例 end--------------"); 
        } 
        public static CacheHandler getInstance(){ 
            return cacheHandler; 
        } 
        /********************************单例模式(饿汉式)  end***********************************************/ 
         
        /**
         * @MethodName  : initCache
         * @Description : 初始化缓存
         */ 
        private void initCache(){ 
            //1.创建cachemanager 
         manager=CacheUtil.getCacheManager(IMemcachedCache.class,MemcachedCacheManager.class.getName());;
            //如果cache是空,則手動創建 
            if(cache==null){ 
       manager.start();
       cache = (IMemcachedCache) manager.getCache("mclient1");
            } 
        } 
        /**
         * @MethodName  : getCache
         * @Description : 外部通过get方法拿到cache后,可清空cache
         * @return
         */ 
        public IMemcachedCache getCache() { 
            return cache; 
        } 
        
        /**
         * @MethodName  : clearCache
         * @Description : 清理缓存
         */ 
        public void clearCache(){ 
            if(cache!=null){ 
                cache.clear();
            } 
        }

    因为我是测试 所以利用EJB的拦截器

    首先创建一个类对查询的方法进行缓存

    @AroundInvoke 
        public Object processCache(InvocationContext context) throws Exception{ 
            String targetName = context.getTarget().getClass().getName(); 
            String methodName = context.getMethod().getName(); 
            Object[] arguments =context.getParameters(); 
            Object result; 
            //获取缓存对象 
            IMemcachedCache cache = CacheHandler.getInstance().getCache(); 
            //如果方法名以find、query、或get开头则执行缓存策略 
            if(methodName.startsWith("find") || methodName.startsWith("get") || methodName.startsWith("query")){ 
                String cacheKey = getCacheKey(targetName, methodName, arguments); 
                Object element = cache.get(cacheKey); 
                if (element == null) { 
                    result = context.proceed(); // 执行目标方法,并保存目标方法执行后的返回值 
                    cache.put(cacheKey, result);
                    element=result;
                    System.out.println("==========================createCache-->" + cacheKey); 
                } else { 
                    System.out.println("==========================hit Cache-->" + cacheKey); 
                } 
                return element; 
            } 
             
            //否则直接执行目标方法 
            return context.proceed(); 
        } 
         
        /**
         * @MethodName  : getCacheKey
         * @Description : 获得cache key的方法,cache key是Cache中一个Element的唯一标识 cache key包括
         * 包名+类名+方法名+各个参数的具体指,如com.jiwu.service.UserServiceImpl.getAllUser
         * @param targetName    类名
         * @param methodName    方法名
         * @param arguments     方法实参数组
         * @return                      cachekey
         */ 
        private String getCacheKey(String targetName, String methodName, 
                Object[] arguments) { 
            StringBuffer sb = new StringBuffer(); 
            sb.append(targetName).append(".").append(methodName); 
            if ((arguments != null) && (arguments.length != 0)) { 
                for (int i = 0; i < arguments.length; i++) { 
                    if(arguments[i] instanceof String[]){ 
                        String[] strArray = (String[])arguments[i]; 
                        sb.append("."); 
                        for(String str : strArray){ 
                            sb.append(str); 
                        } 
                    }else{ 
                        sb.append(".").append(arguments[i]); 
                    } 
                     
                } 
            } 
             
            return sb.toString(); 
        }

    然后manager引用的时候 只要在类上引用即可 例如以下

    @Interceptors(CacheInterceptor.class)
    public class AdminManagerImpl implements IAdminManager

    这样的话就会对该类中所有的find,get,query 开始的方法进行拦截 缓存

    由此整个EJB和memcache已关联,部署的时候还需要在deploy 同等目录的LIB下放入引用alisoft-xplatform-asf-cache-2.5.1.jar

    OK启动你的JBOSS 打上你的断点看是否已经成功

  • 相关阅读:
    类加载器的双亲委派机制
    类加载器
    Linux的cut命令
    Nacos服务发现简单应用
    Nacos当注册中心
    通过pscp命令从Windows向Linux传输大文件
    docker-compose安装nacos集群
    转一篇用分布式解决ERP问题
    转一篇云计算/大数据的通俗文章
    csdn上讲一个实时计算架构比较清晰的一篇文章
  • 原文地址:https://www.cnblogs.com/jiwuyf/p/3795865.html
Copyright © 2020-2023  润新知