多VHost连接管理
VHost 是 RabbitMQ 的逻辑隔离单元,不同 VHost 的交换机、队列、用户完全独立。
VHost 基础概念
每个 VHost 拥有独立的命名空间,资源名称可在不同 VHost 中重复使用。
Java
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
factory.setUsername("app_user");
factory.setPassword("app_pass");
// 指定 VHost
factory.setVirtualHost("/production");
Connection prodConnection = factory.newConnection();
// 另一个 VHost
factory.setVirtualHost("/staging");
Connection stageConnection = factory.newConnection();
VHost 隔离特性:
- 交换机和队列名称在不同 VHost 中可重复
- 用户权限按 VHost 授予
- 消息无法跨 VHost 路由
默认 VHost 为
/,创建用户时必须至少授予一个 VHost 的访问权限。
多 VHost 连接管理器
统一管理多个 VHost 连接,提供连接获取和关闭的集中入口。
Java
public class VHostConnectionManager implements AutoCloseable {
private final Map<String, Connection> connections = new ConcurrentHashMap<>();
private final ConnectionFactory factory;
public VHostConnectionManager(ConnectionFactory factory) {
this.factory = factory;
}
public Connection getConnection(String vHost) throws Exception {
return connections.computeIfAbsent(vHost, v -> {
try {
factory.setVirtualHost(v);
Connection conn = factory.newConnection();
conn.addShutdownListener(cause -> {
connections.remove(v);
System.err.println("VHost " + v + " 连接断开");
});
return conn;
} catch (Exception e) {
throw new RuntimeException("连接 VHost 失败: " + v, e);
}
});
}
public void closeAll() {
connections.forEach((vHost, conn) -> {
try {
conn.close();
System.out.println("关闭 VHost 连接: " + vHost);
} catch (Exception e) {
e.printStackTrace();
}
});
connections.clear();
}
@Override
public void close() {
closeAll();
}
}
使用示例:
Java
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setUsername("admin");
factory.setPassword("admin");
try (VHostConnectionManager manager = new VHostConnectionManager(factory)) {
Connection prodConn = manager.getConnection("/production");
Connection stageConn = manager.getConnection("/staging");
// 各 VHost 独立操作
Channel prodCh = prodConn.createChannel();
prodCh.queueDeclare("prod_queue", true, false, false, null);
Channel stageCh = stageConn.createChannel();
stageCh.queueDeclare("stage_queue", true, false, false, null);
}
VHost 权限控制
通过用户权限实现 VHost 级别的资源隔离。
Java
// 用户权限配置(rabbitmqctl 命令)
// rabbitmqctl set_permissions -p /production app_user ".*" ".*" ".*"
// rabbitmqctl set_permissions -p /staging app_user ".*" ".*" ".*"
// Java Client 使用不同用户连接不同 VHost
public Connection connectWithUser(String vHost, String user, String password) throws Exception {
factory.setVirtualHost(vHost);
factory.setUsername(user);
factory.setPassword(password);
return factory.newConnection();
}
权限粒度:
configure:创建/删除交换机、队列write:发布消息read:消费消息
建议按 VHost 分配独立用户,避免越权访问。
VHost 资源配额
通过策略限制 VHost 的资源使用上限。
Java
// 设置 VHost 队列数量限制(rabbitmqctl 命令)
// rabbitmqctl set_policy -p /production max_queues ".*" '{"max-length-queue": 100}'
// Java Client 声明队列时检查配额
Channel channel = connection.createChannel();
try {
channel.queueDeclare("new_queue", true, false, false, null);
} catch (IOException e) {
if (e.getMessage().contains("resource error")) {
System.err.println("VHost 资源配额已满");
}
}
常见配额限制:
| 配额类型 | 策略键 | 说明 |
|---|---|---|
| 队列数量 | max-length-queue | VHost 最大队列数 |
| 消息数量 | max-length | 单队列最大消息数 |
| 内存占用 | max-memory | VHost 最大内存占用 |
注意事项
- 每个 VHost 需要独立连接,不能通过同一连接切换 VHost
- 多 VHost 连接需独立管理生命周期,避免连接泄漏
- 用户权限按 VHost 分配,确保最小权限原则
- VHost 名称必须以
/开头,如/production
要点总结
- VHost 是逻辑隔离单元,不同 VHost 资源完全独立
- 每个 VHost 需使用独立连接,通过
setVirtualHost()指定 - 使用连接管理器统一管理多 VHost 连接的生命周期
- 通过用户权限和策略实现 VHost 级别的资源隔离与配额控制
- VHost 名称必须以
/开头,权限按 VHost 独立授予
📝 发现内容有误?点击此处直接编辑