Tomcat 7 & 8 的多主机多端口配置入门

0x00 核心配置文件 Server.xml

  位于目录 conf 中的配置文件 server.xml 是 Tomcat 的核心配置文件,无论是涉及到 Tomcat 的性能还是安全,都是在此文件中进行配置。

  server.xml 由比较多的组织部件组成,下面是一张来自 Tomcat 使用文档中的图片,能够清晰地表达出各个配置部件的关系。

输入图片说明

  如果能够理解上面这图示的话,基本上对 Tomcat 的配置可以做到“胸有成竹”,下面是上图的一些注解:

  • Server 上的 8005 端口是 ShutDown 端口,通常用来接收 Server 启动、重启之类的命令。

  • Connector 上的连接(通讯端口),包括有两个:

    • 8080 :web 请求处理端口

    • 8009 : JK 集群通讯端口(通常与 Apache 集成)

  • 从上到下来看部件关系:

    • 每个服务器(Tomcat)可以有多个 Service 进程。通过配置不同的 Service 进程,可以使用不同访问端口来分离不同的应用。

    • 每个 Service 进程可以配置多个 Connector,每个 Connector 对应一个端口,这意味着可以设置多个访问端口(访问内容一样)。例如,我们配置 80、8080 两个端口。

    • 每个 Service 进程可以配置多个 Engine (每个 Engine 相当于一个 Servlet 容器),但是只有最后那个才生效,所以通常只会配置一个 Engine。

      • Engine 相当于请求处理器,接收来自 Connector 的请求数据,然后进行分析处理,再分派到 Host 中处理。
    • 每个 Engine 可以配置多个 Host (虚拟主机)

    • 每个 Host 可以配置多个 Context (应用)

  • 有几个配置注意点

0x01 配置实战

  下面以 Tomcat 8.x 为例子进行配置,虽然没试过 Tomcat 7.x。不过,相信应该同样适合。

  • 为每个 Servlet 容器分配独立的访问端口(或者为每个应用分配置独立的访问端口)

  下面是配置图示:

输入图片说明

  有时为了方便设置控制策略,会将系统分成多个应用,并且通过不同的端口进行访问。本例子,假设系统分成“前台”和“后台管理”两部分,不同子系统使用不同的访问端口。为了实现这样的需求,我们就定义为两个不用服务,每个服务配置自己的访问端口。   下面是配置示例:

<?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="FrontEnd"> <!-- 前端应用 -->
    <!-- 前端应用使用 80 这个端口 -->
    <Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

    <!-- Define an AJP 1.3 Connector on port 8009
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
     -->

    <!-- Engine name 要与 Service name 一致 -->
    <Engine name="FrontEnd" defaultHost="localhost">

      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <!-- 前端应用依然放在 webapps 这个目录 Host Name 通常与 Engine defaultHost 一致-->
      <Host name="localhost"  appBase="webapps" unpackWARs="true" autoDeploy="true">
	  
        <!-- access log 也用不同的文件名称来收集 -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="frontend_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>

    </Engine>

  </Service>

  <Service name="BackEnd"> <!-- 后台管理 -->
    <!-- 后台管理使用 8080 这个端口 -->
    <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

    <Engine name="BackEnd" defaultHost="localhost">

      <!-- 后端应该存放目录为:BackEndApps  要分开目录存放 -->
      <Host name="localhost"  appBase="BackEndApps" unpackWARs="true" autoDeploy="true">
        <!-- access log 也用不同的文件名称来收集 -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="backend_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>
    </Engine>
  </Service>

</Server>

  于是呢,我们就可以使用 http://xxxx/index 通过 80 端口访问前端应用,但是访问不了后端的应用。后端的应用需要类似 http://xxxx:8080/admin/index 来访问。

  因为是不同端口访问,网络安全工程师就可以使用控制策略来,让后台应用只能由局域网 ip 访问,提高系统的安全性。

  • 使用不同端口访问同一个应用

  这个需求似乎有点“怪”,不过有时候我们希望用户通过 80 和 8080 都能够访问应用。习惯了 Tomcat 的 8080 端口之后,需要配置使用 80 端口,那就干脆两个端口一起用吧。

  下面是配置图示:

输入图片说明

  有了第一个示例的经验,看了图示应该很快配置出来:

<?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">

    <!-- 使用 80 端口访问 -->
    <Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

    <!-- 配置使用 8080 端口访问 -->
    <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

    <!-- Define an AJP 1.3 Connector on port 8009
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
     -->

    <!-- Engine name 要与 Service name 一致 -->
    <Engine name="Catalina" defaultHost="localhost">

      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <!-- 应用依然放在 webapps 这个目录 Host Name 通常与 Engine defaultHost 一致-->
      <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>

  配置好之后,重启 Tomcat ,你就会发现使用 80 或 8080 都能访问同一应用了。例如 http://xxxx/myapp/indexhttp://xxxx:8080/myapp/index 都能访问。

  • 配置多个虚拟主机(即通过不同 ip 或 域名 访问不同的应用)

  这个跟上面的不同端口访问不同应用不一样,这里是同一个端口,但是通过不同的 ip (如果可以设置多个的话)或者不同的域名来访问不同的应用。

  下面是配置图示:

输入图片说明   也就是在 Engine 下面猛加 Host 配置。要注意,不同的主机对应的目录应该是不同的,弄到同一个目录就没意思了。

  下面是配置示例:

<?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">

    <!-- 配置使用 8080 端口访问 -->
    <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

    <!-- Define an AJP 1.3 Connector on port 8009
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
     -->

    <!-- Engine 的 defaultHost 是默认访问,而 Host 中并不需要一定存在这个默认的虚拟主机  -->
    <Engine name="Catalina" defaultHost="localhost">

      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <!-- www.me.com 的虚拟主机 -->
      <Host name="www.me.com"  appBase="d:\webapp\www.me.com\webapps" workDir="d:\webapp\www.me.com\works" unpackWARs="true" autoDeploy="true">

        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="me.com_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>

      <!-- www.you.com 的虚拟主机 -->
      <Host name="www.you.com"  appBase="d:\webapp\www.you.com\webapps" workDir="d:\webapp\www.you.com\works" unpackWARs="true" autoDeploy="true">

        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="you.com_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>
    </Engine>
  </Service>
</Server>

  要留意的是,我这个示例“故意”没有配置一个 defaultHost,这是允许的。例子中,为不同的“域名”定义不同的应用目录和工作目录,不同域名目录之间是互不干涉的,也就是说使用“www.me.com”的域名是无法访问“www.you.com”下的应用,这也是虚拟主机的目的。

  • 还有更复杂的吗?

  可以有更复杂的配置吗?试一试下面的配置图:

输入图片说明

0x10 结束语

  作为一个 Web 服务 + Servlet 容器服务器,Tomcat 本身已经提供了足够用的功能。虽然从 Web 服务器的角度来看,Tomcat 因为不是主业而偏弱,不过我们仍然能够通过其他途径来弥补其不足。一方面,众所周知 Tomcat 可以跟 Apache 整合变强;但另一方面,Tomcat 也提供足够灵活的配置与开发模式,让专业人士添加更多的功能。例如,通过 IP 识别限制访问的客户端;请求过滤等等。不过,这些并不是本篇文章所叙述的内容,有机会另起篇幅来描述。

转载于:https://my.oschina.net/delphixp/blog/509780

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值