Tomcat 8.5 / RHEL диспетчер репликации сеансов | Значение атрибута сеанса не будет реплицировано

У меня необычный баг. Я настроил Tomcat Session Replication Manager (Delta). Атрибуты SessionID и Session реплицируются, но не содержимое атрибутов.

мой кластерный тег в server.xml

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
                 channelSendOptions="6">

         <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"/>
                   

          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="auto"
                      port="4001"
                      autoBind="100"
                      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.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
          </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.ClusterSessionListener"/>
        </Cluster>

../webapps/ROOT/WEB-INF/web.xml на всех остальных машинах:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.Date"%>


<%@page import="java.util.List"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%> 
<%@ page import="javax.servlet.http.HttpUtils.*" %>

<!DOCTYPE html>

<html>

<style type="text/css"> 
     th {
        font-weight:bold;
        text-align:left;
    }
</style> 



    <head>
        <meta http-equiv="Content-Type" content"text/html"; charset=UTF-8">
        <title> JSP PAGE </title>
    </head>
    
    <body>
    
    <FONT size = 5 COLOR="#0000FF">
    
    Instance 1 <br/> <br/>
    
    </FONT>
    
    
    
    <hr/>
    
    
    <br/>
    
    <table cellpadding="10" >
    <tr> <th> Session Id </th> <td> <%=request.getSession().getId()%> </td> </tr>
    <tr> <th> Is it New Session </th> <td> <%=request.getSession().isNew()%> </td> </tr>
    <tr> <th> Session Create Date </th> <td> <%=new Date(request.getSession().getCreationTime())%>  </td> </tr>
    <tr> <th> Session Access Date </th> <td> <%=new Date(request.getSession().getLastAccessedTime())%> </td> </tr>
    </table>
    
    <br/><br/><br/><br/>
    
    <b> Cart List </b> <br/>
    
    <hr/>

    <ul>
    
    <%
        String bookName = request.getParameter("bookName");
        List<String> listOfBooks = (List<String>) request.getSession().getAttribute("Books");
        
        if (listOfBooks == null) {
            listOfBooks = new ArrayList<String>();
            request.getSession().setAttribute("Books", listOfBooks);
        }
        
        if (bookName != null) {
            listOfBooks.add(bookName);
        }
        
        for (String book : listOfBooks ) { 
            out.println("<li>"+book + "</li>");
        }
    %>
    </ul>
<form action="index.jsp" method="POST" >
         <input type= "text" name="bookName" placeholder="Enter bookname" required /> 
         <input type = "submit" value = "add to cart" > <br/> 
         
</form>
1.xsd" version="3.1" metadata-complete="true"> <display-name>Welcome to Tomcat</display-name> <description> Welcome to Tomcat </description> <distributable/> </web-app>

../webapps/ROOT/index.jsp для всех экземпляров (1, 2, ..)

<%@page import="java.util.ArrayList"%>
<%@page import="java.util.Date"%>


<%@page import="java.util.List"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%> 
<%@ page import="javax.servlet.http.HttpUtils.*" %>

<!DOCTYPE html>

<html>

<style type="text/css"> 
     th {
        font-weight:bold;
        text-align:left;
    }
</style> 



    <head>
        <meta http-equiv="Content-Type" content"text/html"; charset=UTF-8">
        <title> JSP PAGE </title>
    </head>
    
    <body>
    
    <FONT size = 5 COLOR="#0000FF">
    
    Instance 1 <br/> <br/>
    
    </FONT>
    
    
    
    <hr/>
    
    
    <br/>
    
    <table cellpadding="10" >
    <tr> <th> Session Id </th> <td> <%=request.getSession().getId()%> </td> </tr>
    <tr> <th> Is it New Session </th> <td> <%=request.getSession().isNew()%> </td> </tr>
    <tr> <th> Session Create Date </th> <td> <%=new Date(request.getSession().getCreationTime())%>  </td> </tr>
    <tr> <th> Session Access Date </th> <td> <%=new Date(request.getSession().getLastAccessedTime())%> </td> </tr>
    </table>
    
    <br/><br/><br/><br/>
    
    <b> Cart List </b> <br/>
    
    <hr/>

    <ul>
    
    <%
        String bookName = request.getParameter("bookName");
        List<String> listOfBooks = (List<String>) request.getSession().getAttribute("Books");
        
        if (listOfBooks == null) {
            listOfBooks = new ArrayList<String>();
            request.getSession().setAttribute("Books", listOfBooks);
        }
        
        if (bookName != null) {
            listOfBooks.add(bookName);
        }
        
        for (String book : listOfBooks ) { 
            out.println("<li>"+book + "</li>");
        }
    %>
    </ul>
