Jfinal2.2+Nginx1.12+Tomcat8+EhCache 实现 负载均衡+Session共享

Nginx配置文件 nginx.conf

	#集群配置:服务器列表,weight 采取均匀分配方式,weight越大,分配几率越大
    upstream localhost {
      server localhost:8001 weight=1;
      server localhost:8002 weight=1;
    }

2、http模块中,使用 upstream localhost,在此还做了动静分离,其中静态的就指向一个目录即可,后续在更新的时候也只需要更新着一个目录,当然,如果做CDN,又是另外一种配置方式了。

           location / {
               proxy_connect_timeout   3;
               proxy_send_timeout      30;
               proxy_read_timeout      30;
               proxy_pass http://localhost;
           }
		   
		   
		   #配置Nginx动静分离,定义的静态页面直接从Nginx发布目录读取。
			 location ~*\.(js|css|png|gif|jpg|jpeg)$ {  
				root D:/pnf_etp/app1/;
			}

 

tomcat8 主要是修改 server.xml 中对应的端口,确保不同的tomcat端口不冲突即可。

EhCache主要在配置文件ehcache.xml进行配置修改,完整例子如下:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 缓存配置 name:缓存名称。 maxElementsInMemory:缓存最大个数。 eternal:对象是否永久有效,一但设置了,timeout将不起作用。 
	timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。 
	timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。 
	overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。 diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。 
	maxElementsOnDisk:硬盘最大缓存个数。 diskPersistent:是否缓存虚拟机重启期数据 Whether the disk 
	store persists between restarts of the Virtual Machine. The default value 
	is false. diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。 memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。 
	clearOnFlush:内存数量最大时是否清除。 参考: http://blog.csdn.net/mlitsn/article/details/1909192 
	http://blog.csdn.net/u013366812/article/details/51725335 -->
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="false"
	monitoring="autodetect" dynamicConfig="true">

	<cacheManagerPeerListenerFactory
		class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
		properties="hostName=localhost,port=4081,socketTimeoutMillis=8000" />

	<cacheManagerPeerProviderFactory
		class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
		properties="peerDiscovery=manual,rmiUrls=//localhost:4082/userSessionCache|//localhost:4082/userTokenCache|//localhost:4082/userAllowMenuUri|//localhost:4082/FormToken|//localhost:4082/orderToken|//localhost:4082/AccessTokenCache|//localhost:4082/OAuth2AccessTokenCache|//localhost:4082/MQCache" />

	<diskStore path="java.io.tmpdir" />

	<defaultCache maxEntriesLocalHeap="10000" eternal="false"
		overflowToDisk="true" timeToIdleSeconds="20" timeToLiveSeconds="20">
	</defaultCache>

	<!-- 用户SessionID,通过getSession(true).getId,获取 -->
	<cache name="SessionIDCache" maxElementsInMemory="10000"
		maxElementsOnDisk="100000" maxEntriesLocalHeap="10000"
		maxEntriesLocalDisk="1000" eternal="true" overflowToDisk="true"
		diskSpoolBufferSizeMB="100" memoryStoreEvictionPolicy="FIFO"
		diskPersistent="true" transactionalMode="off" clearOnFlush="false" />

	<!-- 用户登录session缓存 -->
	<cache name="userSessionCache" maxEntriesLocalHeap="10000"
		maxEntriesLocalDisk="0" eternal="false" overflowToDisk="true"
		diskSpoolBufferSizeMB="20" timeToIdleSeconds="3600" timeToLiveSeconds="86400"
		memoryStoreEvictionPolicy="LRU" diskPersistent="true"
		diskExpiryThreadIntervalSeconds="120" transactionalMode="off"
		clearOnFlush="true">
		<cacheEventListenerFactory
			class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
			properties="replicateAsynchronously=false,replicatePuts=true,replicateUpdates=true,replicateUpdatesViaCopy=true,replicateRemovals=true" />
	</cache>

	<!-- 用户API Token 缓存 -->
	<cache name="userTokenCache" maxEntriesLocalHeap="10000"
		maxEntriesLocalDisk="1000" eternal="false" overflowToDisk="true"
		diskSpoolBufferSizeMB="20" timeToIdleSeconds="3600" timeToLiveSeconds="7200"
		memoryStoreEvictionPolicy="LRU" diskPersistent="true"
		diskExpiryThreadIntervalSeconds="120" transactionalMode="off"
		clearOnFlush="true">
		<cacheEventListenerFactory
			class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
			properties="replicateAsynchronously=false,replicatePuts=true,replicateUpdates=true,replicateUpdatesViaCopy=true,replicateRemovals=true" />
	</cache>

	<!-- 用户菜单缓存 -->
	<cache name="userMenuCache" maxEntriesLocalHeap="10000"
		maxEntriesLocalDisk="1000" eternal="false" overflowToDisk="true"
		diskSpoolBufferSizeMB="20" timeToIdleSeconds="7200" timeToLiveSeconds="86400"
		memoryStoreEvictionPolicy="LRU" diskPersistent="true"
		diskExpiryThreadIntervalSeconds="120" transactionalMode="off"
		clearOnFlush="true" />

	<!-- 用户有权访问菜单缓存 -->
	<cache name="userAllowMenuUri" maxEntriesLocalHeap="10000"
		maxEntriesLocalDisk="1000" eternal="false" overflowToDisk="true"
		diskSpoolBufferSizeMB="20" timeToIdleSeconds="3600" timeToLiveSeconds="86400"
		memoryStoreEvictionPolicy="LRU" diskPersistent="true"
		diskExpiryThreadIntervalSeconds="120" transactionalMode="off"
		clearOnFlush="true">
		<cacheEventListenerFactory
			class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
			properties="replicateAsynchronously=false,replicatePuts=true,replicateUpdates=true,replicateUpdatesViaCopy=true,replicateRemovals=true" />
	</cache>

	<!-- 字典缓存,全局使用 -->
	<cache name="dictCache" maxEntriesLocalHeap="10000"
		maxEntriesLocalDisk="1000" eternal="true" overflowToDisk="true"
		diskSpoolBufferSizeMB="20" memoryStoreEvictionPolicy="LRU"
		diskPersistent="true" diskExpiryThreadIntervalSeconds="120"
		transactionalMode="off" clearOnFlush="true" />

	<!-- 微信access_token缓存 -->
	<cache name="AccessTokenCache" maxEntriesLocalHeap="1000"
		maxEntriesLocalDisk="100" eternal="false" overflowToDisk="true"
		diskSpoolBufferSizeMB="20" timeToIdleSeconds="3600" timeToLiveSeconds="7200"
		memoryStoreEvictionPolicy="LRU" diskPersistent="true"
		diskExpiryThreadIntervalSeconds="120" transactionalMode="off"
		clearOnFlush="true">
		<cacheEventListenerFactory
			class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
			properties="replicateAsynchronously=false,replicatePuts=true,replicateUpdates=true,replicateUpdatesViaCopy=true,replicateRemovals=true" />
	</cache>

	<!-- 微信oAuth2 access_token缓存 -->
	<cache name="OAuth2AccessTokenCache" maxEntriesLocalHeap="1000"
		maxEntriesLocalDisk="100" eternal="false" overflowToDisk="true"
		diskSpoolBufferSizeMB="20" timeToIdleSeconds="3600" timeToLiveSeconds="7200"
		memoryStoreEvictionPolicy="LRU" diskPersistent="true"
		diskExpiryThreadIntervalSeconds="120" transactionalMode="off"
		clearOnFlush="true">
		<cacheEventListenerFactory
			class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
			properties="replicateAsynchronously=false,replicatePuts=true,replicateUpdates=true,replicateUpdatesViaCopy=true,replicateRemovals=true" />
	</cache>

	<!-- 消息队列信息缓存 -->
	<cache name="MQCache" maxElementsInMemory="10000"
		maxElementsOnDisk="100000" maxEntriesLocalHeap="10000"
		maxEntriesLocalDisk="1000" eternal="true" overflowToDisk="true"
		diskSpoolBufferSizeMB="100" memoryStoreEvictionPolicy="FIFO"
		diskPersistent="true" transactionalMode="off" clearOnFlush="false">
		<cacheEventListenerFactory
			class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
			properties="replicateAsynchronously=false,replicatePuts=true,replicateUpdates=true,replicateUpdatesViaCopy=true,replicateRemovals=true" />
	</cache>


	<!-- 关键form提交token,用于防止非法或者重复提交 -->
	<cache name="FormToken" maxEntriesLocalHeap="10000"
		maxEntriesLocalDisk="0" eternal="false" overflowToDisk="true"
		diskSpoolBufferSizeMB="20" timeToIdleSeconds="3600" timeToLiveSeconds="86400"
		memoryStoreEvictionPolicy="LRU" diskPersistent="true"
		diskExpiryThreadIntervalSeconds="120" transactionalMode="off"
		clearOnFlush="true">
		<cacheEventListenerFactory
			class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
			properties="replicateAsynchronously=false,replicatePuts=true,replicateUpdates=true,replicateUpdatesViaCopy=true,replicateRemovals=true" />
	</cache>

	<!-- 交易订单OrderId token,用于防止非法或者重复提交 -->
	<cache name="orderToken" maxEntriesLocalHeap="10000"
		maxEntriesLocalDisk="0" eternal="false" overflowToDisk="true"
		diskSpoolBufferSizeMB="20" timeToIdleSeconds="3600" timeToLiveSeconds="86400"
		memoryStoreEvictionPolicy="LRU" diskPersistent="true"
		diskExpiryThreadIntervalSeconds="120" transactionalMode="off"
		clearOnFlush="true">
		<cacheEventListenerFactory
			class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
			properties="replicateAsynchronously=false,replicatePuts=true,replicateUpdates=true,replicateUpdatesViaCopy=true,replicateRemovals=true" />
	</cache>
