zoukankan      html  css  js  c++  java
  • 众人拾柴火焰高之Tomcat集群

    一人拾柴火不旺,众人拾柴火焰高。Tomcat服务器也是一样,一台服务器再强大能承受的访问也是有限的。要提供高并发、高可用的服务,就必须横向扩展,多台Tomcat组成一个集群,根据实际的访问量动态增减服务器的部署。

    负载均衡的难点

    我们一般用session来保持会话,所以Tomcat服务器是有状态的。坏处是当一台宕机后自动跳转到另一台服务器可能会导致用户会话失效,最明显的例子就是要重新登录。所以以下的几种方法,都是在围绕session的问题。

    方案一、使用Tomcat自带的session同步功能

    如果我们使用nginx作为负载均衡服务器,它默认使用是轮询策略(也就是第一次请求分给服务器A,第二次分配给B,以此类推)。这种方案非常简单,但是别忘了我们的session是放在访问服务器上,轮询得结果是下次我们可能访问的是另一台服务器了,导致我们的会话不能保持。
    其实,解决起来也似乎很简单,就是创建session时,只需要把它复制给集群中的所有服务器就行了,下次不管访问哪一台Tomcat,它都能根据sessionID找到我们的session。非常幸运的是,Tomcat本身就已经帮我们实现了这个功能——session复制。我们只需简单两步配置即可:

    1. 在server.xml中打开以下注释:
    <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
    
    1. 在tomcat或者应用下web.xml,添加:
    <distributable/>
    
    是不是非常简单实用呢。
    
    简单归简单,不得不提的是,它有一个缺点,因为它默认使用BackupManager,是all-to-all的复制,所以如果大量节点的集群会有广播风暴,而且即使没有部署应用的节点也会复制。所以对大规模的集群,这种方案需谨慎考虑哦。
    

    方案二、使用nginx的ip_hash策略

    上面说了,nginx默认实用的是轮询策略,所以得配合session复制功能,才能保持会话。其实我们有一个更简单的方法,实用nginx的ip_hash策略。顾名思义,就是对ip进行hash散列,ip散列后找到指定的服务器,下次就一直访问这台服务器,这样一来,就不需要session复制了。
    配置起来也非常简单,nginx自身支持,只需在nginx配置中添加配置即可,Tomcat不需要任何处理:

    upstream mywebsite {
        server 110.119.88.1:8080;
        server 110.119.88.1:8080;
        ip_hash;   
    }
    

    凡事都有两面,它简单但也有一些缺点:

    1. nginx必须作为最前端的服务器,否则得不到正确的ip(自己暂未证实)
    2. nginx后不能再有其他的负载均衡,否则不能保证每次访问的是同一台服务器(未证实,不过按理应该是这样)
    3. 同一局域网下的多个用户可能每次访问的都是同一服务器。如我们的应用是给一个单位使用,使用ip_hash分流会很不理想
    4. 如果一台服务器挂了之后,自动跳转到另一台服务器,没有session,会需要重新登录

    方案三、使用nginx的nginx_upstream_jvm_route扩展模块

    上面两种方案都是nginx已支持的策略,接下来这种需要在nginx安装扩展模块。配置起来稍微复杂一些,需要完成以下三个步骤:

    1. 为nginx添加扩展模块
    2. Tomcat的server.xml标注jvmRoute
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="a">
    
    1. 配置文件nginx.conf中指明负载策略
    jvm_route $cookie_JSESSIONID;
    

    需要注意的是,这个模块通过session和cookie实现会话保持,如果url没有添加sessionid,或者用户禁用了浏览器cookie,则使用nginx默认的轮询,也就不会保持会话了。
    同样,他也有很大的缺点:我在配置实用时,没有找到支持nginx最新版本jvm_route,只找到支持nginx1.6的模块。

    方案四、使用Memcached或Redis统一管理session

    和上面的比起来,这个方案在大规模集群中更合理,管理起来更方便。
    使用Memcached或者redis集中管理session,而不是让Tomcat管理,所以每个Tomcat都是对等的、无状态的,集群便可以随意增减Tomcat了。使用的Memcached_Session_Manager管理session,安装Memcached服务器后,配置起来比较简单,就是在tomcat的context.xml配置中,指定使用Memcached管理器来管理session。

    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"    
            memcachedNodes="n1:memcached_server_ip:11211"  
            requestUriIgnorePattern=".*.(png|gif|jpg|css|js)$"  
            sessionBackupAsync="false"
            sticky="false"
            sessionBackupTimeout="100"  
            transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"  
            copyCollectionsForSerialization="false" />
    

    总结

    没有最好的,只有最适合的,综合实际情况,选择最适合当前项目的方案才是最好的方案。

  • 相关阅读:
    计算两个日期相差的天数
    获取当前星期几
    window下重置mysql用户密码
    window下安装mysql
    oracle用户密码过期如何处理?
    awk
    RunLoop
    通知中心
    KVO
    多线程
  • 原文地址:https://www.cnblogs.com/postnull/p/6394661.html
Copyright © 2011-2022 走看看