• The Apache Tomcat Servlet/JSP Container


    1、Tomcat部署的场景分析

    通常,我们对tomcat单机部署需求可以分为几种:

    • 单实例单应用 (一个tomcat 一个web应用)
    • 单实例多应用 (一个tomcat多个应用)
    • 多实例单应用 (多个tomcat都部署一个应用)
    • 多实例多应用 (多个tomcat部署多个不同的应用)

    第一种场景:这是我们开发中经常用到的,如果不要求周期性地维护tomcat版本,一般的做法是把打好的war包丢到webapps目录下,然后执行startup.sh脚本,并且可以在浏览器里访问就行了。
    第二种场景:是把多个应用程序的war包放在同一个tomcat的webapps目录,这样一来,关闭和启动tomca,或tomcat挂掉会影响所有项目。
    第三种场景: 各个tomcat都运行同一个应用程序,对应地需要修改不同的监听端口,这种方式通常会和apache httpd或者nginx整合使用,做一些负载均衡的处理。
    第四种场景: 相当于第一种场景的复数形式,除了修改不同的监听端口,没有本质区别。

    一般来说,多实例部署tomcat,可以充分利用系统资源,不过这种方式,也有几个方面需要考虑:
    多实例tomcat的更新维护,例如对tomcat进行升级等操作,我们需要考虑如何能“优雅”地对所有实例进行升级
    尽量不要影响应用程序,在更新tomcat时,一不小心就把conf目录等全部覆盖,所以尽量要把配置文件和安装目录隔离
    对于单应用来说,如果将war包分别置于各个tomcat的webapps目录,那么在发布新版本的war时,可能会出现某个实例更新失败,导致用户在访问时可能会访问到不同版本的web app,因此,比较好的方式就是所有tomcat实例都统一指向同一个应用程序,这样做,就可以多个tomcat用一份应用源码,简单部署,单机高可用也能实现(要配合nginx).
    本文重点阐述多实例应用的部署方案,但是为了解决上述几个问题,我们需要先来了解一下tomcat的一些基本情况。

    2、我们的目标

    tomcat架构

    3、tomcat架构

    整体架构图

    tomcat架构

    这里有一台服务器,3台tomcat服务,以及一台tomcat的解构图。

    分离目录

    目录作用
    bin 主要存放脚本文件,例如比较常用的windows和linux系统中启动和关闭脚本
    conf 主要存放配置文件,其中最重要的两个配置文件是server.xml和web.xml
    lib 主要存放tomcat运行所依赖的包
    logs 主要存放运行时产生的日志文件,例如catalina.{date}.log等
    temp 存放tomcat运行时产生的临时文件,例如开启了hibernate缓存的应用程序,会在该目录下生成一些文件
    webapps 部署web应用程序的默认目录
    work 主要存放由JSP文件生成的servlet(java文件以及最终编译生成的class文件)

    再介绍两个tomcat中比较重要的概念(通常也是两个系统变量)——CATALINA_HOME和CATALINA_BASE:

    CATALINA_HOME:即指向Tomcat安装路径的系统变量
    CATALINA_BASE:即指向活跃配置路径的系统变量通过设置这两个变量,就可以将tomcat的安装目录和工作目录分离,从而实现tomcat多实例的部署。
    Tomcat官方文档指出,CATALINA_HOME路径的路径下只需要包含bin和lib目录,这也就是支持tomcat软件运行的目录,而CATALINA_BASE设置的路径可以包括上述所有目录,不过其中bin和lib目录并不是必需的,缺省时会使用CATALINA_HOME中的bin和conf。如此,我们就可以使用一个tomcat安装目录部署多个tomcat实例,这样的好处在于方便升级,就可以在不影响tomcat实例的前提下,替换掉CATALINA_HOME指定的tomcat安装目录。

    tomcat架构

    tomcat serve.xml 配置结构
    Container容器子容器间关系图

    tomcat架构

    交互图

    tomcat架构

    对比下Tomcat serve.xml 的配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    <?xml version="1.0" encoding="UTF-8"?>
    <Server port="8005" shutdown="SHUTDOWN">
    <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
    <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
    <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
     
    <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
    type="org.apache.catalina.UserDatabase"
    description="User database that can be updated and saved"
    factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
    pathname="conf/tomcat-users.xml" />
    </GlobalNamingResources>
    <Service name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" />
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    <Engine name="Catalina" defaultHost="localhost">
    <Realm className="org.apache.catalina.realm.LockOutRealm">
    <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
    resourceName="UserDatabase"/>
    </Realm>
    <Host name="localhost" appBase="webapps"
    unpackWARs="true" autoDeploy="true">
    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
    prefix="localhost_access_log" suffix=".txt"
    pattern="%h %l %u %t &quot;%r&quot; %s %b" />
    </Host>
    </Engine>
    </Service>
    </Server>

    4、实战

    <Server>                                                //顶层类元素,外层最大的容器,可以包括多个Service  
        <Service>                                           //顶层类元素,可包含一个Engine,多个Connecter
            <Connector>                                     //连接器类元素,代表通信接口
                    <Engine>                                //容器类元素,为特定的Service组件处理客户请求,要包含多个Host
                            <Host>                          //容器类元素,为特定的虚拟主机组件处理客户请求,可包含多个Context
                                    <Context>               //容器类元素,为特定的Web应用处理所有的客户请求
                                    </Context>
                            </Host>
                    </Engine>
            </Connector>
        </Service>
    </Server>
    
    ------
    其中
    <Service name="Catalina">   //Catalina容器
     
    <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>    //根据ip、端口建立连接
     
    <Context docBase="web" path="/" reloadable="true" source="org.eclipse.jst.jee.server:web"/></Host>  //该Server下部署的项目,项目名称为web,path也就是该项目的根访问路径
    

      

    端口配置

    修改server.xml

    在server.xml中配置了四个监听端口,分别是:
    Server Port:该端口用于监听关闭tomcat的shutdown命令,默认为8005.
    Connector Port:该端口用于监听HTTP的请求,默认为8080.
    AJP Port:该端口用于监听AJP( Apache JServ Protocol )协议上的请求,通常用于整合Apache Server等其他HTTP服务器,默认为8009
    Redirect Port:重定向端口,出现在Connector配置中,如果该Connector仅支持非SSL的普通http请求,那么该端口会把https的请求转发到这个Redirect Port指定的端口,默认为8443

    虚拟主机配置
    再来说Host配置,Host就是所谓的虚拟主机,对应包含了一个或者多个web应用程序,默认的Host配置如下

    1
    <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">

    其中:
    name: 虚拟主机的名称,一台主机表示了完全限定的域名或IP地址,默认为localhost,同时也是唯一的host,进入tomcat的所有http请求都会映射到该主机上
    appBase:web应用程序目录的路径,可以是CATALINA_HOME的相对路径,也可以写成绝对路径,默认情况下为$CATALINA_HOME/webappsunpackWARs: 表示是否自动解压war包
    autoDeploy:所谓的热部署,即在tomcat正在运行的情况下,如果有新的war加入,则会立即执行部署操作
    另外再介绍一个Host中的属性—deployOnStartup:表示tomcat启动时是否自动部署appBase目录下所有的Web应用程序,默认为true。这个属性和autoDeploy会产生两次部署的“副作用”:一次是tomcat启动时就开始部署,第二次就是autoDeploy引起的热部署。因此最好将autoDeploy置为false
    在部署多实例单应用的时候,默认的$CATALINA/webapps会因为tomcat安装目录升级产生不必要的麻烦,我们考虑将appBase的目录统一到另外的路径下。

    Context的配置
    最后再说明一下Context的配置,它出现在Host配置内,一个Context的配置就代表了一个web应用程序,如果配置多应用程序,就需要在Host下配置多个Context,一个简单的Context配置如下

    1
    <Context path="/some" docBase="someapp.war" >

    path:表示访问入口,例如,path=”/abc”,则访问localhost:8080/abc时,就可以访问该Context对应的应用程序。如果path=””,则直接用localhost:8080就可以访问
    docBase:表示应用程序的解包目录或者war文件路径,是Host的appBase配置目录的相对路径,也可以是直接写成绝对路径,但是不要将appBase的值,作为docBase配置路径的前缀,例如appBase=”somedir”,docBase=”somedir-someapp.war”,这样的配置会导致部署错误
    通过配置Host的appBase和Context的docBase两个属性,可以将应用程序的文件和tomcat相关的目录进行分离,这样webapps目录也就没有作用了。

    跟我来实施该方案

    • 现在假设我们有一台已经配置好Java环境的服务器:(我用的是阿里云)
    • 我已经有一个已经完成的shop.war 应用程序

    步骤1:
    下载并解压tomcat

    tomcat架构

    步骤2:
    对Tomcat目录作以下调整:
    在tomcat安装目录下创建a.ttlsa.com、b.ttlsa.com,并且将conf、logs、webapp、temp、work目录拷贝到这两个目录,然后tomcat安装目录只需要留下bin、a.ttlsa.com、b.ttlsa.com、lib这4个目录即可。配置后的目录结构如下:

    tomcat架构

    如果要度tomcat 进行升级,我们只是需要对tomcat的lib 和 bin 目录进行升级即可。

    步骤3:
    配置站点server.xml
    配置a.ttlsa.com 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 8005 改为8005 -->
    <Server port="8005" shutdown="SHUTDOWN">
    <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
    <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
    <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
     
    <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
    type="org.apache.catalina.UserDatabase"
    description="User database that can be updated and saved"
    factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
    pathname="conf/tomcat-users.xml" />
    </GlobalNamingResources>
     
    <Service name="Catalina">
    <Connector port="8081" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" />
     
    <!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->
     
    <Engine name="Catalina" defaultHost="localhost">
    <Realm className="org.apache.catalina.realm.LockOutRealm">
    <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
    resourceName="UserDatabase"/>
    </Realm>
    <!--
    <Host name="localhost" appBase="webapps"
    unpackWARs="true" autoDeploy="true">
    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
    prefix="localhost_access_log" suffix=".txt"
    pattern="%h %l %u %t &quot;%r&quot; %s %b" />
     
    </Host>
    -->
     
    <Host name="localhost" appBase="F:datawwwa.ttlsa.com"
    unpackWARs="true" autoDeploy="true"
    xmlValidation="false" xmlNamespaceAware="false">
    <Context path="" docBase="" reloadable="true">
    <valve className="org.apache.catalina.valves.RemoteAddrValve" />
    </Context>
    </Host>
     
    </Engine>
    </Service>
    </Server>

    配置b.ttlsa.com

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 8005 改为8006 -->
    <Server port="8002" shutdown="SHUTDOWN">
    <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
    <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
    <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
     
    <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
    type="org.apache.catalina.UserDatabase"
    description="User database that can be updated and saved"
    factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
    pathname="conf/tomcat-users.xml" />
    </GlobalNamingResources>
     
    <Service name="Catalina">
    <Connector port="8082" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" />
     
    <!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->
     
    <Engine name="Catalina" defaultHost="localhost">
    <Realm className="org.apache.catalina.realm.LockOutRealm">
    <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
    resourceName="UserDatabase"/>
    </Realm>
    <!--
    <Host name="localhost" appBase="webapps"
    unpackWARs="true" autoDeploy="true">
    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
    prefix="localhost_access_log" suffix=".txt"
    pattern="%h %l %u %t &quot;%r&quot; %s %b" />
     
    </Host>
    -->
     
    <Host name="localhost" appBase="F:datawwwa.ttlsa.com"
    unpackWARs="true" autoDeploy="true"
    xmlValidation="false" xmlNamespaceAware="false">
    <Context path="" docBase="" reloadable="true">
    <valve className="org.apache.catalina.valves.RemoteAddrValve" />
    </Context>
    </Host>
     
    </Engine>
    </Service>
    </Server>

    创建多实例启动脚本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    # description: 启动tomcat多实例.#
    . /etc/init.d/functions
    RETVAL=$?
    # tomcat实例目录
    export CATALINA_BASE="$PWD"
    # tomcat安装目录
    export CATALINA_HOME="/usr/local/tomcat-7.0.50"
    # 可选
    export JVM_OPTIONS="-Xms128m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=512m"
    case "$1" in
    start)
    if [ -f $CATALINA_HOME/bin/startup.sh ];then
    echo $"Start Tomcat"
    $CATALINA_HOME/bin/startup.sh
    fi
    ;;
    stop)
    if [ -f $CATALINA_HOME/bin/shutdown.sh ];then
    echo $"Stop Tomcat"
    $CATALINA_HOME/bin/shutdown.sh
    fi
    ;;
    *)
    echo $"Usage: $0 {start|stop}"
    exit 1
    ;;
    esac
    exit $RETVAL

    这段shell 脚本比较简单,主要是设置环境变量,接受命令参数 RETVAL=?RETVAL=start/stopexportCATALINABASE=?,来执行不同的命令。RETVAL=start/stop等exportCATALINABASE=”PWD” 表示设置当前路径为 CATALINA_BASE 的环境变量,一般情况下CATALINA_BASE 和 CATALINA_HOME 是默认一样的。

    启动脚本赋权限

    1
    # chmod a+x tomcat.sh

    5、启动测试

    启动/关闭a.ttlsa.com

    1
    2
    3
    4
    5
    6
    启动
    # cd /usr/local/tomcat-7.0.50/a.ttlsa.com/
    # ./tomcat.sh start
    关闭
    # cd /usr/local/tomcat-7.0.50/a.ttlsa.com/
    # ./tomcat.sh stop

    启动/关闭b.ttlsa.com

    1
    2
    3
    4
    5
    6
    启动
    # cd /usr/local/tomcat-7.0.50/a.ttlsa.com/
    # ./tomcat.sh start
    关闭
    # cd /usr/local/tomcat-7.0.50/a.ttlsa.com/
    # ./tomcat.sh stop

    备注:一定需要cd到tomcat.sh的当前目录下执行才可以

    在win7 下,需要创建在a.ttlsa.com 和b.ttlsa.com下面创建 startup.bat 来启动

    1
    2
    3
    4
    5
    6
    @echo off
    set JAVA_HOME=D:Program FilesJavajdk1.8.0_112
    set PATH=%JAVA_HOME%in;%PATH%
    set CATALINA_BASE=%CD%
    cd E: omcat-8.5.6in
    catalina.bat start

    这段是在win7 下云的bat脚本,于shell脚本同理,set CATALINA_BASE=%CD% 也是设置环境变量,CD 可以获取当前的路径。

    shell 脚本入门参考:

    6、结果

    单个Tomcat应用多个tomcat实例的配置到此,就结束了。
    此外,我们在这里的基础上进行系统的扩展,比如如果我的Tomcat应用挂掉了,我的整个应用都将不可用了,我们应该如何处理?
    我们可以把Tomcat复制多份,在单机的情况下,开多一个Tomcat进程,在配合Nginx 来配置,就能实现Tomcat的自动切换,这些内容,有空再写。

    如果需要操作多个实例显得比较麻烦,大家可以自行写统一的脚本。

    tomcat架构
    tomcat架构

    Linux 下的实现基本一致。

    这样的好处是,显而易见的,这样能开启Tomcat的多个进程,即多台tomcat,挂了也不太怕,还有其他tomcat应用支撑,代码实例我们发版本的时候,只需要发布一份,实例代码易于维护。
    但是,我们网站的域名和端口一般是同一采用80端口,统一的域名,而现在我们开启tomcat只能一个使用80端口,显然是不合适的·,为此我们会引入负载均衡的nginx来配置。
    nginx 采用80 端口,tomcat分别采用8080, 8081, 8082 这样就能让我们的程序稳定的运行。
    这样,我们就能进最大的限度来压榨单机的性能,保证应用程序的稳定的运行。
    而然,单机不然有单机的瓶颈,毕竟单机中的cpu 已经各种硬件的限制,会大大影响实例程序的跑动,在这时,就不再是单机能抗的动的了,我们需要分析程序的瓶颈在那?数据库,那就把数据库单独分出去,单独一台机器,是文件图片服务器,就把他分出去。如果是应用程序太大,就要考虑把应用实例进行拆解为不同哦那个的组件,单独部署,这就是分布式部署。
    当然,这都是后话,只有程序复杂到一定的程度,并体量很大的话,才会做这种架构的演变,成本和技术投入的难度也会相应的变大。
    本章,只局限于如何玩好单机的基础上来讨论,对于分布式的那块,笔者能力有限,尚且还不能完全驾驭,不做分享。

    7、nginx+tomcat热备

    在上面的配置的基础上,我们在进一步进行扩展,进行实例的均衡和热备。
    可以在一个服务器挂了的情况下连到另外一个,那怎么弄呢?
    其实很简单,在upstream中的local_tomcat中配置多一个server。
    在上面,我的a.ttlsa.com 和 b.ttlsa.com 都是访问 F:datawwwa.ttlsa.com 下的源码的index.jsp 页面,
    为了能观察,nginx 的keepAlive 的效果,我做一下修改:
    a.ttlsa.com —> F:datawwwa.ttlsa.com index.jsp 中文字是 1
    b.ttlsa.com —> F:datawww.ttlsa.com index.jsp 中文字是 2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    upstream local_tomcat {
    server localhost:8081 weight=1;
    server localhost:8082 weight=5;
    }
     
    server {
    listen 80;
    server_name localhost:8081;
     
    #charset koi8-r;
     
    #access_log logs/host.access.log main;
     
    #location / {
    # root html;
    # index index.html index.htm;
    #}
    location / {
    proxy_pass http://local_tomcat;
    }
    tomcat架构

    在通常的情况下,我们一般是指向一份源码就足够了,并且设置权值,减轻应用的压力。同时也不会出现单点的情况。

    补充:nginx.con 配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    #user nobody;
    worker_processes 1;
    events {
    worker_connections 1024;
    }
    http {
    include mime.types;
    default_type application/octet-stream;
     
    sendfile on;
    #tcp_nopush on;
     
    #keepalive_timeout 0;
    keepalive_timeout 65;
     
    #gzip on;
     
    upstream local_tomcat {
    server localhost:8081 weight=1;
    server localhost:8082 weight=5;
    }
     
    server {
    listen 80;
    server_name localhost;
     
    #charset koi8-r;
     
    #access_log logs/host.access.log main;
     
    #location / {
    # root html;
    # index index.html index.htm;
    #}
    location / {
    proxy_pass http://local_tomcat;
    }
     
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    root html;
    }
    }
     
    }

    综上:我们做到了多台tomcat 但是我们也能做到tomcat的简单升级,并且实现实例的负载均衡,已经应用的主备,在也不用担心应用挂掉而睡不了觉了。
    缺点:nginx依然存在单点的问题。

    本次的实验资源供下载:http://download.csdn.net/detail/a82793510/9687715

    经验之谈

    如果是在资源有限的情况下,已经选择了单机,证明不是有钱荏,我一般会把上面的权去掉,在这样我们就可以在一台tomcat应用服务器挂掉的情况下,才会访问备机Tomcat应用服务器。
    如果只是应用的情况下,这样已经足够了。用基于IP分发的策略已经能解决绝大部分需求。

    资源进一步极端化

    现在,我们在这台单机上已经部署了一个应用app1, 假设现在我司实在是资源太紧缺了,我们又要在这台机子上,部署另外一个应用app2。
    那么现在我们就要对Nginx 和 Tomcat 进行改动。
    改动一般分为2种方法:2级域名改动 或 2级目录改动。
    先来在上面的基础上说说二级目录改动:
    按照我们上面的,我们的目标的架构:我们已经部署了一个应用程序:some.war ,现在我要采用二级目录方式部署另外的一个应用程序:app.war。
    那么我会在上面的基础上做如下的修改:localhost 可以修改为自己的域名。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <Host name="localhost/some" appBase="F:datawwwa.ttlsa.com"
    unpackWARs="true" autoDeploy="true"
    xmlValidation="false" xmlNamespaceAware="false">
    <Context path="" docBase="" reloadable="true">
    <valve className="org.apache.catalina.valves.RemoteAddrValve" />
    </Context>
    </Host>
    <Host name="localhost/app" appBase="F:datawww.ttlsa.com"
    unpackWARs="true" autoDeploy="true"
    xmlValidation="false" xmlNamespaceAware="false">
    <Context path="" docBase="" reloadable="true">
    <valve className="org.apache.catalina.valves.RemoteAddrValve" />
    </Context>
    </Host>

    另外的一台的service.xml 也同样如此配置。
    nginx中的localhost 可以修改为自己的域名 如 mp.hello.io

    1
    2
    3
    4
    5
    server {
    listen 80;
    server_name localhost; // 可以修改为自己的域名
     
    }

    二级域名的改动,
    前提:我们有一个顶级域名:如 hello.io 这样的一个顶级域名:
    那么,我们现在可以这样做:
    现在万网中配置一下我们的二级域名,如som.hello.io和app.hello.io 都要在万网中指向我们的服务器Ip 地址。
    在增加二级域名的情况下,我们可以新增2个是实例。
    把Nginx修改为这样的配置:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    #user nobody;
    worker_processes 1;
    events {
    worker_connections 1024;
    }
    http {
    include mime.types;
    default_type application/octet-stream;
     
    sendfile on;
    #tcp_nopush on;
     
    #keepalive_timeout 0;
    keepalive_timeout 65;
     
    #gzip on;
     
    upstream local_tomcat01 {
    server localhost:8081;
    server localhost:8082;
    }
    upstream local_tomcat02 {
    server localhost:8083;
    server localhost:8084;
    }
    server {
    listen 80;
    server_name some.hello.io;
     
    #charset koi8-r;
     
    #access_log logs/host.access.log main;
     
    #location / {
    # root html;
    # index index.html index.htm;
    #}
    location / {
    proxy_pass http://local_tomcat02;
    }
     
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    root html;
    }
    }
     
    server {
    listen 80;
    server_name app.hello.io;
     
    #charset koi8-r;
     
    #access_log logs/host.access.log main;
     
    #location / {
    # root html;
    # index index.html index.htm;
    #}
    location / {
    proxy_pass http://local_tomcat02;
    }
     
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    root html;
    }
    }

    此外,修改一下,Tomcat 的端口就可以了,同时80 81, 指向一个实例,83 84 指向另外一个实例(appBase中指定)。这样就可以做到程序的主备操作。

    备注:service_name 的名称可以是ip 地址。
    nginx在配置upstream时,有两个参数:
    ip_hash(同一IP一直使用同一台server服务)
    weight(server的使用权重,数值越大,nginx分发的请求越多)

    通过配合这两个参数,能粗糙地解决session共享的问题。
    对于一些不是太依赖session的应用,或者只有用户登录时保存,那么我认为可以用Cookies代替。
    即使真的要Session共享,我认为手动写代码保存到Memcached比为Tomcat加插件好,这样能获得更好的可控性。
    而且我不用Tomcat,用Redis,这个msm就用不上啦,不过我会按照我的思想实现session共享,呵呵,个人愚见!

    tomcat架构

    最后我们的架构是这样的。在这样的解构下,我们无论是修改为 二级目录 亦或是二级域名,我们运维都只是要做很小的改动就能切换。配置和源码分离的结构,对我们以后的扩展为分布式应用,还是依然是单机的传统结构都是进可以攻退以守。
    留有余地,唯一不足就是nginx的单点问题,不过就单机体系来说已经够用了。

    集群、会话保持

    上面不架构已经是属于在单机上做了一个简单的集群了,要实现Tomcat。
    要多台机器,只要修改上面Nginx的分发的Ip 就可,但是会话共享是一个很大的问题,但是,用基于IP分发的策略已经能解决绝大部分需求。
    这里已经脱离了我们单机应用的主题,以后有机会探讨。

    Docker安装tomcat,并提供Web应用服务

    CATALINA_HOME和CATALINA_BASE的区别

    日志

    日志引擎,日志种类,日志收集,日志分析,日志切割,日志清理

     Tomcat日志管理(一) - CSDN博客 https://blog.csdn.net/pengjunlee/article/details/79477567

     Apache Tomcat 7 (7.0.88) - Logging in Tomcat http://tomcat.apache.org/tomcat-7.0-doc/logging.html

    tomcat日志集中采集、分析与展示的几种方法 - CSDN博客 https://blog.csdn.net/enweitech/article/details/79543320 

    Tomcat访问日志分析 - CSDN博客 https://blog.csdn.net/leizi191110211/article/details/51669431 

    tomcat6 日志配置说明 - longdechuanren - 博客园 https://www.cnblogs.com/hailong-tec/p/6834583.html 

    Java常用日志框架介绍 - chlsmile - 博客园 https://www.cnblogs.com/chenhongliang/p/5312517.html 

     Tomcat 的 catalina.out 日志分割 - R.U.Ready - 博客园 https://www.cnblogs.com/RUReady/p/7048920.html

     如何将tomcat8的运行日志框架切换到log4j2 - CSDN博客 https://blog.csdn.net/shiyong1949/article/details/78850230

     Tomcat使用Log4j输出catalina.out日志 - CSDN博客 https://blog.csdn.net/u013673976/article/details/51425645

     Tomcat日志系统详解 - CSDN博客 https://blog.csdn.net/xysoul/article/details/50347285

     tomcat logs 目录下各日志文件的含义 - signheart - 博客园 https://www.cnblogs.com/signheart/p/0ed0bef7dfadf59534eec76ad4607654.html

     简述Tomcat的日志系统 - CSDN博客 https://blog.csdn.net/hspingcc/article/details/73206146?utm_source=itdadao&utm_medium=referral

     【Tomcat】tomcat logs 目录下各日志文件的含义 - QiaoZhi - 博客园 https://www.cnblogs.com/qlqwjy/p/8036091.html

     tomcat配置参数详解 - CSDN博客 https://blog.csdn.net/zhu_xun/article/details/16817937

     tom猫—–(Tomcat详解) | Linux运维部落 http://www.178linux.com/88456

    监控、

    应用更新部署、热部署、冷部署、灰度发布

  • 相关阅读:
    D. Babaei and Birthday Cake--- Codeforces Round #343 (Div. 2)
    Vijos P1389婚礼上的小杉
    AIM Tech Round (Div. 2) C. Graph and String
    HDU 5627Clarke and MST
    bzoj 3332 旧试题
    codeforces 842C Ilya And The Tree
    codesforces 671D Roads in Yusland
    Travelling
    codeforces 606C Sorting Railway Cars
    codeforces 651C Watchmen
  • 原文地址:https://www.cnblogs.com/aftree/p/9111142.html
Copyright © 2020-2023  润新知