</ehcache>

 其中,关键节点说明:

1、使用RMI方式进行分布式缓存模块的共享方式,hostName为主机ID,如果是本机使用localhost,port是通讯端口,必须确保不同的应用有不同端口

<cacheManagerPeerListenerFactory
		class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
		properties="hostName=localhost,port=4081,socketTimeoutMillis=8000" />

2、共享的具体cache模块,在rmiUrls中增加,其中 //localhost:4082是另外一个tomcat的ehcache.xml配置的上面模块的配置localhost  和port参数,需要共享几个,就配置几个Cache

<cacheManagerPeerProviderFactory
		class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
		properties="peerDiscovery=manual,rmiUrls=//localhost:4082/userSessionCache|//localhost:4082/userTokenCache|//localhost:4082/userAllowMenuUri|//localhost:4082/FormToken|//localhost:4082/orderToken|//localhost:4082/AccessTokenCache|//localhost:4082/OAuth2AccessTokenCache|//localhost:4082/MQCache" />

以上配置成功后,若tomcat启动成功,可以通过写一个测试 Controller代码验证是否已共享了其中的cache

例如:


public void index(){
if(CacheKit.get("testCacheName","abc")==null){
  System.out.println("第一次创建testCacheName");
  CacheKit.put("testCacheName","abc",getSession(true).getId());
}

System.out.println(CacheKit.get("testCacheName","abc"));
}

启动Nginx,启动两个tomcat,不断刷新测试Controller对应方法的页面,查看两个Tomcat的控制台页面输入的SessionID是否为同一个,一致则表示共享成功。

通过以上方式,把要共享的Session都存在ehcache中,从而实现多tomcat共享的目的。所以,在jfinal中,不要再单独使用getSession或者setSession等方法,这样会造成集群访问时Session失效。全部采取ehcache来保存Session,当然,可以根据业务情况来决定对Session用完之后的去留。

转载于:https://my.oschina.net/vstation/blog/1427066

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值