常见问题
本文档收集了 ZHub 使用过程中的常见问题和解答。
基础问题
Q: ZHub 是什么?
A: ZHub 是一个高性能的事件发布订阅服务组件,支持发布-订阅、广播消息、延时消息、RPC调用、分布式定时调度、分布式锁等功能。运行包仅有1M+,初始启动内存10M-。
Q: ZHub 支持哪些编程语言?
A: 目前主要支持:
- Java: 提供完整的客户端 SDK
- Go: 服务端使用 Go 语言开发
- 其他语言: 可以通过 HTTP API 接入
Q: ZHub 的性能如何?
A: ZHub 具有以下性能特点:
- 运行包仅 1M+
- 初始启动内存 10M-
- 支持高并发消息处理
- 低延迟消息传递
安装和配置
Q: 如何安装 ZHub?
A: 安装步骤:
- 下载
zhub.zip
发布包 - 解压到目标目录
- 配置
app.ini
文件 - 运行
./zhub.sh
(Linux)或./zhub.exe
(Windows)
Q: 如何配置 ZHub?
A: 主要配置文件是 app.ini
:
[service]
watch=0.0.0.0:711 # 管理端口
addr=0.0.0.0:1216 # 服务端口
auth=0 # 是否开启认证
[data]
dir=./data # 数据目录
[log]
handlers=console # 日志处理器
level=debug # 日志级别
Q: 如何开启权限验证?
A: 在 app.ini
中设置 auth=1
,并配置 auth.yml
文件:
users:
- id: 1
username: "client-001"
password: "password123"
status: "active"
reads: ["*"]
writes: ["*"]
客户端使用
Q: 如何创建客户端连接?
A: Java 客户端连接:
// 基础连接
ZHubClient zhub = new ZHubClient("127.0.0.1:1216", "group1", "app1");
// 带认证连接
ZHubClient zhub = new ZHubClient("127.0.0.1:1216", "group1", "app1", "token");
Q: 为什么需要唯一的 appid?
A: appid 用于标识客户端实例,特别是在 RPC 调用中:
- RPC 消息回复地址使用 appid 标识
- 多个客户端使用相同 appid 会导致 RPC 消息回复找不到目标
- 建议使用有意义的命名:
project-module-001
Q: 如何发布和订阅消息?
A: 基础用法:
// 订阅消息
zhub.subscribe("topic", message -> {
System.out.println("收到消息: " + message);
});
// 发布消息
zhub.publish("topic", "Hello ZHub!");
功能使用
Q: 如何实现 RPC 调用?
A: RPC 使用示例:
// 服务端
zhub.rpcSubscribe("user.getInfo", IType.STRING, request -> {
String userId = request.getValue();
return request.render("用户信息: " + userId);
});
// 客户端
RpcResult<String> result = zhub.rpc("user.getInfo", "user123", IType.STRING);
System.out.println("结果: " + result.getResult());
Q: 如何实现分布式锁?
A: 分布式锁使用:
// 阻塞式获取锁
Lock lock = zhub.lock("resource-key", 30);
try {
if (lock.success()) {
// 执行业务逻辑
}
} finally {
lock.unLock();
}
// 非阻塞式获取锁
Lock lock = zhub.tryLock("resource-key", 30);
if (lock.success()) {
try {
// 执行业务逻辑
} finally {
lock.unLock();
}
}
Q: 如何实现定时任务?
A: 定时任务使用:
// 订阅定时任务
zhub.timer("T:A", () -> {
System.out.println("定时任务执行");
});
需要在数据库中配置定时任务:
INSERT INTO tasktimer (timerid, name, expr, single, remark, status) VALUES
('T1', 'T:A', '*/5 * * * * ?', 1, '每5秒执行一次', 10);
权限和安全
Q: 如何配置用户权限?
A: 在 auth.yml
中配置用户权限:
users:
- id: 1
username: "user-service"
password: "password123"
status: "active"
groups: ["user-service"]
reads: ["user.*"] # 读取权限
writes: ["user.*"] # 写入权限
Q: 如何实现细粒度权限控制?
A: 使用正则表达式控制 Topic 权限:
users:
- id: 1
username: "client-001"
reads: ["user.*", "order.*"] # 可读取 user.* 和 order.* 主题
writes: ["user.*"] # 只能写入 user.* 主题
Q: Token 过期了怎么办?
A: 解决方案:
延长 Token 过期时间:
tokens:
- id: 1
token: "token-12345"
expiration: "2030-12-31T23:59:59Z" # 设置较长时间重新加载权限配置:
curl http://127.0.0.1:711/auth/reload
仅在开发环境关闭权限验证:
[service]
auth=0 # 仅适用于完全隔离的开发测试环境安全提醒- 生产环境强烈建议开启权限验证,即使在内网环境
- 关闭权限验证存在安全风险,仅适用于开发测试环境
数据库配置
Q: 支持哪些数据库?
A: ZHub 支持以下数据库:
- MySQL: 默认支持
- PostgreSQL: 支持
Q: 如何配置数据库连接?
A: 在 app.ini
中配置:
[ztimer]
db.addr=127.0.0.1:3306
db.user=root
db.password=123456
db.database=zhub
db.schema=public # PostgreSQL 模式名
db.type=mysql # mysql|postgres
Q: 如何初始化数据库表?
A: MySQL 初始化:
CREATE TABLE `tasktimer` (
`timerid` varchar(64) NOT NULL DEFAULT '' PRIMARY KEY,
`name` varchar(32) NOT NULL DEFAULT '',
`expr` varchar(32) NOT NULL DEFAULT '',
`single` int NOT NULL DEFAULT '1',
`remark` varchar(128) NOT NULL DEFAULT '',
`status` smallint NOT NULL DEFAULT '10'
);
PostgreSQL 初始化:
CREATE TABLE tasktimer (
timerid varchar(64) NOT NULL DEFAULT '' PRIMARY KEY,
name varchar(32) NOT NULL DEFAULT '',
expr varchar(32) NOT NULL DEFAULT '',
single int NOT NULL DEFAULT 1,
remark varchar(128) NOT NULL DEFAULT '',
status smallint NOT NULL DEFAULT 10
);
性能优化
Q: 如何提高消息处理性能?
A: 性能优化建议:
异步处理消息:
zhub.subscribe("topic", message -> {
CompletableFuture.runAsync(() -> {
processMessage(message);
});
});批量处理消息:
private final List<String> messageBatch = new ArrayList<>();
zhub.subscribe("topic", message -> {
synchronized (messageBatch) {
messageBatch.add(message);
if (messageBatch.size() >= 100) {
processBatch(new ArrayList<>(messageBatch));
messageBatch.clear();
}
}
});使用连接池:
// 复用连接,避免频繁创建
private static final ZHubClient zhub = new ZHubClient(...);
Q: 如何监控性能?
A: 监控方法:
使用管理接口:
curl http://127.0.0.1:711/_/info
客户端监控:
public class PerformanceMonitor {
private final AtomicLong messageCount = new AtomicLong(0);
public void monitorMessage(String message) {
messageCount.incrementAndGet();
// 处理消息
}
}
故障排除
Q: 客户端连接失败怎么办?
A: 排查步骤:
检查服务是否运行:
ps aux | grep zhub
检查端口是否监听:
netstat -tulpn | grep :1216
检查网络连接:
telnet 127.0.0.1 1216
检查防火墙设置:
ufw status
iptables -L
Q: 消息丢失怎么办?
A: 消息丢失排查:
- 检查网络连接:确保网络稳定
- 检查客户端处理:确保消息处理逻辑正确
- 检查服务端资源:确保服务端有足够资源
- 使用管理接口清理内存:
curl http://127.0.0.1:711/_/cleanup
Q: RPC 调用超时怎么办?
A: RPC 超时解决:
增加超时时间:
RpcResult<String> result = zhub.rpc("rpc-topic", "data", IType.STRING, 30000);
使用异步 RPC:
CompletableFuture<RpcResult<String>> future =
zhub.rpcAsync("rpc-topic", "data", IType.STRING);检查服务端处理时间:优化服务端处理逻辑
Q: 定时任务不执行怎么办?
A: 定时任务排查:
检查数据库连接:
curl http://127.0.0.1:711/_/info
重新加载定时任务:
curl http://127.0.0.1:711/timer/reload
检查任务状态:
SELECT * FROM tasktimer WHERE status = 10;
部署问题
Q: 如何部署到生产环境?
A: 生产环境部署建议:
使用 Docker 部署:
docker run -d -p 711:711 -p 1216:1216 --name zhub zhub:latest
配置数据持久化:
docker run -d -v /host/data:/opt/zhub/data zhub:latest
配置环境变量:
docker run -d -e ZHUB_AUTH=1 zhub:latest
版本升级
Q: 如何升级 ZHub?
A: 升级步骤:
- 备份数据:备份数据目录和配置文件
- 停止服务:停止当前 ZHub 服务
- 替换文件:替换为新版本文件
- 启动服务:启动新版本服务
- 验证功能:验证各项功能正常
Q: 升级后配置不兼容怎么办?
A: 配置兼容性处理:
- 检查配置文件:对比新旧配置文件
- 更新配置格式:按照新版本要求更新配置
- 测试功能:测试各项功能是否正常
- 回滚准备:准备回滚方案
性能优化
Q: 如何优化 ZHub 性能?
A: 性能优化建议:
异步处理:避免阻塞消息处理
zhub.subscribe("topic", message -> {
CompletableFuture.runAsync(() -> {
processMessage(message);
});
});错误处理:添加异常捕获
zhub.subscribe("topic", message -> {
try {
processMessage(message);
} catch (Exception e) {
logger.error("消息处理失败", e);
}
});内存管理:定期清理内存
curl http://127.0.0.1:711/_/cleanup
Q: 如何监控 ZHub 状态?
A: 监控方法:
- 服务状态:
curl http://127.0.0.1:711/_/info
- 内存使用:
free -h
- 网络连接:
netstat -tulpn | grep :1216
技术支持
Q: 如何获取技术支持?
A: 技术支持渠道:
- 查看文档:参考官方文档
- 查看日志:检查服务端和客户端日志
- 联系作者:
- 作者: 绝尘
- 微信: zhub_dev
- 邮箱: lxy208@126.com