故障排除
本文档提供了 ZHub 使用过程中常见问题的诊断和解决方案。
连接问题
1. 客户端连接失败
症状:
- 客户端无法连接到 ZHub 服务
- 连接超时或连接被拒绝
可能原因:
- 服务未启动
- 端口被占用
- 网络连接问题
- 防火墙阻止连接
诊断步骤:
# 1. 检查服务是否运行
ps aux | grep zhub
# 2. 检查端口是否监听
netstat -tulpn | grep :1216
netstat -tulpn | grep :711
# 3. 测试端口连通性
telnet 127.0.0.1 1216
telnet 127.0.0.1 711
解决方案:
# 启动服务
./zhub.sh
# 检查配置文件
cat app.ini
# 修改端口(如果冲突)
# 编辑 app.ini 文件
[service]
addr=0.0.0.0:1217 # 修改端口
watch=0.0.0.0:712 # 修改管理端口
2. 连接频繁断开
症状:
- 客户端连接后频繁断开重连
- 日志中出现连接异常
可能原因:
- 网络不稳定
- 服务端资源不足
- 客户端配置问题
解决方案:
// 客户端配置优化
ZHubClient zhub = new ZHubClient(
"127.0.0.1:1216",
"groupid",
"appid",
"token"
);
// 重新创建客户端连接(使用正确的参数)
zhub = new ZHubClient("127.0.0.1:1216", "groupid", "appid", "token");
权限问题
1. 认证失败
症状:
- 客户端连接时提示认证失败
- 日志显示 "invalid or expired token"
可能原因:
- Token 过期
- Token 格式错误
- 权限配置错误
诊断步骤:
# 1. 检查权限配置
curl http://127.0.0.1:711/_/info
# 2. 检查 auth.yml 文件
cat auth.yml
# 3. 重新加载权限配置
curl http://127.0.0.1:711/auth/reload
解决方案:
# 更新 auth.yml 中的 token 过期时间
tokens:
- id: 1
user_id: 1
token: "token-12345"
expiration: "2030-12-31T23:59:59Z" # 延长过期时间
status: "active"
2. Topic 权限不足
症状:
- 无法订阅或发布特定 Topic
- 权限验证失败
解决方案:
# 在 auth.yml 中添加权限
users:
- id: 2
username: "client-001"
reads: ["user.*", "order.*"] # 添加读取权限
writes: ["user.*"] # 添加写入权限
消息问题
1. 消息丢失
症状:
- 发送的消息未被接收
- 消息处理不完整
可能原因:
- 网络问题
- 客户端处理异常
- 服务端资源不足
诊断步骤:
# 1. 检查服务状态
curl http://127.0.0.1:711/_/info
# 2. 查看服务日志
tail -f zhub.log
# 3. 检查内存使用
curl http://127.0.0.1:711/_/cleanup
解决方案:
// 客户端消息处理优化
zhub.subscribe("topic-name", message -> {
try {
// 处理消息
processMessage(message);
} catch (Exception e) {
logger.error("消息处理失败", e);
// 记录失败消息,后续重试
}
});
RPC 问题
1. RPC 调用超时
症状:
- RPC 调用长时间无响应
- 超时异常
可能原因:
- 服务端处理时间过长
- 网络延迟
- 服务端异常
解决方案:
// RPC 调用(基础版本)
RpcResult<String> result = zhub.rpc("rpc-topic", "data", IType.STRING);
if (result.getRetcode() == 0) {
System.out.println("RPC 调用成功: " + result.getResult());
} else {
System.err.println("RPC 调用失败: " + result.getRetmsg());
}
2. RPC 调用失败
症状:
- RPC 调用返回错误码
- 服务端未响应
诊断步骤:
// 检查 RPC 结果
RpcResult<String> result = zhub.rpc("rpc-topic", "data", IType.STRING);
if (result.getRetcode() != 0) {
logger.error("RPC 调用失败: code={}, msg={}",
result.getRetcode(), result.getRetmsg());
}
解决方案:
// 服务端 RPC 处理优化
zhub.rpcSubscribe("rpc-topic", IType.STRING, request -> {
try {
String data = request.getValue();
// 处理业务逻辑
String result = processData(data);
return request.render(result);
} catch (Exception e) {
logger.error("RPC 处理异常", e);
return request.retError("服务处理失败: " + e.getMessage());
}
});
性能问题
1. 内存使用过高
症状:
- 服务端内存持续增长
- 系统响应变慢
诊断步骤:
# 1. 检查内存使用
free -h
top -p $(pgrep zhub)
# 2. 查看服务状态
curl http://127.0.0.1:711/_/info
# 3. 清理内存
curl http://127.0.0.1:711/_/cleanup
解决方案:
# 优化 app.ini 配置
[log]
level=info # 降低日志级别
handlers=file # 使用文件日志
[data]
dir=./data # 确保数据目录存在
2. 消息处理缓慢
症状:
- 消息处理延迟增加
- 系统吞吐量下降
解决方案:
// 使用异步处理
zhub.subscribe("topic-name", message -> {
CompletableFuture.runAsync(() -> {
processMessage(message);
});
});
定时任务问题
1. 定时任务不执行
症状:
- 配置的定时任务未执行
- 任务状态异常
诊断步骤:
# 1. 检查数据库连接
curl http://127.0.0.1:711/_/info
# 2. 重新加载定时任务
curl http://127.0.0.1:711/timer/reload
# 3. 检查数据库配置
mysql -u root -p -e "SELECT * FROM zhub.tasktimer WHERE status = 10;"
解决方案:
-- 检查定时任务配置
SELECT timerid, name, expr, single, status FROM tasktimer;
-- 更新任务状态
UPDATE tasktimer SET status = 10 WHERE name = 'task-name';
-- 检查时间表达式格式
UPDATE tasktimer SET expr = '*/5 * * * * ?' WHERE name = 'task-name';
2. 定时任务重复执行
症状:
- 同一个定时任务被多次执行
- 业务逻辑重复处理
解决方案:
-- 确保单实例执行
UPDATE tasktimer SET single = 1 WHERE name = 'task-name';
分布式锁问题
1. 锁获取失败
症状:
- 无法获取分布式锁
- 业务逻辑无法执行
解决方案:
// 优化锁获取逻辑
public boolean processWithLock(String resourceKey) {
Lock lock = zhub.tryLock(resourceKey, 10); // 10秒超时
if (!lock.success()) {
logger.warn("获取锁失败,资源被占用: {}", resourceKey);
return false;
}
try {
// 执行业务逻辑
processResource(resourceKey);
return true;
} finally {
lock.unLock();
}
}
2. 死锁问题
症状:
- 系统卡死
- 资源无法释放
解决方案:
// 避免死锁的最佳实践
public void safeProcess() {
// 1. 避免嵌套锁
// 2. 设置合理的超时时间
// 3. 确保锁的释放
Lock lock1 = zhub.tryLock("resource1", 5);
if (!lock1.success()) return;
try {
Lock lock2 = zhub.tryLock("resource2", 5);
if (!lock2.success()) return;
try {
// 业务逻辑
} finally {
lock2.unLock();
}
} finally {
lock1.unLock();
}
}
监控和诊断
基础监控
# 检查服务状态
curl http://127.0.0.1:711/_/info
# 查看服务日志
tail -f zhub.log
# 检查内存使用
free -h
联系支持
如果遇到无法解决的问题,请提供:
- 错误日志: 完整的错误信息
- 配置信息: app.ini 和 auth.yml 配置
- 复现步骤: 详细的问题复现步骤
更多技术支持信息请参考 FAQ 文档。