Tomcat 虚拟主机配置

Virtual Host Configuration

概述

虚拟主机允许单个Tomcat实例托管多个域名和网站。本文介绍Tomcat虚拟主机的配置方法、管理技巧和最佳实践。

1. 虚拟主机基础配置

1.1 单域名虚拟主机

<!-- server.xml - 基础虚拟主机配置 -->
<Engine name="Catalina" defaultHost="www.example.com">

  <Host name="www.example.com" 
        appBase="webapps"
        unpackWARs="true" 
        autoDeploy="true">

    <!-- 域名别名 -->
    <Alias>example.com</Alias>

    <!-- 访问日志 -->
    <Valve className="org.apache.catalina.valves.AccessLogValve" 
           directory="logs"
           prefix="www_access_log" 
           suffix=".txt"
           pattern="%h %l %u %t &quot;%r&quot; %s %b" />
  </Host>
</Engine>

1.2 多域名虚拟主机

<Engine name="Catalina" defaultHost="www.example.com">

  <!-- 主网站 -->
  <Host name="www.example.com" appBase="/opt/webapps/main">
    <Alias>example.com</Alias>
    <Context path="" docBase="main.war" />
  </Host>

  <!-- API服务 -->
  <Host name="api.example.com" appBase="/opt/webapps/api">
    <Context path="" docBase="api.war">
      <Resource name="jdbc/ApiDB" 
                auth="Container"
                type="javax.sql.DataSource"
                driverClassName="com.mysql.cj.jdbc.Driver"
                url="jdbc:mysql://db.example.com:3306/apidb"
                username="apiuser"
                password="apipass"
                maxTotal="50" />
    </Context>
  </Host>

  <!-- 管理后台 -->
  <Host name="admin.example.com" appBase="/opt/webapps/admin">
    <!-- IP访问限制 -->
    <Valve className="org.apache.catalina.valves.RemoteAddrValve"
           allow="192\.168\.1\..*|127\.0\.0\.1" />
    <Context path="" docBase="admin.war" />
  </Host>
</Engine>

2. SSL虚拟主机配置

2.1 多域名SSL配置

<Connector port="8443" 
           protocol="org.apache.coyote.http11.Http11NioProtocol"
           SSLEnabled="true">

  <!-- 主域名SSL -->
  <SSLHostConfig hostName="www.example.com">
    <Certificate certificateKeystoreFile="conf/www-keystore.jks"
                 certificateKeystorePassword="www123"
                 type="RSA" />
  </SSLHostConfig>

  <!-- API域名SSL -->
  <SSLHostConfig hostName="api.example.com">
    <Certificate certificateKeystoreFile="conf/api-keystore.jks"
                 certificateKeystorePassword="api123"
                 type="RSA" />
  </SSLHostConfig>
</Connector>

3. 虚拟主机安全配置

3.1 访问控制

<Host name="secure.example.com" appBase="/opt/webapps/secure">

  <!-- IP访问控制 -->
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="192\.168\.1\..*"
         deny=".*" />

  <!-- 安全头设置 -->
  <Valve className="org.apache.catalina.valves.HttpHeaderSecurityFilter"
         hstsEnabled="true"
         hstsMaxAgeSeconds="31536000"
         antiClickJackingEnabled="true"
         blockContentTypeSniffingEnabled="true" />

  <Context path="" docBase="secure.war">
    <!-- 安全会话配置 -->
    <Manager className="org.apache.catalina.session.PersistentManager"
             maxActiveSession="100">
      <Store className="org.apache.catalina.session.FileStore"
             directory="/opt/secure/sessions" />
    </Manager>
  </Context>
</Host>

3.2 自定义访问控制Valve

// CustomAccessControlValve.java
package com.example.valve;

import org.apache.catalina.valves.ValveBase;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;

public class CustomAccessControlValve extends ValveBase {

    private String allowedCountries = "";
    private String businessHours = "09:00-18:00";

    @Override
    public void invoke(Request request, Response response) 
            throws IOException, ServletException {

        // 检查地理位置
        if (!isCountryAllowed(request)) {
            response.sendError(403, "Access denied for your country");
            return;
        }

        // 检查营业时间
        if (!isBusinessHours()) {
            response.sendError(503, "Service unavailable");
            return;
        }

        getNext().invoke(request, response);
    }

    // 实现检查方法...
}

4. 资源管理与监控

4.1 独立资源配置

<Host name="shop.example.com" appBase="/opt/webapps/shop">
  <Context path="" docBase="shop.war">

    <!-- 独立数据源 -->
    <Resource name="jdbc/ShopDB" 
              auth="Container"
              type="javax.sql.DataSource"
              driverClassName="com.mysql.cj.jdbc.Driver"
              url="jdbc:mysql://shop-db.example.com:3306/shopdb"
              username="shopuser"
              password="shoppass"
              maxTotal="100"
              maxIdle="50"
              validationQuery="SELECT 1" />

    <!-- 应用参数 -->
    <Parameter name="shop.payment.gateway" value="stripe" />
    <Parameter name="shop.currency.default" value="USD" />

    <!-- 环境变量 -->
    <Environment name="shop.environment" 
                 value="production" 
                 type="java.lang.String" />
  </Context>
