Tomcat群集系列第2部分:会话相似性负载均衡器

这是Tomcat群集系列的第二部分。 在第一部分中,我们讨论了如何设置简单的负载均衡器。 我们看到了负载均衡器如何以循环方式将请求分配给tomcat实例。 在本文中,我们讨论在Web应用程序中引入会话时,简单负载均衡器中会出现什么问题。 我们将看到如何解决此问题。

Session如何在Servlet / Tomcat中工作?

在解决问题之前,让我们看一下Tomcat中会话管理

如果任何页面/ servlet创建了会话,那么Tomcat将创建会话对象并将其附加到会话组中(类似于HashMap的结构),并且可以使用session-id标识该会话,该ID只是一个随机数通过任何一种哈希算法生成。 然后使用Cookie标头字段响应客户端。 Cookie标头字段是键值对。 因此,tomcat创建了jsessioid这是密钥,而随机session-id是值。

当响应到达客户端(Web浏览器)时,它将更新cookie值。 如果已经存在,则它将覆盖cookie值。 从现在开始,浏览器将与请求一起附加的cookie发送到该服务器。

HTTP是无状态协议。 因此服务器无法轻松找到客户端会话。 因此,服务器读取请求的标头并提取cookie值和随机会话ID。 然后,它搜索由Tomcat维护的会话组。 然后,tomcat获取该特定客户端的会话(Web浏览器)。

如果客户端cookie值在会话组中不匹配,则Tomcat将创建一个全新的会话并将新的cookie发送到浏览器。 然后浏览器更新它。

index.jsp代码将部署所有tomcat实例。

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

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

        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>

