问题:在使用Ehcache缓存,采用RMI(UDP传输协议)进行数据广播同步,启动项目时报异常: net.sf.ehcache.CacheException: Can’t assign requested address
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cacheManagerFactory' defined in class path resource [app-ehcache.xml]: Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: Can't assign requested address
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
... 128 more
Caused by: net.sf.ehcache.CacheException: Can't assign requested address
at net.sf.ehcache.distribution.MulticastRMICacheManagerPeerProvider.init(MulticastRMICacheManagerPeerProvider.java:99)
at net.sf.ehcache.CacheManager.doInit(CacheManager.java:479)
at net.sf.ehcache.CacheManager.init(CacheManager.java:395)
at net.sf.ehcache.CacheManager.<init>(CacheManager.java:270)
at net.sf.ehcache.CacheManager.newInstance(CacheManager.java:1116)
at net.sf.ehcache.CacheManager.newInstance(CacheManager.java:1092)
at net.sf.ehcache.CacheManager.create(CacheManager.java:1075)
at org.springframework.cache.ehcache.EhCacheManagerFactoryBean.afterPropertiesSet(EhCacheManagerFactoryBean.java:148)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
... 135 more
配置信息如下:
<!-- 瞬时缓存,用于缓存时间较短的中间缓存 add by xubiao-->
<cache name="instantCache" eternal="false"
maxElementsInMemory="10000" overflowToDisk="true" diskPersistent="false"
timeToIdleSeconds="90" timeToLiveSeconds="30" >
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=true, replicatePuts=true, replicateUpdates=true,
replicateUpdatesViaCopy=false, replicateRemovals=true,asynchronousReplicationIntervalMillis=1000"
/>
</cache>
<!--缓存监听工厂-->
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName = 127.0.0.1,
port = 50001,
socketTimeoutMillis=10000" />
<!--使用RMI机制进行广播,当前限制同一子网下访问-->
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
multicastGroupPort=4666, timeToLive=1" />
问题分析:
- 定位:“无法分配请求地址”的异常常出现在网络分配问题上。这个问题之前在Windows电脑上使用ehcache未出现此问题。当前使用的电脑是Macbook Pro无线网络环境,网络环境使用的公司内网。防火墙处于关闭状态。网络是可以正常指配的。
调试
- 根据异常提示,发现报错在调用heartBeatReceiver.init()创建接受器的的时候,会创建多广播socket–MulticastSocket,创建MulticastSocket时,调用NetworkInterface会静态获取默认的网络接口:
/**
* Join the multicast group.
* @param inetaddr multicast address to join.
*/
protected void join(InetAddress inetaddr) throws IOException {
join(inetaddr, null);
}
/**
* required for some platforms where it's not possible to join
* a group without setting the interface first.
*/
NetworkInterface defaultInterface = NetworkInterface.getDefault();
if (!interfaceSet && defaultInterface != null) {
setNetworkInterface(defaultInterface);
}
getImpl().join(mcastaddr);
/**
//静态加载默认的网络接口
* Returns the default network interface of this system
*
* @return the default interface
*/
static NetworkInterface getDefault() {
return defaultInterface;
}
发现的问题原因:
经过调试发现,在创建心跳接受器时,调用java虚拟机,系统默认使用的网络接口是ipv6,配置的ipv4的广播端口230.0.0.1,无法join进去,所以报了无法分配请求地址的异常。如下图:
解决办法:在启动服务时,指定使用默认ipv4的网络接口。可以在启动jvm时添加参数-Djava.net.preferIPv4Stack=true。