</Host>

4.2 虚拟主机监控

// VirtualHostMonitor.java
package com.example.monitor;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;

public class VirtualHostMonitor {

    private MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

    public void monitorVirtualHosts() throws Exception {
        Set<ObjectName> hosts = mbs.queryNames(
            new ObjectName("Catalina:type=Host,*"), null
        );

        for (ObjectName host : hosts) {
            String hostName = host.getKeyProperty("host");
            String appBase = (String) mbs.getAttribute(host, "appBase");
            Boolean autoDeploy = (Boolean) mbs.getAttribute(host, "autoDeploy");

            System.out.println("虚拟主机: " + hostName);
            System.out.println("  应用目录: " + appBase);
            System.out.println("  自动部署: " + autoDeploy);
        }
    }
}

5. 动态虚拟主机管理

5.1 管理脚本

#!/bin/bash
# vhost-manager.sh

CATALINA_HOME="/opt/tomcat9"
SERVER_XML="$CATALINA_HOME/conf/server.xml"
VHOST_DIR="/opt/webapps"

create_vhost() {
    local hostname=$1
    local appbase=$2

    # 创建应用目录
    mkdir -p "$VHOST_DIR/$appbase"

    # 备份配置
    cp "$SERVER_XML" "$SERVER_XML.backup"

    # 添加虚拟主机配置
    echo "虚拟主机 $hostname 已创建"
}

remove_vhost() {
    local hostname=$1

    # 移除配置
    sed -i "/<Host name=\"$hostname\"/,/<\/Host>/d" "$SERVER_XML"
    echo "虚拟主机 $hostname 已移除"
}

list_vhosts() {
    echo "当前虚拟主机列表:"
    grep -o 'name="[^"]*"' "$SERVER_XML" | cut -d'"' -f2
}

case "$1" in
    "create") create_vhost "$2" "$3" ;;
    "remove") remove_vhost "$2" ;;
    "list") list_vhosts ;;
    *) echo "用法: $0 {create|remove|list}" ;;
esac

5.2 动态主机管理器

// DynamicHostManager.java
package com.example.manager;

import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.startup.HostConfig;

public class DynamicHostManager {

    private Engine engine;

    public void addVirtualHost(String hostName, String appBase) {
        try {
            StandardHost host = new StandardHost();
            host.setName(hostName);
            host.setAppBase(appBase);
            host.setUnpackWARs(true);
            host.setAutoDeploy(true);

            HostConfig hostConfig = new HostConfig();
            host.addLifecycleListener(hostConfig);

            engine.addChild(host);
            host.start();

            System.out.println("虚拟主机已添加: " + hostName);
        } catch (Exception e) {
            System.err.println("添加失败: " + e.getMessage());
        }
    }

    public void removeVirtualHost(String hostName) {
        try {
            Host host = (Host) engine.findChild(hostName);
            if (host != null) {
                host.stop();
                engine.removeChild(host);
                System.out.println("虚拟主机已移除: " + hostName);
            }
        } catch (Exception e) {
            System.err.println("移除失败: " + e.getMessage());
        }
    }
}

6. 性能优化配置

6.1 高性能虚拟主机

<Host name="high-perf.example.com" 
      appBase="/opt/webapps/hperf"
      startStopThreads="4"
      deployOnStartup="false"
      autoDeploy="false">

  <!-- 性能监控 -->
  <Valve className="org.apache.catalina.valves.StuckThreadDetectionValve"
         threshold="60" />

  <!-- 压缩优化 -->
  <Context path="" docBase="app.war">
    <Resources allowLinking="true"
               cacheMaxSize="51200"
               cacheTtl="5000"
               cacheObjectMaxSize="512" />
  </Context>
</Host>

6.2 负载测试脚本

#!/bin/bash
# vhost-load-test.sh

VHOST_URLS=(
    "http://www.example.com"
    "http://api.example.com/health"
    "http://admin.example.com/status"
)

for url in "${VHOST_URLS[@]}"; do
    echo "测试: $url"
    ab -n 1000 -c 10 "$url" | grep -E "(Requests per second|Time per request)"
    echo "---"
done

小结

通过本文学习,你应该掌握:

  1. 基础和高级虚拟主机配置方法
  2. SSL多域名证书配置
  3. 虚拟主机安全控制技术
  4. 独立资源配置和管理
  5. 动态虚拟主机管理技术
  6. 性能监控和优化方法

下一篇文章将详细介绍Tomcat安全配置与防护。

powered by Gitbook© 2025 编外计划 | 最后修改: 2025-08-29 15:40:15

results matching ""

    No results matching ""