入门级Tomcat集群

入门级Tomcat集群搭建

为什么是入门?讷讷,组件—使用的都是apache社区的免费组件了。
httpd+mod_jk+tomcat。入门换句话说,企业级开发基本不用。

  • 集群
  • Httpd
  • Mod_jk
  • Tomcat配置
  • Httpd配置
  • 代码
  • 集群高可用,热拔插
  • 一定要用session同步吗
  • 总结

集群

互联网,大数据的时代,软硬件集群已是常态话。tomcat集群结构如图:
这里写图片描述
负载均衡器依据配置的负载规则,将某一用户请求分配给tomcat集群中的某一tomcat服务。
下面给出集群的搭建,由于没有Linux机器用,因此该集群使用的是windows环境。

Httpd

Httpd是Apache的http服务器,用于http的转发。下载
Httpd下载完成,安装,程序运行默认占用80端口。启动后访问http://localhost/
这里写图片描述
It works!显示Httpd服务运行正常。

Mod_jk

Mod_jk是Apache/IIS 用来连接后台Tomcat的连接器,支持集群和负载均衡。下载
将下载到的mod_jk-1.2.31-httpd-2.2.3.so文件放入到Httpd安装目录下/modules目录下即可。

Tomcat配置

tomcat集群,因此至少要配置两个tomcat容器才能被称为集群。
修改tomcat容器/conf/server.xml文件。

<!--为Engine标签增加jvmRoute属性并赋值,就代表这个tomcat容器的唯一名字呗-->
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">

并在Engine标签中增加集群的配置,session同步就是通过这个广播的。并切记是在Engine标签中。

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

          <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="4000"
                          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.MessageDispatch15Interceptor"/>
          </Channel>

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

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                    tempDir="/tmp/war-temp/"
                    deployDir="/tmp/war-deploy/"
                    watchDir="/tmp/war-listen/"
                    watchEnabled="false"/>

          <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
       </Cluster>

另外的tomcat也按照如此配置方式。我这里默认jvmRoute=”tomcat2”了。

Httpd配置

嗯,Tomcat配置好了,就需要将tomcat的信息配置到Httpd中了。
Httpd安装目录/conf目录下新建文件:mod_jk.conf。并加如如下内容:

#加载mod_jk Module 
LoadModule jk_module modules/mod_jk-1.2.31-httpd-2.2.3.so

#指定workers.properties文件路径 该文件中配置tomcat服务的信息
JkWorkersFile conf/workers.properties

#指定那些请求交给tomcat处理,"controller"为在workers.propertise里指定的负载分配控制器名 *就是将所有请求。
JkMount /* controller

也就是将请求都转发给workers。
Httpd安装目录/conf目录下新建文件:workers.propertise。并加入如下内容:

#server
worker.list = controller
#========tomcat1========
#ajp13端口号,在tomcat下server.xml中Connector标签的端口
worker.tomcat1.port=8009

#tomcat的主机地址,如不为本机,请填写ip地址 
worker.tomcat1.host=localhost

#协议类型
worker.tomcat1.type=ajp13

#server的加权比重,值越高,分得的请求越多。lbfactor是负载平衡因数(Load Balance Factor)
worker.tomcat1.lbfactor=1

#========tomcat2========
worker.tomcat2.port=9009
worker.tomcat2.host= localhost
worker.tomcat2.type=ajp13
worker.tomcat2.lbfactor=1

#========controller,负载均衡控制器========
#负载均衡控制器类型,lbfactor是负载平衡因数(Load Balance Factor)
worker.controller.type=lb

#指定分担请求的tomcat列表  server.xml文件中jvmRoute制定的唯一名称。
worker.controller.balanced_workers=tomcat1,tomcat2

#粘性session(默认是打开的) 当该属性值=true(或1)时,代表session是粘性的,即同一session在集群中的同一个节点上处理,session不跨越节点。在集群环境中,一般将该值设置为false
worker.controller.sticky_session=false

#设置用于负载均衡的server的session可否共享
worker.controller.sticky_session_force=true

咦!该配置的都配置好了吗?差一小步,httpd.conf文件中需要引入刚刚定义的mod_jk.conf文件。只需要在httpd.conf末尾加入Include conf/mod_jk.conf即可。
好了tomcat集群搭建完成。
重启httpd服务即可访问,刷新http://localhost/跳转tomcat界面。至此集群搭建成功。

完了?NO!

是时候来一些代码来证明这个集群可用。

代码

代码通过meavn管理。新建meavn的web项目。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.tomcat</groupId>
  <artifactId>tomcat_colony_project</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>tomcat_colony_project Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-servlet-api -->
<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-servlet-api</artifactId>
    <version>9.0.0.M25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>


  </dependencies>
  <build>  
      <plugins>  
        <plugin>  
            <groupId>org.apache.maven.plugins</groupId>  
            <artifactId>maven-compiler-plugin</artifactId>  
            <version>2.3.2</version>  
            <configuration>  
                <source>1.8</source>  
                <target>1.8</target>  
                <encoding>utf-8</encoding>
            </configuration>  
        </plugin> 

         <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <port>8088</port>
                    <path>/</path>
                    <uriEncoding>UTF-8</uriEncoding>
                    <finalName>colony</finalName>
                    <server>tomcat7</server>
                </configuration>
          </plugin>

      </plugins>  


    </build>  
</project>

新建Servert,要实现逻辑:当session中无数据时插入session数据

package com.ccycc.tomcat.colony;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyServert extends HttpServlet{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub

        Object content = req.getSession().getAttribute("session");
        if(content == null || content.toString().trim().length() == 0) {

            req.getSession().setAttribute("session", "ccycc_" + Math.random());
        }
        resp.sendRedirect(req.getContextPath());
    }



}

修改web.xml。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name></display-name>
  <servlet>
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>com.ccycc.tomcat.colony.MyServert</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/servlet/MyServlet</url-pattern>
  </servlet-mapping>    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <distributable/>

</web-app>

来一个简单的index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
  </head>

  <body>
    server info : ${pageContext.request.localAddr}:${pageContext.request.localPort} <br>
    <br>
    session ID : ${pageContext.session.id} <br>
    <br>
    session value : ${sessionScope["session"]}
    <form action="${pageContext.request.contextPath}/servlet/MyServlet?method=session" method="post">
        <input type="submit" value="seesionsubmit">
    </form>
  </body>
</html>

OK!将应用部署到tomcat服务中即可。请求http://localhost/tomcat_colony_project-0.0.1-SNAPSHOT/
这里写图片描述
点击按钮可以看到以轮询的方式访问,并且session不会变。说明session是共享的。
启动tomcat时可以看到日志,如下的日志就是集群之间通过udp广播并共享session。
这里写图片描述
因此如果发现session不可共享,就要查查是否时跨域等网络问题。

集群高可用,热拔插

集群本事高可用的,通过kill或启动tomcat服务,你变可以发现httpd是支持热拔插的。

一定要用session同步吗

互联网级的开发,不可能将session或者token存储于内存中吧,试想用户量上来,那可不是内存吃的消的。redis就是一个很好的选择。那还要同步session吗?仁者见仁智者见智吧!
可以试着去掉tomcat中的集群配置,请求照样正常转发,但是缺点是http请求都是短链接(集群中一个tomcat容器除外),每次请求都会新建会话。

总结

入门级的一个tomcat集群,不能说明问题,只是要多用互联网的思维取考虑问题。


技术为王
这里写图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值