Назад | Перейти на главную страницу

Статический кластер Tomcat перестает отвечать на вызов процедуры JDBC

StackOverflow был для меня образом жизни, но на этот раз это вопрос, а не поиск ответа, поскольку я, вероятно, исчерпал все варианты.

Извините, так как это будет подробное описание проблемы!

У нас есть приложение Spring MVC + Tomcat 7, работающее на сервере Windows 2012 на AWS. Будучи приложением Analytics, вызывающим вызовы высокопроизводительных процедур, выполняющие статистические вычисления в резервной копии.

Из-за требований к высокой доступности мне нужно настроить кластер. Теперь без многоадресной рассылки на AWS я прибег к двум другим вариантам (я должен сказать, что это мой первый набег на AWS и Tomcat в производственной среде).

1. Статический кластер Tomcat с DeltaManager для репликации сеанса 2. Репликация сеанса на основе Redis (будет долгая задача с сервером Windows и с закрепленным сеансом)

Начав со статического кластера Tomcat, который я настроил без особых хлопот, продолжил настройку Apache Httpd mod_proxy в качестве балансировщика нагрузки.

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8" channelStartOptions="3"><!--startoption 3 added to disable 
    multicast ,channel send option 8 is for async replication-->
    <Manager className="org.apache.catalina.ha.session.DeltaManager"
               expireSessionsOnShutdown="false"
               notifyListenersOnReplication="true"/>
    <Channel className="org.apache.catalina.tribes.group.GroupChannel">
        <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
               address="auto"
               port="4002"
               autoBind="9"
               selectorTimeout="5000"
               maxThreads="6"/>
        <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
            <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
        </Sender>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpPingInterceptor"/><!--Added ,This interceptor pings other nodes
        sothat all nodes can recognize when other nodes have left the cluster. Without this class, the cluster may appear to work fine, but session
        replication can break down when nodes are removed and re-introduced-->
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.StaticMembershipInterceptor">
        <Member className="org.apache.catalina.tribes.membership.StaticMember"  
              port="4000"  
              host="localhost"  
              domain="delta-static"  
              uniqueId="{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0}" />
        </Interceptor>  
    </Channel>

    <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/>
    <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
    <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
    <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>

Конфигурация прокси мода httpd.conf с коннектором AJP с соответствующими модулями без комментариев

<Proxy balancer://IOCluster stickysession=JSESSIONID>
  BalancerMember ajp://127.0.0.1:8009  route=tcruntime8009 loadfactor=1  
  BalancerMember ajp://127.0.0.1:8012  route=tcruntime8012 loadfactor=1 
</Proxy>
ProxyPreserveHost On
ProxyStatus On

ProxyPass "/IO"  "balancer://IOCluster/IO"
ProxyPassReverse "/IO"  "balancer://IOCluster/IO"

Конфигурация мода прокси httpd.conf с HTTP-коннектором с соответствующими модулями без комментариев

ProxyRequests Off ProxyPass / Балансировщик ввода-вывода: // IOCluster stickysession = JSESSIONID ProxyPassReverse / Балансировщик ввода-вывода: // IOCluster
БалансирЧлен http: // локальный: 8092 / IO route = tcruntime8092 BalancerMember http: // локальный: 8091 / IO route = tcruntime8091

Балансировщик нагрузки работал в обоих случаях. Проблема заключалась в том, что репликация сеанса не работала, и я не видел никаких признаков того же в журналах. Если я выключил один экземпляр, балансировщик перенаправил бы на другой узел, но я бы увидел страница входа в систему, что подтверждает то же самое.

Согласно этому 18835014 вопрос Я добавил тег в приложение web.xml и переместил тег дельта-менеджера в context.xml

<Context>

   <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"/>
    <!-- Default set of monitored resources -->


    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <!--<Context distributable="true"></Context>-->
    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
    <!--
    <Manager pathname="" />
    -->

    <!-- Uncomment this to enable Comet connection tacking (provides events
         on session expiration as well as webapp lifecycle) -->
    <!--
    <Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
    -->

</Context>

И я мог видеть активную репликацию сеанса на консоли.

Проблема в том, что теперь, когда я вхожу в приложение, страница перестает отвечать, несмотря на запросы, запущенные в приложении! Я вижу сообщение 504 (время ожидания шлюза истекло) в журналах доступа, где я вижу, что все запросы на получение успешно возвращаются. Но как только поскольку первые запросы запускаются после отправки страницы входа, запросы к базе данных запускаются, но приложение перестает отвечать.

Если я верну DeltaManager обратно внутрь server.xml, приложение станет отзывчивым, но без репликации сеанса.

Некоторые другие настройки, которые я пробовал с модулем prefork httpd.conf, keepalive, timeout и т.д., после чего я вижу 500 в журнале доступа на сервере apache, ничего не работает. Был бы очень признателен за любую помощь!

<IfModule mpm_prefork_module>
  StartServers           10
  MinSpareServers        10
  MaxSpareServers        20
  MaxClients             50
  ServerLimit            50
  MaxRequestsPerChild  500
</IfModule>
ProxyRequests On 
ProxyTimeout 600
<Proxy *>
  AddDefaultCharset Off
  Order deny,allow
  Allow from all
</Proxy>
<Proxy balancer://IOCluster stickysession=JSESSIONID>
  BalancerMember ajp://127.0.0.1:8009 min=10 max=100 route=tcruntime8009 loadfactor=1 keepalive=On timeout=600 
  BalancerMember ajp://127.0.0.1:8012 min=10 max=100 route=tcruntime8012 loadfactor=1 keepalive=On timeout=600
</Proxy>
ProxyPreserveHost On
ProxyStatus On
ProxyPass "/IO"  "balancer://IOCluster/IO"
ProxyPassReverse "/IO"  "balancer://IOCluster/IO"