2017-02-19 9 views
2

У меня есть проблема в продуктивной среде с Websphere 7.x с библиотекой ehcache 2.1.0. Нити веб-контейнера ждут консультации или вставки в кеш.Ehcache ReentrantReadWriteLock в параллельной среде

Это свалка в тот момент, когда все нити контейнер сервлетов находятся на рассмотрении:

NULL 
3XMTHREADINFO  "WebContainer : 11" J9VMThread:0x00000000C7C10300, j9thread_t:0x0000010043913FB0, java/lang/Thread:0x00000000507623F0, state:P, prio=5 
sun.misc.Unsafe.park(Native Method) 
java.util.concurrent.locks.LockSupport.park(LockSupport.java:182) 
java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:822) <2> 
java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock.lock(ReentrantReadWriteLock.java:907) 
net.sf.ehcache.store.compound.Segment.put(Segment.java:402) 
net.sf.ehcache.store.compound.CompoundStore.put(CompoundStore.java:132) 
net.sf.ehcache.Cache.putInternal(Cache.java:1247) <2> 
org.springframework.cache.ehcache.EhCacheCache.put(EhCacheCache.java:70) 
xxx.yyy.fac.security.userdetails.GaiaLdapAuthoritiesPopulator.putElementCache(GaiaLdapAuthoritiesPopulator.java:466) <4> 
xxx.yyy.dgtp.gaiafrontend.core.filters.preauth.GaiaGrantedAuthoritiesWebAuthenticationDetails.buildDetails(GaiaGrantedAuthoritiesWebAuthenticationDetails.java:32) <1> 
org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.doAuthenticate(AbstractPreAuthenticatedProcessingFilter.java:114) <1> 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) 
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) 
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) 
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:184) <1> 
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) <1> 
com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:190) 
com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:125) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:322) 
xxx.yyy.dgtp.gaiafrontend.core.web.filters.JsonDeserializerFilter.doFilterChain(JsonDeserializerFilter.java:109) <1> 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) 
xxx.yyy.dgtp.gaiafrontend.core.filters.userinfo.UserInfoFilter.followWithTheRequestChain(UserInfoFilter.java:106) <1> 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) 
xxx.yyy.dgtp.gaia.commons.web.filters.RequestResponseWrapperFilter.doFilter(RequestResponseWrapperFilter.java:69) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) 
org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:83) 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) 
xxx.yyy.dgtp.gaiafrontend.core.web.filters.ResponseHeadersFilter.doFilter(ResponseHeadersFilter.java:55) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) 
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:184) <1> 
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) <1> 
com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:190) 
com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:125) 
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) 
com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:190) 
com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:125) <1> 
com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:908) 
com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:939) <1> 
com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:181) 
com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3994) 
com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:276) 
com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:945) 
com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1592) 
com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:191) 
com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:453) <3> 
com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214) <1> 
com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:175) 
com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217) 
com.ibm.io.async.AsyncChannelFuture$1.run(AsyncChannelFuture.java:205) 
com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1660)  

Я использую весной, как уровень абстракции на Ehcache и код, чтобы получить/положить на кэш программно не имеет ничего особенного.

Конфигурация кэша выглядит следующим образом:

@Bean 
    public EhCacheManagerFactoryBean cacheFactoryBean() { 

     EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean(); 
     ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("gaia-cache-ldap.xml")); 
     return ehCacheManagerFactoryBean; 

    } 

    @Bean 
    public CacheManager cacheManagerLdap() { 
     CacheManager cacheManager = new EhCacheCacheManager(cacheFactoryBean().getObject()); 
     return cacheManager; 

    } 

код с доступом к кэш-памяти:

private void getMemberOfRecursive(String group, ConcurrentMap<String, String> groupsCollector) { 

     if (group != null) { 
      if (existInCache(group)) { 
       log.debug("Group: {} exist in cache. No query executing", group); 
       groupsCollector.put(group, group); 
       Set<String> groups = (Set<String>) getElementCache(group).get(); 
       for (String newGroup : groups) { 
        getMemberOfRecursive(newGroup, groupsCollector); 
       } 
      } else { 
       String cn = getCnFromDn(group); 
       String filter = MessageFormat.format(getFilterGroupRecursive(), cn); 
       String baseDN = group.substring(group.indexOf(",") + 1); 
       groupsCollector.put(group, group); 

       log.debug("Executing recursive query with baseDN: {} " + 
         " and filter {}: ", baseDN, filter); 
       Set<String> groups = 
         getLdapTemplate().searchForSingleAttributeValues(
           baseDN, filter, new String[]{}, getRetrievesAttributes()); 
       putElementCache(group, groups); 
       for (String newGroup : groups) { 
        getMemberOfRecursive(newGroup, groupsCollector); 
       } 
      } 

     } 

Ehcache конфигурационный файл:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="false" monitoring="autodetect"  dynamicConfig="true"> 
    <diskStore path="java.io.tmpdir" /> 
    <defaultCache maxElementsInMemory="3000" eternal="false" timeToIdleSeconds="1200" 
        timeToLiveSeconds="1200" overflowToDisk="true" maxElementsOnDisk="10000" 
        diskPersistent="false" diskExpiryThreadIntervalSeconds="120" 
        memoryStoreEvictionPolicy="LRU"/> 
    <cache name="groupsldap" maxElementsInMemory="3000" eternal="true" overflowToDisk="false" 
      memoryStoreEvictionPolicy="LRU"/> 

</ehcache> 
+0

Можете ли вы добавить конфигурацию Ehcache? И если возможно, попробуйте перейти на более новую версию, '2.1.0' довольно древняя. –

+0

Это возможность, которую мы имеем, но она должна была бы оценить рост версии. Цель состоит в том, чтобы действительно знать, является ли это исправлением этой версии перед выполнением обновления. –

+0

По крайней мере, один поток должен удерживать замок. Или есть две различные блокировки (две разные трассы стека), которые затем могут вызвать тупик. Невозможно заблокировать все потоки на одном замке (и дамп потока может лежать об этом ... они не настолько надежны). – Henri

ответ

0

Наконец, это было возможно воспроизвести производственную ошибку. Эта ошибка, похоже, связана с перекрестными группами, которые существовали, по крайней мере, у пользователей группы Active Directory. Эта ошибка также пропущена без кэша, включенного на прошлой неделе, и для более тщательного анализа его было обнаружено, что существует stackoverflowerror, который в этом случае заставлял пул соединений ldap быть исчерпан с потоком в состоянии ожидания.

Когда-то выяснилось, что именно из-за этой проблемы было включено исправление, исключающее ранее посещенные группы, оно было воспроизведено в локальном тесте на этот раз с кешем, и мы должны насытить пул потоков веб-контейнера с поведением аналогично обнаружению в производстве.

Смежные вопросы