<font size="5" color="#0000FF">
        Instance 1 

        </font>

        <hr>

        <font size="5" color="#CC0000">

        Session Id : <%=request.getSession().getId()%> 

        Is it New Session : <%=request.getSession().isNew()%>

        Session Creation Date : <%=new Date(request.getSession().getCreationTime())%>

        Session Access Date : <%=new Date(request.getSession().getLastAccessedTime())%>

        </font>
        <b>Cart List </b>

        <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);
                    request.getSession().setAttribute("Books", listOfBooks);
                }

                for (String book : listOfBooks) {
                    out.println("<li>"+book + "</li>
");
                }

        %>
        </string></string></string></ul>
        <hr>
        <form action="index.jsp" method="post">
            Book Name <input type="text" name="bookName">

            <input type="submit" value="Add to Cart">
        </form>
        <hr>


Simple Load Balancer中的问题是什么?
如果我们部署使用会话的Web应用程序,则实际上会出现问题。


我用顺序描述

  1. 用户请求一个网页,在该网页中它使用了会话(例如购物车)。
  2. 负载均衡器拦截请求并使用循环方式将其发送到其中之一的tomcat。 假设这次将其发送到tomcat1。
  3. tomcat1创建会话,并向客户端发送cookie标头。
  4. 负载平衡器仅充当中继器。 将其发送回客户端。
  5. 下次用户再次向服务器请求购物车时。 这次用户还发送了Cookie标头
  6. 负载均衡器拦截请求并使用循环方式将其发送到其中之一的tomcat。 这次将其发送到tomcat2。
  7. Tomcat 2收到请求并提取会话ID。 并且此会话ID与他们的托管会话不匹配。 因为此会话仅在tomcat1中可用。 所以tomcat 2是创建新会话并将新的cookie发送给客户端
  8. 客户端收到响应并更新cookie(它会覆盖旧的cookie)。
  9. 客户端再发送一次请求该页面并将cookie发送到服务器。
  10. 负载均衡器拦截请求并使用循环方式将其发送到其中之一的tomcat。 这次将其发送到tomcat3。
  11. Tomcat 3接收请求并提取会话ID。 并且此会话ID与他们的托管会话不匹配。 因为此会话仅在tomcat2中可用。 因此,tomcat3将创建新会话并将新的cookie发送给客户端
  12. 客户端收到响应并更新cookie。(它将覆盖旧的cookie)。
  13. 客户端再发送一次请求该页面并将cookie发送到服务器。
  14. 负载均衡器拦截请求并使用循环方式将其发送到其中之一的tomcat。 这次将其发送到tomcat1。
  15. Tomcat 1收到请求并提取会话ID。 并且此会话ID与他们的托管会话不匹配。 因为客户端会话ID是上次由Tomcat 3更新的。 因此,即使tomcat 1拥有一个由该客户端创建的会话对象。 但是客户端会话ID错误。因此,tomcat3创建了新会话并将新的Cookie发送给客户端(有关更多信息,请观看下面的视频)
  16. 客户端收到响应并更新cookie。

此顺序继续……

结果,在每个请求上都会创建一个新会话。 而不是继续旧的。

根本原因是负载均衡器 。 如果负载均衡器正确地重定向了请求,则此问题已解决。 但是负载均衡器如何在特定的Tomcat实例处理该客户端之前预先知道该客户端。

HTTP是无状态协议。 因此,HTTP无法解决这种情况。 其他信息是jsessionid cookie。 很好,但这只是一个随机值。 因此,我们无法根据此随机值做出决定。

例如:

Cookie:JSESSIONID = 40025608F7B50E42DFA2785329079227

会话亲和力/粘性会话

会话亲缘关系通过将会话中的所有请求定向到特定的Tomcat服务器来覆盖负载平衡算法。 因此,当我们设置会话亲和力时,我们的问题就解决了。 但是如何设置它,问题是会话值是随机值。 因此,我们需要生成会话值,以某种方式确定哪个Tomcat实例生成响应。

jvmRoute

Tomcat配置文件(server.xml)包含<Engine>标记,该标记为此具有jvmRoute属性。 因此,编辑配置文件并像这样更新<Engine>标记

<Engine name='Catalina' defaultHost='localhost“ jvmRoute=“tomcat1” >

这里我们提到jvmRoute ='tomcat1'

这里,tomcat1是此Tomcat实例的工作程序名称。 检查最后一篇文章中的worker.properties文件。

将此行添加到所有Tomcat实例conf / server.xml文件中,然后重新启动Tomcat实例。

现在所有的Tomcat实例都生成如下的session-id模式

<与之前一样的随机值>。<jvmRoute值>

例如:

Cookie:JSESSIONID = 40025608F7B50E42DFA2785329079227.tomcat1

在此值的末尾,我们可以看到哪个Tomcat实例已生成此特定会话。 因此,负载平衡器可以轻松找出我们需要在哪里委派请求。 在这种情况下,它是tomcat1。

因此,更新所有tomcat实例conf / server.xml文件,以将jvmRoute属性添加到适当的工作程序名称值。 并重新启动实例。 解决了所有问题,即使在基于会话的应用程序中,整个负载平衡也可以正常工作。 但是仍然有一个缺点

假设有5位用户正在访问该网站。 会话亲和力已设置。 这里

tomcat 1服务2位用户,

tomcat 2服务2位用户,

tomcat 2为1个用户服务,然后突然其中一个实例失败。 那会怎样

假设实例1(tomcat1)失败,则这2个用户丢失了会话。 但是他们的请求被重定向到剩余的tomcat实例之一(tomcat2,tomcat3)。 因此他们仍然可以访问网页。 但是他们输掉了以前的比赛。 这是缺点之一。 但与上一个后期负载均衡器相比,它也可以在基于会话的Web应用程序中工作。

在下一篇文章中,我们将看到如何在负载均衡器中设置会话复制。

视频

http://www.youtube.com/watch?feature=player_embedded&v=-9C2ZtdAAFY

参考: Tomcat群集系列第2部分:来自Ramki Java Blog博客的JCG合作伙伴 Rama Krishnan提供的会话亲和力负载均衡器

翻译自: https://www.javacodegeeks.com/2012/11/tomcat-clustering-series-part-2-session-affinity-load-balancer.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值