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 "%r" %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
小结
通过本文学习,你应该掌握:
- 基础和高级虚拟主机配置方法
- SSL多域名证书配置
- 虚拟主机安全控制技术
- 独立资源配置和管理
- 动态虚拟主机管理技术
- 性能监控和优化方法
下一篇文章将详细介绍Tomcat安全配置与防护。