<form action="index.jsp" method="POST" >
         <input type= "text" name="bookName" placeholder="Enter bookname" required /> 
         <input type = "submit" value = "add to cart" > <br/> 
         
</form>

Результат после добавления некоторых атрибутов / значений сеанса через index.jsp

на INSTANCE1 (основной)

введите описание изображения здесь

на INSTANCE2 (резервное копирование) (атрибуты не будут реплицированы!)

введите описание изображения здесь

В файлах журнала я вижу, что экземпляры узнают друг друга и посылают сигналы. Но

  1. когда я отправляю ping -t 1 -c 2 228.0.0.4, я получаю следующее: 2 пакета переданы, 0 получено, 100% потеря пакетов, время 5852 мс

  2. Почему реплицируются SessionID и атрибут, но не значение атрибута?


person ng-User    schedule 18.08.2020    source источник


Ответы (1)


Я, наконец, смог решить эту проблему, и никто, даже официальная документация по java, не помог, когда я набрал ключевые слова, что является НЕПОЛАДКОЙ в мире документации !!!!!! Видите ли, я не думаю, что в java есть нестандартный способ уведомлять другие экземпляры при изменении содержимого списка. Не существует метода DatasetChangedNotify для уведомления других экземпляров tomcat об изменении содержимого списка, только если изменен сам атрибут сеанса.

Верно. Я знаю, что вы следуете руководству Рамки; Я тоже. Не следуйте сумасшедшим предложениям, которые вы найдете в Интернете, потому что они не работают; Я их пробовал. ТОЧНО следуйте инструкциям Рамки; что бы он ни делал на видео, вы делаете это, НО ИЗМЕНИТЕ свой скриптлет JSP на:

String bookName = request.getParameter("bookName");
List<String> listOfBooks = (ArrayList<String>) request.getSession().getAttribute("Books");
if(listOfBooks == null) {
  listOfBooks = new ArrayList<String>();                                      
}
if(bookName != null) {
    listOfBooks.add(bookName);
}
request.getSession().setAttribute("Books", listOfBooks);
for(String book: listOfBooks) {
    out.println("<li>" + book + "</li><br />");
}           

Вы, наверное, уже поняли это, но если кому-то еще понадобится дополнительная помощь, вот что происходит: в учебнике Рамки устанавливает listOfBooks в качестве объекта для атрибута сеанса Книги только в начале. Его следует устанавливать каждый раз.

Всякий раз, когда вызывается метод setAttribute, все экземпляры tomcat будут получать уведомление о том, что атрибут сеанса с именем Books был изменен, и, если это список, список будет просканирован, поэтому все экземпляры будут знать, что содержимое было изменено, и будут покажите их. Не беспокойтесь, что вы всегда будете устанавливать атрибут «Книги» поверх самого себя, потому что он будет просто перезаписан.

Если setAttribute вызывается только один раз, когда listOfBooks имеет значение null, при изменении списка только экземпляр tomcat, на котором запущен скриптлет, будет уведомлен и будет действовать соответственно в отношении атрибута сеанса, но все другие экземпляры не будут повторно сканировать список у них есть атрибуты сеанса в своих Книгах, поэтому их списки все еще пусты для них.

Вот почему в первую очередь у вас есть полный список, а во всех остальных - пустой список.

person Gustavo Souza    schedule 28.11.2020