Files
z-docs/docs/tutorial-extras/troubleshooting.md

422 lines
7.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
sidebar_position: 10
title: 故障排除
description: ZHub 常见问题和解决方案
---
# 故障排除
本文档提供了 ZHub 使用过程中常见问题的诊断和解决方案。
---
## 连接问题
### 1. 客户端连接失败
**症状**
- 客户端无法连接到 ZHub 服务
- 连接超时或连接被拒绝
**可能原因**
- 服务未启动
- 端口被占用
- 网络连接问题
- 防火墙阻止连接
**诊断步骤**
```bash
# 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
```
**解决方案**
```bash
# 启动服务
./zhub.sh
# 检查配置文件
cat app.ini
# 修改端口(如果冲突)
# 编辑 app.ini 文件
[service]
addr=0.0.0.0:1217 # 修改端口
watch=0.0.0.0:712 # 修改管理端口
```
### 2. 连接频繁断开
**症状**
- 客户端连接后频繁断开重连
- 日志中出现连接异常
**可能原因**
- 网络不稳定
- 服务端资源不足
- 客户端配置问题
**解决方案**
```java
// 客户端配置优化
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 格式错误
- 权限配置错误
**诊断步骤**
```bash
# 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
```
**解决方案**
```yaml
# 更新 auth.yml 中的 token 过期时间
tokens:
- id: 1
user_id: 1
token: "token-12345"
expiration: "2030-12-31T23:59:59Z" # 延长过期时间
status: "active"
```
### 2. Topic 权限不足
**症状**
- 无法订阅或发布特定 Topic
- 权限验证失败
**解决方案**
```yaml
# 在 auth.yml 中添加权限
users:
- id: 2
username: "client-001"
reads: ["user.*", "order.*"] # 添加读取权限
writes: ["user.*"] # 添加写入权限
```
---
## 消息问题
### 1. 消息丢失
**症状**
- 发送的消息未被接收
- 消息处理不完整
**可能原因**
- 网络问题
- 客户端处理异常
- 服务端资源不足
**诊断步骤**
```bash
# 1. 检查服务状态
curl http://127.0.0.1:711/_/info
# 2. 查看服务日志
tail -f zhub.log
# 3. 检查内存使用
curl http://127.0.0.1:711/_/cleanup
```
**解决方案**
```java
// 客户端消息处理优化
zhub.subscribe("topic-name", message -> {
try {
// 处理消息
processMessage(message);
} catch (Exception e) {
logger.error("消息处理失败", e);
// 记录失败消息,后续重试
}
});
```
---
## RPC 问题
### 1. RPC 调用超时
**症状**
- RPC 调用长时间无响应
- 超时异常
**可能原因**
- 服务端处理时间过长
- 网络延迟
- 服务端异常
**解决方案**
```java
// 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 调用返回错误码
- 服务端未响应
**诊断步骤**
```java
// 检查 RPC 结果
RpcResult<String> result = zhub.rpc("rpc-topic", "data", IType.STRING);
if (result.getRetcode() != 0) {
logger.error("RPC 调用失败: code={}, msg={}",
result.getRetcode(), result.getRetmsg());
}
```
**解决方案**
```java
// 服务端 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. 内存使用过高
**症状**
- 服务端内存持续增长
- 系统响应变慢
**诊断步骤**
```bash
# 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
```
**解决方案**
```ini
# 优化 app.ini 配置
[log]
level=info # 降低日志级别
handlers=file # 使用文件日志
[data]
dir=./data # 确保数据目录存在
```
### 2. 消息处理缓慢
**症状**
- 消息处理延迟增加
- 系统吞吐量下降
**解决方案**
```java
// 使用异步处理
zhub.subscribe("topic-name", message -> {
CompletableFuture.runAsync(() -> {
processMessage(message);
});
});
```
---
## 定时任务问题
### 1. 定时任务不执行
**症状**
- 配置的定时任务未执行
- 任务状态异常
**诊断步骤**
```bash
# 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;"
```
**解决方案**
```sql
-- 检查定时任务配置
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. 定时任务重复执行
**症状**
- 同一个定时任务被多次执行
- 业务逻辑重复处理
**解决方案**
```sql
-- 确保单实例执行
UPDATE tasktimer SET single = 1 WHERE name = 'task-name';
```
---
## 分布式锁问题
### 1. 锁获取失败
**症状**
- 无法获取分布式锁
- 业务逻辑无法执行
**解决方案**
```java
// 优化锁获取逻辑
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. 死锁问题
**症状**
- 系统卡死
- 资源无法释放
**解决方案**
```java
// 避免死锁的最佳实践
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();
}
}
```
---
## 监控和诊断
### 基础监控
```bash
# 检查服务状态
curl http://127.0.0.1:711/_/info
# 查看服务日志
tail -f zhub.log
# 检查内存使用
free -h
```
---
## 联系支持
如果遇到无法解决的问题,请提供:
1. **错误日志**: 完整的错误信息
2. **配置信息**: app.ini 和 auth.yml 配置
3. **复现步骤**: 详细的问题复现步骤
更多技术支持信息请参考 [FAQ 文档](./faq.md)。