添加:ZHub 管理接口文档和客户端使用指南
This commit is contained in:
@@ -3,6 +3,6 @@
|
||||
"position": 3,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "分布式系统常用组件"
|
||||
"description": "ZHub 高级功能配置,包含权限管理、性能优化、安全实践等"
|
||||
}
|
||||
}
|
||||
|
||||
148
docs/tutorial-extras/api-reference.md
Normal file
148
docs/tutorial-extras/api-reference.md
Normal file
@@ -0,0 +1,148 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
title: API 参考
|
||||
description: ZHub 完整 API 参考文档
|
||||
---
|
||||
|
||||
# API 参考
|
||||
|
||||
ZHub 客户端和管理接口的完整参考。
|
||||
|
||||
## 客户端 API
|
||||
|
||||
### 创建连接
|
||||
|
||||
```java
|
||||
// 基础连接
|
||||
ZHubClient zhub = new ZHubClient("127.0.0.1:1216", "group1", "app1");
|
||||
|
||||
// 带认证连接
|
||||
ZHubClient zhub = new ZHubClient("127.0.0.1:1216", "group1", "app1", "token123");
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `addr`: 服务地址 `IP:端口`
|
||||
- `groupId`: 组名
|
||||
- `appId`: 应用ID(唯一)
|
||||
- `auth`: 认证码(可选)
|
||||
|
||||
### 消息操作
|
||||
|
||||
#### 发布订阅
|
||||
```java
|
||||
// 发布消息
|
||||
zhub.publish("user.login", "用户登录");
|
||||
|
||||
// 订阅消息
|
||||
zhub.subscribe("user.login", message -> {
|
||||
System.out.println("收到: " + message);
|
||||
});
|
||||
```
|
||||
|
||||
#### 广播消息
|
||||
```java
|
||||
// 广播给所有客户端
|
||||
zhub.broadcast("topic-abc", "hello!");
|
||||
```
|
||||
|
||||
#### 延时消息
|
||||
```java
|
||||
// 30秒后发送
|
||||
zhub.delay("order.timeout", "订单超时", 30000);
|
||||
```
|
||||
|
||||
### RPC 调用
|
||||
|
||||
#### 提供服务
|
||||
```java
|
||||
// 提供 RPC 服务
|
||||
zhub.rpcSubscribe("user.getInfo", IType.STRING, request -> {
|
||||
String userId = request.getValue();
|
||||
return request.render("用户信息: " + userId);
|
||||
});
|
||||
```
|
||||
|
||||
#### 调用服务
|
||||
```java
|
||||
// 调用 RPC 服务
|
||||
RpcResult<String> result = zhub.rpc("user.getInfo", "user123", IType.STRING);
|
||||
if (result.isSuccess()) {
|
||||
System.out.println("结果: " + result.getResult());
|
||||
}
|
||||
```
|
||||
|
||||
### 定时任务
|
||||
|
||||
```java
|
||||
// 订阅定时任务
|
||||
zhub.timer("T:A", () -> {
|
||||
System.out.println("定时执行");
|
||||
});
|
||||
```
|
||||
|
||||
### 分布式锁
|
||||
|
||||
```java
|
||||
// 获取锁
|
||||
Lock lock = zhub.tryLock("resource-key", 30);
|
||||
if (lock.success()) {
|
||||
try {
|
||||
// 执行业务逻辑
|
||||
} finally {
|
||||
lock.unLock();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 管理接口
|
||||
|
||||
### 查看服务状态
|
||||
```bash
|
||||
# 查看服务信息
|
||||
curl http://127.0.0.1:711/_/info
|
||||
|
||||
# 查看版本
|
||||
curl http://127.0.0.1:711/_/version
|
||||
```
|
||||
|
||||
### 管理操作
|
||||
```bash
|
||||
# 清理内存
|
||||
curl http://127.0.0.1:711/_/cleanup
|
||||
|
||||
# 重载定时任务
|
||||
curl http://127.0.0.1:711/timer/reload
|
||||
|
||||
# 重载权限配置
|
||||
curl http://127.0.0.1:711/auth/reload
|
||||
```
|
||||
|
||||
### 发送消息
|
||||
```bash
|
||||
# 发布消息
|
||||
curl -X POST http://127.0.0.1:711/message/send \
|
||||
-d "type=publish&name=user.login&value=用户登录"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 常用类型
|
||||
|
||||
### IType 类型
|
||||
```java
|
||||
IType.STRING // 字符串
|
||||
IType.INT // 整数
|
||||
IType.LONG // 长整数
|
||||
IType.DOUBLE // 浮点数
|
||||
IType.MAP // 键值对
|
||||
```
|
||||
|
||||
### 错误码
|
||||
| 错误码 | 说明 |
|
||||
|--------|------|
|
||||
| 0 | 成功 |
|
||||
| 501 | 请求失败 |
|
||||
| 505 | 请求超时 |
|
||||
| 401 | 认证失败 |
|
||||
191
docs/tutorial-extras/auth-config.md
Normal file
191
docs/tutorial-extras/auth-config.md
Normal file
@@ -0,0 +1,191 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
title: 权限配置
|
||||
description: ZHub 权限配置和认证管理
|
||||
---
|
||||
|
||||
# ZHub 权限配置
|
||||
|
||||
## 配置方式
|
||||
|
||||
- **app.ini**: 开启/关闭权限验证
|
||||
- **auth.yml**: 详细权限配置
|
||||
|
||||
## 权限控制
|
||||
|
||||
- **连接认证**:通过Token验证客户端身份
|
||||
- **主题权限**:控制对特定主题的读写权限
|
||||
- **操作类型**:区分读取(r)和写入(w)操作
|
||||
|
||||
## 基础配置
|
||||
|
||||
**开启权限验证**:
|
||||
```ini
|
||||
[service]
|
||||
auth=1 # 开启连接授权
|
||||
```
|
||||
|
||||
**关闭权限验证**:
|
||||
```ini
|
||||
[service]
|
||||
auth=0 # 关闭连接授权(内网环境)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## auth.yml 配置文件
|
||||
|
||||
### 配置文件结构
|
||||
|
||||
```yaml
|
||||
# auth.yml 权限配置文件
|
||||
users:
|
||||
- id: 1
|
||||
username: "admin"
|
||||
password: "admin123"
|
||||
status: "active"
|
||||
groups: ["admin"]
|
||||
reads: ["*"] # 读取权限
|
||||
writes: ["*"] # 写入权限
|
||||
|
||||
- id: 2
|
||||
username: "client-001"
|
||||
password: "client123"
|
||||
status: "active"
|
||||
groups: ["client"]
|
||||
reads: ["user.*", "order.*"] # 可读取 user.* 和 order.* 主题
|
||||
writes: ["user.*"] # 可写入 user.* 主题
|
||||
|
||||
groups:
|
||||
- name: "admin"
|
||||
description: "管理员组"
|
||||
reads: ["*"]
|
||||
writes: ["*"]
|
||||
|
||||
- name: "client"
|
||||
description: "客户端组"
|
||||
reads: ["user.*", "order.*"]
|
||||
writes: ["user.*"]
|
||||
```
|
||||
|
||||
### 配置说明
|
||||
|
||||
#### 用户配置 (users)
|
||||
- **id**: 用户唯一标识
|
||||
- **username**: 用户名
|
||||
- **password**: 密码
|
||||
- **status**: 用户状态 (active/inactive)
|
||||
- **groups**: 所属用户组列表
|
||||
- **reads**: 读取权限列表,支持正则表达式
|
||||
- **writes**: 写入权限列表,支持正则表达式
|
||||
|
||||
#### 用户组配置 (groups)
|
||||
- **name**: 组名
|
||||
- **description**: 组描述
|
||||
- **reads**: 组读取权限
|
||||
- **writes**: 组写入权限
|
||||
|
||||
---
|
||||
|
||||
## 客户端连接配置
|
||||
|
||||
### Java 项目
|
||||
```java
|
||||
// 带认证的连接
|
||||
ZHubClient zhub = new ZHubClient(
|
||||
"127.0.0.1:1216", // 服务地址
|
||||
"groupid-x", // 消费者组
|
||||
"appid-unique-001", // 应用ID(必须唯一)
|
||||
"token-12345" // 认证令牌
|
||||
);
|
||||
```
|
||||
|
||||
### SpringBoot 项目
|
||||
```yaml
|
||||
# application.yml
|
||||
zhub:
|
||||
addr: 127.0.0.1:1216
|
||||
groupid: groupid-x
|
||||
appid: appid-unique-002
|
||||
auth: token-12345
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 重要注意事项
|
||||
|
||||
### AppID 唯一性
|
||||
:::warning 关键要求
|
||||
- **每个客户端必须使用不同的 appid**
|
||||
- RPC 消息回复使用 appid 标识
|
||||
- 相同 appid 会导致 RPC 消息回复失败
|
||||
:::
|
||||
|
||||
### 权限管理
|
||||
```bash
|
||||
# 重新加载权限配置
|
||||
curl http://127.0.0.1:711/auth/reload
|
||||
```
|
||||
|
||||
### 内网环境
|
||||
```ini
|
||||
# app.ini - 关闭权限验证(仅内网环境)
|
||||
[service]
|
||||
auth=0
|
||||
```
|
||||
|
||||
### 权限配置示例
|
||||
```yaml
|
||||
users:
|
||||
- id: 1
|
||||
username: "user-service"
|
||||
reads: ["user.*"] # 匹配 user.login, user.profile 等
|
||||
writes: ["user.*"]
|
||||
|
||||
- id: 2
|
||||
username: "order-service"
|
||||
reads: ["order.*", "user.basic.*"]
|
||||
writes: ["order.*"]
|
||||
|
||||
- id: 3
|
||||
username: "admin-service"
|
||||
reads: ["*"] # 匹配所有主题
|
||||
writes: ["*"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 管理接口
|
||||
|
||||
```bash
|
||||
# 重新加载权限配置
|
||||
curl http://127.0.0.1:711/auth/reload
|
||||
|
||||
# 查看服务状态
|
||||
curl http://127.0.0.1:711/_/info
|
||||
```
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### Topic 命名规范
|
||||
```
|
||||
team.service.action
|
||||
# 示例:
|
||||
user.profile.update
|
||||
order.payment.process
|
||||
```
|
||||
|
||||
### 权限最小化
|
||||
```yaml
|
||||
# 只给必要的权限
|
||||
- id: 1
|
||||
username: "order-service"
|
||||
reads: ["order.*", "user.basic.*"]
|
||||
writes: ["order.*"]
|
||||
```
|
||||
|
||||
### 环境配置
|
||||
- **开发环境**: 可关闭权限验证 (`auth=0`)
|
||||
- **生产环境**: 必须开启权限验证 (`auth=1`)
|
||||
- 使用强随机 Token
|
||||
- 定期轮换 Token
|
||||
169
docs/tutorial-extras/docker-deployment.md
Normal file
169
docs/tutorial-extras/docker-deployment.md
Normal file
@@ -0,0 +1,169 @@
|
||||
---
|
||||
sidebar_position: 6
|
||||
title: Docker 部署
|
||||
description: ZHub Docker 容器化部署指南
|
||||
---
|
||||
|
||||
# Docker 部署
|
||||
|
||||
ZHub 支持 Docker 容器化部署,提供简化的构建和运行方式。
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 准备文件
|
||||
|
||||
从 [https://zhub.dev/release/latest/](https://zhub.dev/release/latest/) 下载软件包并解压:
|
||||
|
||||
```bash
|
||||
# 解压后目录结构
|
||||
zhub/
|
||||
├── zhub.sh # 可执行文件
|
||||
├── app.ini # 配置文件
|
||||
└── auth.yml # 权限配置文件(可选)
|
||||
```
|
||||
|
||||
### 2. 构建镜像
|
||||
|
||||
创建 `Dockerfile` 文件:
|
||||
|
||||
```dockerfile
|
||||
# 使用Alpine Linux作为基础镜像
|
||||
FROM alpine:latest
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /opt/zhub
|
||||
|
||||
# 复制解压后的文件
|
||||
COPY zhub.sh ./
|
||||
COPY app.ini ./
|
||||
COPY auth.yml ./
|
||||
|
||||
# 给执行文件添加执行权限
|
||||
RUN chmod +x ./zhub.sh
|
||||
|
||||
# 暴露端口
|
||||
# 711: 管理接口端口
|
||||
# 1216: 服务端口
|
||||
EXPOSE 711 1216
|
||||
|
||||
# 设置启动命令
|
||||
CMD ["./zhub.sh"]
|
||||
```
|
||||
|
||||
构建镜像:
|
||||
|
||||
```bash
|
||||
# 构建镜像
|
||||
docker build -t zhub:latest .
|
||||
```
|
||||
|
||||
### 3. 运行容器
|
||||
|
||||
```bash
|
||||
# 基础运行
|
||||
docker run -d -p 711:711 -p 1216:1216 --name zhub zhub:latest
|
||||
|
||||
# 带数据持久化
|
||||
docker run -d \
|
||||
-p 711:711 \
|
||||
-p 1216:1216 \
|
||||
-v /host/data:/opt/zhub/data \
|
||||
--name zhub \
|
||||
zhub:latest
|
||||
```
|
||||
|
||||
### 4. 验证部署
|
||||
|
||||
```bash
|
||||
# 检查服务状态
|
||||
curl http://localhost:711/_/info
|
||||
|
||||
# 查看容器日志
|
||||
docker logs -f zhub
|
||||
```
|
||||
|
||||
## 生产环境配置
|
||||
|
||||
### 数据持久化
|
||||
```bash
|
||||
# 挂载数据目录
|
||||
docker run -d \
|
||||
-p 711:711 \
|
||||
-p 1216:1216 \
|
||||
-v /host/data:/opt/zhub/data \
|
||||
--name zhub \
|
||||
zhub:latest
|
||||
```
|
||||
|
||||
### 自定义配置
|
||||
```bash
|
||||
# 挂载自定义配置文件
|
||||
docker run -d \
|
||||
-p 711:711 \
|
||||
-p 1216:1216 \
|
||||
-v /host/config/app.ini:/opt/zhub/app.ini \
|
||||
-v /host/config/auth.yml:/opt/zhub/auth.yml \
|
||||
--name zhub \
|
||||
zhub:latest
|
||||
```
|
||||
|
||||
## Docker Compose 部署
|
||||
|
||||
### 基础配置
|
||||
|
||||
创建 `docker-compose.yml` 文件:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
zhub:
|
||||
image: zhub:latest
|
||||
container_name: zhub
|
||||
ports:
|
||||
- "711:711" # 管理端口
|
||||
- "1216:1216" # 服务端口
|
||||
volumes:
|
||||
- ./data:/opt/zhub/data
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
### 启动服务
|
||||
|
||||
```bash
|
||||
# 启动服务
|
||||
docker-compose up -d
|
||||
|
||||
# 查看服务状态
|
||||
docker-compose ps
|
||||
|
||||
# 停止服务
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
```bash
|
||||
# 查看容器日志
|
||||
docker logs zhub
|
||||
|
||||
# 检查端口占用
|
||||
netstat -tulpn | grep :1216
|
||||
netstat -tulpn | grep :711
|
||||
|
||||
# 检查服务状态
|
||||
curl http://localhost:711/_/info
|
||||
```
|
||||
|
||||
### 调试模式
|
||||
|
||||
```bash
|
||||
# 以调试模式运行
|
||||
docker run -it --rm \
|
||||
-p 711:711 \
|
||||
-p 1216:1216 \
|
||||
-v ./data:/opt/zhub/data \
|
||||
zhub:latest
|
||||
```
|
||||
497
docs/tutorial-extras/faq.md
Normal file
497
docs/tutorial-extras/faq.md
Normal file
@@ -0,0 +1,497 @@
|
||||
---
|
||||
sidebar_position: 11
|
||||
title: 常见问题
|
||||
description: ZHub 常见问题解答
|
||||
---
|
||||
|
||||
# 常见问题
|
||||
|
||||
本文档收集了 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: 安装步骤:
|
||||
1. 下载 `zhub.zip` 发布包
|
||||
2. 解压到目标目录
|
||||
3. 配置 `app.ini` 文件
|
||||
4. 运行 `./zhub.sh`(Linux)或 `./zhub.exe`(Windows)
|
||||
|
||||
### Q: 如何配置 ZHub?
|
||||
|
||||
A: 主要配置文件是 `app.ini`:
|
||||
```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` 文件:
|
||||
```yaml
|
||||
users:
|
||||
- id: 1
|
||||
username: "client-001"
|
||||
password: "password123"
|
||||
status: "active"
|
||||
reads: ["*"]
|
||||
writes: ["*"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 客户端使用
|
||||
|
||||
### Q: 如何创建客户端连接?
|
||||
|
||||
A: Java 客户端连接:
|
||||
```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: 基础用法:
|
||||
```java
|
||||
// 订阅消息
|
||||
zhub.subscribe("topic", message -> {
|
||||
System.out.println("收到消息: " + message);
|
||||
});
|
||||
|
||||
// 发布消息
|
||||
zhub.publish("topic", "Hello ZHub!");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 功能使用
|
||||
|
||||
### Q: 如何实现 RPC 调用?
|
||||
|
||||
A: RPC 使用示例:
|
||||
```java
|
||||
// 服务端
|
||||
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: 分布式锁使用:
|
||||
```java
|
||||
// 阻塞式获取锁
|
||||
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: 定时任务使用:
|
||||
```java
|
||||
// 订阅定时任务
|
||||
zhub.timer("T:A", () -> {
|
||||
System.out.println("定时任务执行");
|
||||
});
|
||||
```
|
||||
|
||||
需要在数据库中配置定时任务:
|
||||
```sql
|
||||
INSERT INTO tasktimer (timerid, name, expr, single, remark, status) VALUES
|
||||
('T1', 'T:A', '*/5 * * * * ?', 1, '每5秒执行一次', 10);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 权限和安全
|
||||
|
||||
### Q: 如何配置用户权限?
|
||||
|
||||
A: 在 `auth.yml` 中配置用户权限:
|
||||
```yaml
|
||||
users:
|
||||
- id: 1
|
||||
username: "user-service"
|
||||
password: "password123"
|
||||
status: "active"
|
||||
groups: ["user-service"]
|
||||
reads: ["user.*"] # 读取权限
|
||||
writes: ["user.*"] # 写入权限
|
||||
```
|
||||
|
||||
### Q: 如何实现细粒度权限控制?
|
||||
|
||||
A: 使用正则表达式控制 Topic 权限:
|
||||
```yaml
|
||||
users:
|
||||
- id: 1
|
||||
username: "client-001"
|
||||
reads: ["user.*", "order.*"] # 可读取 user.* 和 order.* 主题
|
||||
writes: ["user.*"] # 只能写入 user.* 主题
|
||||
```
|
||||
|
||||
### Q: Token 过期了怎么办?
|
||||
|
||||
A: 解决方案:
|
||||
1. **延长 Token 过期时间**:
|
||||
```yaml
|
||||
tokens:
|
||||
- id: 1
|
||||
token: "token-12345"
|
||||
expiration: "2030-12-31T23:59:59Z" # 设置较长时间
|
||||
```
|
||||
|
||||
2. **重新加载权限配置**:
|
||||
```bash
|
||||
curl http://127.0.0.1:711/auth/reload
|
||||
```
|
||||
|
||||
3. **仅在开发环境关闭权限验证**:
|
||||
```ini
|
||||
[service]
|
||||
auth=0 # 仅适用于完全隔离的开发测试环境
|
||||
```
|
||||
|
||||
:::warning 安全提醒
|
||||
- 生产环境强烈建议开启权限验证,即使在内网环境
|
||||
- 关闭权限验证存在安全风险,仅适用于开发测试环境
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## 数据库配置
|
||||
|
||||
### Q: 支持哪些数据库?
|
||||
|
||||
A: ZHub 支持以下数据库:
|
||||
- **MySQL**: 默认支持
|
||||
- **PostgreSQL**: 支持
|
||||
|
||||
### Q: 如何配置数据库连接?
|
||||
|
||||
A: 在 `app.ini` 中配置:
|
||||
```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 初始化:
|
||||
```sql
|
||||
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 初始化:
|
||||
```sql
|
||||
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: 性能优化建议:
|
||||
1. **异步处理消息**:
|
||||
```java
|
||||
zhub.subscribe("topic", message -> {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
processMessage(message);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
2. **批量处理消息**:
|
||||
```java
|
||||
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();
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
3. **使用连接池**:
|
||||
```java
|
||||
// 复用连接,避免频繁创建
|
||||
private static final ZHubClient zhub = new ZHubClient(...);
|
||||
```
|
||||
|
||||
### Q: 如何监控性能?
|
||||
|
||||
A: 监控方法:
|
||||
1. **使用管理接口**:
|
||||
```bash
|
||||
curl http://127.0.0.1:711/_/info
|
||||
```
|
||||
|
||||
2. **客户端监控**:
|
||||
```java
|
||||
public class PerformanceMonitor {
|
||||
private final AtomicLong messageCount = new AtomicLong(0);
|
||||
|
||||
public void monitorMessage(String message) {
|
||||
messageCount.incrementAndGet();
|
||||
// 处理消息
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 故障排除
|
||||
|
||||
### Q: 客户端连接失败怎么办?
|
||||
|
||||
A: 排查步骤:
|
||||
1. **检查服务是否运行**:
|
||||
```bash
|
||||
ps aux | grep zhub
|
||||
```
|
||||
|
||||
2. **检查端口是否监听**:
|
||||
```bash
|
||||
netstat -tulpn | grep :1216
|
||||
```
|
||||
|
||||
3. **检查网络连接**:
|
||||
```bash
|
||||
telnet 127.0.0.1 1216
|
||||
```
|
||||
|
||||
4. **检查防火墙设置**:
|
||||
```bash
|
||||
ufw status
|
||||
iptables -L
|
||||
```
|
||||
|
||||
### Q: 消息丢失怎么办?
|
||||
|
||||
A: 消息丢失排查:
|
||||
1. **检查网络连接**:确保网络稳定
|
||||
2. **检查客户端处理**:确保消息处理逻辑正确
|
||||
3. **检查服务端资源**:确保服务端有足够资源
|
||||
4. **使用管理接口清理内存**:
|
||||
```bash
|
||||
curl http://127.0.0.1:711/_/cleanup
|
||||
```
|
||||
|
||||
### Q: RPC 调用超时怎么办?
|
||||
|
||||
A: RPC 超时解决:
|
||||
1. **增加超时时间**:
|
||||
```java
|
||||
RpcResult<String> result = zhub.rpc("rpc-topic", "data", IType.STRING, 30000);
|
||||
```
|
||||
|
||||
2. **使用异步 RPC**:
|
||||
```java
|
||||
CompletableFuture<RpcResult<String>> future =
|
||||
zhub.rpcAsync("rpc-topic", "data", IType.STRING);
|
||||
```
|
||||
|
||||
3. **检查服务端处理时间**:优化服务端处理逻辑
|
||||
|
||||
### Q: 定时任务不执行怎么办?
|
||||
|
||||
A: 定时任务排查:
|
||||
1. **检查数据库连接**:
|
||||
```bash
|
||||
curl http://127.0.0.1:711/_/info
|
||||
```
|
||||
|
||||
2. **重新加载定时任务**:
|
||||
```bash
|
||||
curl http://127.0.0.1:711/timer/reload
|
||||
```
|
||||
|
||||
3. **检查任务状态**:
|
||||
```sql
|
||||
SELECT * FROM tasktimer WHERE status = 10;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 部署问题
|
||||
|
||||
### Q: 如何部署到生产环境?
|
||||
|
||||
A: 生产环境部署建议:
|
||||
1. **使用 Docker 部署**:
|
||||
```bash
|
||||
docker run -d -p 711:711 -p 1216:1216 --name zhub zhub:latest
|
||||
```
|
||||
|
||||
2. **配置数据持久化**:
|
||||
```bash
|
||||
docker run -d -v /host/data:/opt/zhub/data zhub:latest
|
||||
```
|
||||
|
||||
3. **配置环境变量**:
|
||||
```bash
|
||||
docker run -d -e ZHUB_AUTH=1 zhub:latest
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 版本升级
|
||||
|
||||
### Q: 如何升级 ZHub?
|
||||
|
||||
A: 升级步骤:
|
||||
1. **备份数据**:备份数据目录和配置文件
|
||||
2. **停止服务**:停止当前 ZHub 服务
|
||||
3. **替换文件**:替换为新版本文件
|
||||
4. **启动服务**:启动新版本服务
|
||||
5. **验证功能**:验证各项功能正常
|
||||
|
||||
### Q: 升级后配置不兼容怎么办?
|
||||
|
||||
A: 配置兼容性处理:
|
||||
1. **检查配置文件**:对比新旧配置文件
|
||||
2. **更新配置格式**:按照新版本要求更新配置
|
||||
3. **测试功能**:测试各项功能是否正常
|
||||
4. **回滚准备**:准备回滚方案
|
||||
|
||||
---
|
||||
|
||||
## 性能优化
|
||||
|
||||
### Q: 如何优化 ZHub 性能?
|
||||
|
||||
A: 性能优化建议:
|
||||
1. **异步处理**:避免阻塞消息处理
|
||||
```java
|
||||
zhub.subscribe("topic", message -> {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
processMessage(message);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
2. **错误处理**:添加异常捕获
|
||||
```java
|
||||
zhub.subscribe("topic", message -> {
|
||||
try {
|
||||
processMessage(message);
|
||||
} catch (Exception e) {
|
||||
logger.error("消息处理失败", e);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
3. **内存管理**:定期清理内存
|
||||
```bash
|
||||
curl http://127.0.0.1:711/_/cleanup
|
||||
```
|
||||
|
||||
### Q: 如何监控 ZHub 状态?
|
||||
|
||||
A: 监控方法:
|
||||
1. **服务状态**:`curl http://127.0.0.1:711/_/info`
|
||||
2. **内存使用**:`free -h`
|
||||
3. **网络连接**:`netstat -tulpn | grep :1216`
|
||||
|
||||
## 技术支持
|
||||
|
||||
### Q: 如何获取技术支持?
|
||||
|
||||
A: 技术支持渠道:
|
||||
1. **查看文档**:参考官方文档
|
||||
2. **查看日志**:检查服务端和客户端日志
|
||||
3. **联系作者**:
|
||||
- 作者: 绝尘
|
||||
- 微信: zhub_dev
|
||||
- 邮箱: lxy208@126.com
|
||||
@@ -1,5 +1,314 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
sidebar_position: 3
|
||||
title: 分布式锁
|
||||
description: ZHub 分布式锁功能详解
|
||||
---
|
||||
|
||||
# 分布式锁
|
||||
|
||||
ZHub 提供了分布式锁功能,支持多客户端环境下的资源互斥访问控制。
|
||||
|
||||
---
|
||||
|
||||
## 功能特性
|
||||
|
||||
- **分布式互斥**: 多个客户端实例之间互斥访问共享资源
|
||||
- **自动超时**: 支持锁超时自动释放,避免死锁
|
||||
- **非阻塞获取**: 支持尝试获取锁,立即返回结果
|
||||
- **自动释放**: 支持手动释放锁,确保资源及时释放
|
||||
|
||||
---
|
||||
|
||||
## 基础使用
|
||||
|
||||
### 1. 阻塞式获取锁
|
||||
|
||||
```java
|
||||
// 获取锁,会阻塞直到获取成功或超时
|
||||
Lock lock = zhub.lock("resource-key", 30); // 30秒超时
|
||||
try {
|
||||
if (lock.success()) {
|
||||
System.out.println("获取到锁,开始处理业务");
|
||||
// 执行业务逻辑
|
||||
Thread.sleep(5000); // 模拟业务处理
|
||||
} else {
|
||||
System.out.println("获取锁失败");
|
||||
}
|
||||
} finally {
|
||||
lock.unLock(); // 释放锁
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 非阻塞式获取锁
|
||||
|
||||
```java
|
||||
// 尝试获取锁,立即返回结果
|
||||
Lock lock = zhub.tryLock("resource-key", 30);
|
||||
if (lock.success()) {
|
||||
try {
|
||||
System.out.println("获取到锁,开始处理业务");
|
||||
// 执行业务逻辑
|
||||
} finally {
|
||||
lock.unLock(); // 释放锁
|
||||
}
|
||||
} else {
|
||||
System.out.println("未获取到锁,资源被其他客户端占用");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 高级用法
|
||||
|
||||
### 1. 锁超时处理
|
||||
|
||||
```java
|
||||
public void processWithTimeout(String resourceKey, int timeoutSeconds) {
|
||||
Lock lock = zhub.tryLock(resourceKey, timeoutSeconds);
|
||||
if (!lock.success()) {
|
||||
System.out.println("资源被占用,请稍后重试");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 业务处理
|
||||
processResource(resourceKey);
|
||||
} finally {
|
||||
lock.unLock();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 锁重试机制
|
||||
|
||||
```java
|
||||
public boolean processWithRetry(String resourceKey, int maxRetries) {
|
||||
for (int i = 0; i < maxRetries; i++) {
|
||||
Lock lock = zhub.tryLock(resourceKey, 10);
|
||||
if (lock.success()) {
|
||||
try {
|
||||
// 业务处理
|
||||
processResource(resourceKey);
|
||||
return true;
|
||||
} finally {
|
||||
lock.unLock();
|
||||
}
|
||||
}
|
||||
|
||||
// 等待一段时间后重试
|
||||
try {
|
||||
Thread.sleep(1000 * (i + 1)); // 递增等待时间
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 锁监控和统计
|
||||
|
||||
```java
|
||||
public class LockMonitor {
|
||||
private final ZHubClient zhub;
|
||||
private final Map<String, LockInfo> lockStats = new ConcurrentHashMap<>();
|
||||
|
||||
public void acquireLock(String key, int timeout) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
Lock lock = zhub.lock(key, timeout);
|
||||
|
||||
if (lock.success()) {
|
||||
long acquireTime = System.currentTimeMillis() - startTime;
|
||||
lockStats.put(key, new LockInfo(key, acquireTime, System.currentTimeMillis()));
|
||||
System.out.println("锁获取成功,耗时: " + acquireTime + "ms");
|
||||
}
|
||||
}
|
||||
|
||||
public void releaseLock(String key) {
|
||||
LockInfo info = lockStats.remove(key);
|
||||
if (info != null) {
|
||||
long holdTime = System.currentTimeMillis() - info.acquireTime;
|
||||
System.out.println("锁持有时间: " + holdTime + "ms");
|
||||
}
|
||||
}
|
||||
|
||||
static class LockInfo {
|
||||
String key;
|
||||
long acquireTime;
|
||||
long acquireDuration;
|
||||
|
||||
LockInfo(String key, long acquireDuration, long acquireTime) {
|
||||
this.key = key;
|
||||
this.acquireDuration = acquireDuration;
|
||||
this.acquireTime = acquireTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 实现原理
|
||||
|
||||
### 服务端实现
|
||||
|
||||
ZHub 服务端锁管理结构:
|
||||
|
||||
```go
|
||||
// 锁结构
|
||||
type Lock struct {
|
||||
Key string
|
||||
UUID string
|
||||
Duration int
|
||||
Conn *ZConn
|
||||
CreateTime time.Time
|
||||
}
|
||||
|
||||
// 锁管理
|
||||
type ZBus struct {
|
||||
locks map[string][]*Lock // 锁映射表
|
||||
// ... 其他字段
|
||||
}
|
||||
```
|
||||
|
||||
### 客户端实现
|
||||
|
||||
ZHub 客户端锁实现结构:
|
||||
|
||||
```java
|
||||
public class Lock {
|
||||
protected String name; // 锁名称
|
||||
protected String uuid; // 锁唯一标识
|
||||
protected int duration; // 锁持续时间
|
||||
protected boolean success; // 获取是否成功
|
||||
protected ZHubClient hubClient; // 客户端引用
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 1. 锁命名规范
|
||||
|
||||
```java
|
||||
// 推荐:使用有意义的锁名称
|
||||
String lockKey = "user:update:" + userId;
|
||||
String lockKey = "order:process:" + orderId;
|
||||
String lockKey = "cache:refresh:" + cacheType;
|
||||
|
||||
// 避免:使用无意义的锁名称
|
||||
String lockKey = "lock1";
|
||||
String lockKey = "temp";
|
||||
```
|
||||
|
||||
### 2. 超时时间设置
|
||||
|
||||
```java
|
||||
// 根据业务处理时间设置合理的超时时间
|
||||
int shortTaskTimeout = 5; // 短任务:5秒
|
||||
int mediumTaskTimeout = 30; // 中等任务:30秒
|
||||
int longTaskTimeout = 300; // 长任务:5分钟
|
||||
|
||||
// 避免设置过短或过长的超时时间
|
||||
int tooShort = 1; // 太短,可能导致获取失败
|
||||
int tooLong = 3600; // 太长,可能导致资源长时间占用
|
||||
```
|
||||
|
||||
### 3. 异常处理
|
||||
|
||||
```java
|
||||
public void safeProcess(String resourceKey) {
|
||||
Lock lock = null;
|
||||
try {
|
||||
lock = zhub.lock(resourceKey, 30);
|
||||
if (lock.success()) {
|
||||
// 业务处理
|
||||
processResource(resourceKey);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("处理资源时发生异常", e);
|
||||
} finally {
|
||||
if (lock != null && lock.success()) {
|
||||
try {
|
||||
lock.unLock();
|
||||
} catch (Exception e) {
|
||||
logger.error("释放锁时发生异常", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 性能优化
|
||||
|
||||
```java
|
||||
// 使用 tryLock 避免长时间阻塞
|
||||
public boolean tryProcess(String resourceKey) {
|
||||
Lock lock = zhub.tryLock(resourceKey, 5);
|
||||
if (!lock.success()) {
|
||||
return false; // 快速失败
|
||||
}
|
||||
|
||||
try {
|
||||
processResource(resourceKey);
|
||||
return true;
|
||||
} finally {
|
||||
lock.unLock();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
### 1. 死锁预防
|
||||
|
||||
- 避免嵌套锁的使用
|
||||
- 设置合理的锁超时时间
|
||||
- 确保锁的释放逻辑正确
|
||||
|
||||
### 2. 性能考虑
|
||||
|
||||
- 锁的粒度要适中,不要过细或过粗
|
||||
- 避免长时间持有锁
|
||||
- 考虑使用非阻塞的 tryLock
|
||||
|
||||
### 3. 错误处理
|
||||
|
||||
- 始终在 finally 块中释放锁
|
||||
- 处理锁获取失败的情况
|
||||
- 记录锁的使用情况用于监控
|
||||
|
||||
---
|
||||
|
||||
## 监控和调试
|
||||
|
||||
### 1. 锁状态查询
|
||||
|
||||
```bash
|
||||
# 通过管理接口查看锁状态
|
||||
curl http://127.0.0.1:711/_/info
|
||||
```
|
||||
|
||||
### 2. 日志监控
|
||||
|
||||
```java
|
||||
// 在客户端代码中添加锁使用日志
|
||||
logger.info("尝试获取锁: " + resourceKey);
|
||||
Lock lock = zhub.lock(resourceKey, 30);
|
||||
if (lock.success()) {
|
||||
logger.info("锁获取成功: " + resourceKey);
|
||||
} else {
|
||||
logger.warn("锁获取失败: " + resourceKey);
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 性能指标
|
||||
|
||||
- 锁获取成功率
|
||||
- 锁平均持有时间
|
||||
- 锁等待时间
|
||||
- 锁竞争频率
|
||||
|
||||
132
docs/tutorial-extras/security-best-practices.md
Normal file
132
docs/tutorial-extras/security-best-practices.md
Normal file
@@ -0,0 +1,132 @@
|
||||
---
|
||||
sidebar_position: 8
|
||||
title: 安全最佳实践
|
||||
description: ZHub 安全配置和最佳实践指南
|
||||
---
|
||||
|
||||
# 安全最佳实践
|
||||
|
||||
ZHub 安全配置和最佳实践指南,帮助您构建安全的分布式系统。
|
||||
|
||||
## 认证和授权
|
||||
|
||||
### 启用权限验证
|
||||
|
||||
**服务端配置**:
|
||||
```ini
|
||||
# app.ini - 生产环境配置
|
||||
[service]
|
||||
auth=1 # 生产环境必须开启连接授权
|
||||
```
|
||||
|
||||
:::warning 重要安全提醒
|
||||
**生产环境强烈建议开启权限验证**:
|
||||
- 关闭权限验证 (`auth=0`) 意味着任何客户端都可以无限制访问所有主题
|
||||
- 即使在内网环境,也存在内部威胁、误操作、配置错误等风险
|
||||
- 仅在完全隔离的开发测试环境可考虑关闭权限验证
|
||||
:::
|
||||
|
||||
**客户端配置**:
|
||||
```java
|
||||
// 使用认证令牌连接
|
||||
ZHubClient zhub = new ZHubClient(
|
||||
"127.0.0.1:1216",
|
||||
"group1",
|
||||
"app1",
|
||||
"your-secure-token"
|
||||
);
|
||||
```
|
||||
|
||||
### 权限配置
|
||||
|
||||
**最小权限原则**:
|
||||
```yaml
|
||||
# auth.yml
|
||||
users:
|
||||
- id: 1
|
||||
username: "user-service"
|
||||
password: "secure-password"
|
||||
status: "active"
|
||||
groups: ["user-service"]
|
||||
reads: ["user.*"] # 只读用户相关主题
|
||||
writes: ["user.*"] # 只写用户相关主题
|
||||
|
||||
- id: 2
|
||||
username: "order-service"
|
||||
password: "secure-password"
|
||||
status: "active"
|
||||
groups: ["order-service"]
|
||||
reads: ["order.*", "user.basic.*"] # 只读订单和用户基础信息
|
||||
writes: ["order.*"] # 只写订单相关主题
|
||||
```
|
||||
|
||||
**权限隔离**:
|
||||
```yaml
|
||||
# 不同团队权限隔离
|
||||
groups:
|
||||
- name: "user-team"
|
||||
description: "用户服务团队"
|
||||
reads: ["user.*"]
|
||||
writes: ["user.*"]
|
||||
|
||||
- name: "order-team"
|
||||
description: "订单服务团队"
|
||||
reads: ["order.*", "user.basic.*"]
|
||||
writes: ["order.*"]
|
||||
|
||||
- name: "admin-team"
|
||||
description: "管理员团队"
|
||||
reads: ["*"]
|
||||
writes: ["*"]
|
||||
```
|
||||
|
||||
## 网络安全
|
||||
|
||||
### 网络隔离
|
||||
|
||||
**内网部署**:
|
||||
```ini
|
||||
# app.ini - 只监听内网地址
|
||||
[service]
|
||||
watch=192.168.1.100:711 # 管理端口只监听内网
|
||||
addr=192.168.1.100:1216 # 服务端口只监听内网
|
||||
```
|
||||
|
||||
**防火墙配置**:
|
||||
```bash
|
||||
# 只允许内网访问
|
||||
iptables -A INPUT -p tcp --dport 1216 -s 192.168.1.0/24 -j ACCEPT
|
||||
iptables -A INPUT -p tcp --dport 711 -s 192.168.1.0/24 -j ACCEPT
|
||||
iptables -A INPUT -p tcp --dport 1216 -j DROP
|
||||
iptables -A INPUT -p tcp --dport 711 -j DROP
|
||||
```
|
||||
|
||||
|
||||
## 监控
|
||||
|
||||
### 基础监控
|
||||
|
||||
**服务状态监控**:
|
||||
```bash
|
||||
# 检查服务状态
|
||||
curl http://127.0.0.1:711/_/info
|
||||
|
||||
# 检查权限配置
|
||||
curl http://127.0.0.1:711/auth/reload
|
||||
```
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 安全配置检查清单
|
||||
|
||||
- [ ] 启用认证和授权 (`auth=1`)
|
||||
- [ ] 配置最小权限原则
|
||||
- [ ] 实施网络隔离
|
||||
- [ ] 启用访问日志
|
||||
- [ ] 定期安全审计
|
||||
|
||||
### 定期维护
|
||||
|
||||
- 定期检查权限配置
|
||||
- 定期更新认证令牌
|
||||
- 监控服务状态和连接情况
|
||||
@@ -1,5 +1,444 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
title: 定时调度
|
||||
description: ZHub 定时调度功能详解
|
||||
---
|
||||
|
||||
# 定时调度
|
||||
# 定时调度
|
||||
|
||||
ZHub 提供了强大的定时调度功能,支持基于 Cron 表达式和简单时间间隔的定时任务。
|
||||
|
||||
---
|
||||
|
||||
## 功能特性
|
||||
|
||||
- **Cron 表达式**: 支持标准的 Cron 表达式语法
|
||||
- **简单间隔**: 支持秒、分、时、天等时间单位
|
||||
- **数据库持久化**: 支持将定时任务配置保存到数据库
|
||||
- **任务执行**: 支持定时任务执行
|
||||
- **动态重载**: 支持运行时重新加载定时任务配置
|
||||
|
||||
---
|
||||
|
||||
## 基础使用
|
||||
|
||||
### 1. 简单定时任务
|
||||
|
||||
```java
|
||||
// 订阅定时任务
|
||||
zhub.timer("T:A", () -> {
|
||||
System.out.println("收到定时调度事件:T:A");
|
||||
// 执行定时任务逻辑
|
||||
});
|
||||
|
||||
// 每5秒执行一次
|
||||
zhub.timer("T:B", () -> {
|
||||
System.out.println("每5秒执行一次");
|
||||
});
|
||||
```
|
||||
|
||||
### 2. 基于 Cron 表达式的定时任务
|
||||
|
||||
```java
|
||||
// 每天早上8点执行
|
||||
zhub.timer("daily-report", () -> {
|
||||
System.out.println("生成日报");
|
||||
});
|
||||
|
||||
// 每周一上午9点执行
|
||||
zhub.timer("weekly-summary", () -> {
|
||||
System.out.println("生成周报");
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 时间表达式语法
|
||||
|
||||
### 1. 简单时间间隔
|
||||
|
||||
ZHub 支持以下时间单位格式:
|
||||
|
||||
```java
|
||||
// 支持的时间单位
|
||||
"5s" // 5秒
|
||||
"10m" // 10分钟
|
||||
"2H" // 2小时
|
||||
"1d" // 1天
|
||||
"1M" // 1个月
|
||||
"1y" // 1年
|
||||
|
||||
// 纯数字表示毫秒
|
||||
"5000" // 5000毫秒
|
||||
```
|
||||
|
||||
### 2. Cron 表达式
|
||||
|
||||
ZHub 支持标准 Cron 表达式格式:
|
||||
|
||||
```java
|
||||
// 标准 Cron 表达式格式:分 时 日 月 周
|
||||
"0 8 * * *" // 每天8点
|
||||
"0 0 1 * *" // 每月1号0点
|
||||
"0 9 * * 1" // 每周一9点
|
||||
"*/5 * * * *" // 每5分钟
|
||||
"0 0 0 1 1" // 每年1月1日0点
|
||||
```
|
||||
|
||||
### 3. 复杂 Cron 表达式
|
||||
|
||||
```java
|
||||
// 工作日每天9点和18点执行
|
||||
"0 9,18 * * 1-5"
|
||||
|
||||
// 每月1号和15号执行
|
||||
"0 0 1,15 * *"
|
||||
|
||||
// 每小时的0分和30分执行
|
||||
"0,30 * * * *"
|
||||
|
||||
// 每5分钟执行
|
||||
"*/5 * * * *"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 数据库配置
|
||||
|
||||
### 1. 数据库表结构
|
||||
|
||||
ZHub 定时任务数据库表结构:
|
||||
|
||||
```sql
|
||||
CREATE TABLE `tasktimer` (
|
||||
`timerid` varchar(64) NOT NULL DEFAULT '' COMMENT '[主键]UUID',
|
||||
`name` varchar(32) NOT NULL DEFAULT '' COMMENT '[任务名称]',
|
||||
`expr` varchar(32) NOT NULL DEFAULT '' COMMENT '[时间表达式]',
|
||||
`single` int NOT NULL DEFAULT '1' COMMENT '[单实例消费]1单对象,0不限',
|
||||
`remark` varchar(128) NOT NULL DEFAULT '' COMMENT '[备注]',
|
||||
`status` smallint NOT NULL DEFAULT '10' COMMENT '[状态]10启用,60停用',
|
||||
PRIMARY KEY (`timerid`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
```
|
||||
|
||||
### 2. 配置示例
|
||||
|
||||
```sql
|
||||
-- 插入定时任务配置
|
||||
INSERT INTO `tasktimer` (`timerid`, `name`, `expr`, `single`, `remark`, `status`) VALUES
|
||||
('T1', 'T:A', '*/5 * * * * ?', 1, '每5秒执行一次', 10),
|
||||
('T2', 'T:B', '15s', 1, '每15秒执行一次', 10),
|
||||
('T3', 'T:C', '0 0 0 * * 1', 0, '每周一00:00执行', 10),
|
||||
('T4', 'T:D', '0 0 24 * * ?', 1, '每天00:00执行', 10);
|
||||
```
|
||||
|
||||
### 3. 服务端配置
|
||||
|
||||
在 `app.ini` 中配置数据库连接:
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 高级功能
|
||||
|
||||
### 1. 单实例执行
|
||||
|
||||
```java
|
||||
// 单实例执行:只有一个客户端实例会执行任务
|
||||
zhub.timer("single-task", () -> {
|
||||
System.out.println("只有一个实例执行此任务");
|
||||
});
|
||||
```
|
||||
|
||||
### 2. 多实例执行
|
||||
|
||||
```java
|
||||
// 多实例执行:所有客户端实例都会执行任务
|
||||
zhub.timer("multi-task", () -> {
|
||||
System.out.println("所有实例都会执行此任务");
|
||||
});
|
||||
```
|
||||
|
||||
### 3. 动态重载配置
|
||||
|
||||
```bash
|
||||
# 通过管理接口重新加载定时任务配置
|
||||
curl http://127.0.0.1:711/timer/reload
|
||||
```
|
||||
|
||||
### 4. 本地定时任务
|
||||
|
||||
ZHub 客户端还提供本地定时任务功能:
|
||||
|
||||
```java
|
||||
// 本地延时任务(适用于短时间延时)
|
||||
Timers.delay(() -> {
|
||||
System.out.println("延时5秒后执行");
|
||||
}, 5000);
|
||||
|
||||
// 本地重试任务
|
||||
Timers.tryDelay(() -> {
|
||||
// 返回 true 表示成功,false 表示需要重试
|
||||
return processTask();
|
||||
}, 1000, 3); // 每1秒重试一次,最多重试3次
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 实际应用场景
|
||||
|
||||
### 1. 数据同步任务
|
||||
|
||||
```java
|
||||
public class DataSyncService {
|
||||
private final ZHubClient zhub;
|
||||
|
||||
public void init() {
|
||||
// 每小时同步一次数据
|
||||
zhub.timer("data-sync", () -> {
|
||||
syncData();
|
||||
});
|
||||
|
||||
// 每天凌晨2点清理过期数据
|
||||
zhub.timer("data-cleanup", () -> {
|
||||
cleanupExpiredData();
|
||||
});
|
||||
}
|
||||
|
||||
private void syncData() {
|
||||
System.out.println("开始同步数据...");
|
||||
// 数据同步逻辑
|
||||
}
|
||||
|
||||
private void cleanupExpiredData() {
|
||||
System.out.println("开始清理过期数据...");
|
||||
// 数据清理逻辑
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 监控和告警
|
||||
|
||||
```java
|
||||
public class MonitorService {
|
||||
private final ZHubClient zhub;
|
||||
|
||||
public void init() {
|
||||
// 每30秒检查系统状态
|
||||
zhub.timer("system-check", () -> {
|
||||
checkSystemHealth();
|
||||
});
|
||||
|
||||
// 每天生成监控报告
|
||||
zhub.timer("daily-report", () -> {
|
||||
generateDailyReport();
|
||||
});
|
||||
}
|
||||
|
||||
private void checkSystemHealth() {
|
||||
// 系统健康检查逻辑
|
||||
if (isSystemHealthy()) {
|
||||
System.out.println("系统状态正常");
|
||||
} else {
|
||||
sendAlert("系统异常,请检查");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 缓存刷新
|
||||
|
||||
```java
|
||||
public class CacheService {
|
||||
private final ZHubClient zhub;
|
||||
|
||||
public void init() {
|
||||
// 每5分钟刷新缓存
|
||||
zhub.timer("cache-refresh", () -> {
|
||||
refreshCache();
|
||||
});
|
||||
|
||||
// 每天凌晨3点预热缓存
|
||||
zhub.timer("cache-warmup", () -> {
|
||||
warmupCache();
|
||||
});
|
||||
}
|
||||
|
||||
private void refreshCache() {
|
||||
System.out.println("刷新缓存...");
|
||||
// 缓存刷新逻辑
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 1. 任务命名规范
|
||||
|
||||
```java
|
||||
// 推荐:使用有意义的任务名称
|
||||
zhub.timer("user:data-sync", () -> {});
|
||||
zhub.timer("order:status-check", () -> {});
|
||||
zhub.timer("system:health-check", () -> {});
|
||||
|
||||
// 避免:使用无意义的名称
|
||||
zhub.timer("task1", () -> {});
|
||||
zhub.timer("timer", () -> {});
|
||||
```
|
||||
|
||||
### 2. 异常处理
|
||||
|
||||
```java
|
||||
zhub.timer("safe-task", () -> {
|
||||
try {
|
||||
// 任务逻辑
|
||||
processTask();
|
||||
} catch (Exception e) {
|
||||
logger.error("定时任务执行失败", e);
|
||||
// 发送告警或记录错误
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 3. 性能优化
|
||||
|
||||
```java
|
||||
// 避免在定时任务中执行耗时操作
|
||||
zhub.timer("light-task", () -> {
|
||||
// 快速执行的任务
|
||||
updateStatus();
|
||||
});
|
||||
|
||||
// 耗时操作应该异步执行
|
||||
zhub.timer("heavy-task", () -> {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
// 异步执行耗时操作
|
||||
processHeavyTask();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 4. 监控和日志
|
||||
|
||||
```java
|
||||
public class MonitoredTimer {
|
||||
private final ZHubClient zhub;
|
||||
private final Logger logger = LoggerFactory.getLogger(MonitoredTimer.class);
|
||||
|
||||
public void init() {
|
||||
zhub.timer("monitored-task", () -> {
|
||||
long startTime = System.currentTimeMillis();
|
||||
try {
|
||||
processTask();
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
logger.info("定时任务执行成功,耗时: {}ms", duration);
|
||||
} catch (Exception e) {
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
logger.error("定时任务执行失败,耗时: {}ms", duration, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 1. 任务不执行
|
||||
|
||||
**可能原因**:
|
||||
- 数据库连接配置错误
|
||||
- 任务状态为停用(status=60)
|
||||
- 时间表达式格式错误
|
||||
|
||||
**解决方法**:
|
||||
```bash
|
||||
# 检查数据库连接
|
||||
curl http://127.0.0.1:711/_/info
|
||||
|
||||
# 重新加载配置
|
||||
curl http://127.0.0.1:711/timer/reload
|
||||
|
||||
# 检查任务状态
|
||||
SELECT * FROM tasktimer WHERE status = 10;
|
||||
```
|
||||
|
||||
### 2. 任务重复执行
|
||||
|
||||
**可能原因**:
|
||||
- 多个客户端实例都订阅了同一个任务
|
||||
- 单实例配置错误
|
||||
|
||||
**解决方法**:
|
||||
```sql
|
||||
-- 确保单实例配置正确
|
||||
UPDATE tasktimer SET single = 1 WHERE name = 'task-name';
|
||||
```
|
||||
|
||||
### 3. 任务执行时间不准确
|
||||
|
||||
**可能原因**:
|
||||
- 系统时间不同步
|
||||
- 任务执行时间过长
|
||||
|
||||
**解决方法**:
|
||||
- 同步系统时间
|
||||
- 优化任务执行逻辑
|
||||
- 考虑拆分长时间任务
|
||||
|
||||
---
|
||||
|
||||
## 监控和调试
|
||||
|
||||
### 1. 任务执行状态
|
||||
|
||||
```bash
|
||||
# 查看所有定时任务状态
|
||||
curl http://127.0.0.1:711/_/info | jq '.timersize'
|
||||
```
|
||||
|
||||
### 2. 日志监控
|
||||
|
||||
```java
|
||||
// 在任务中添加详细日志
|
||||
zhub.timer("logged-task", () -> {
|
||||
logger.info("定时任务开始执行: {}", LocalDateTime.now());
|
||||
try {
|
||||
processTask();
|
||||
logger.info("定时任务执行完成: {}", LocalDateTime.now());
|
||||
} catch (Exception e) {
|
||||
logger.error("定时任务执行异常: {}", e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 3. 性能监控
|
||||
|
||||
```java
|
||||
// 监控任务执行时间
|
||||
public class PerformanceMonitor {
|
||||
public void monitorTask(String taskName, Runnable task) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
try {
|
||||
task.run();
|
||||
} finally {
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
if (duration > 5000) { // 超过5秒记录警告
|
||||
logger.warn("任务 {} 执行时间过长: {}ms", taskName, duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
421
docs/tutorial-extras/troubleshooting.md
Normal file
421
docs/tutorial-extras/troubleshooting.md
Normal file
@@ -0,0 +1,421 @@
|
||||
---
|
||||
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)。
|
||||
278
docs/tutorial-extras/zhub-log.md
Normal file
278
docs/tutorial-extras/zhub-log.md
Normal file
@@ -0,0 +1,278 @@
|
||||
---
|
||||
sidebar_position: 11
|
||||
title: 日志管理
|
||||
description: ZHub 日志配置、格式分析、故障排查和监控指南
|
||||
keywords: [ZHub日志, 日志管理, 日志分析, 故障排查, 监控]
|
||||
---
|
||||
|
||||
# 日志管理
|
||||
|
||||
ZHub 日志文件配置、分析和故障排查指南。
|
||||
|
||||
## 目录
|
||||
|
||||
- [日志配置](#日志配置)
|
||||
- [日志文件位置](#日志文件位置)
|
||||
- [服务端日志](#日志内容分析)
|
||||
- [Java客户端日志](#java-客户端日志)
|
||||
- [日志分析](#日志分析)
|
||||
- [日志轮转](#日志轮转)
|
||||
- [故障排查](#故障排查)
|
||||
|
||||
## 日志配置
|
||||
|
||||
### 基础配置
|
||||
|
||||
**app.ini 配置**:
|
||||
```ini
|
||||
[log]
|
||||
level=info # 日志级别: debug, info, error
|
||||
handlers=console # 日志处理器: console, file
|
||||
file=zhub.log # 日志文件名
|
||||
```
|
||||
|
||||
### 日志级别说明
|
||||
|
||||
| 级别 | 说明 | 使用场景 |
|
||||
|------|------|----------|
|
||||
| debug | 调试信息 | 开发调试,包含详细的执行流程 |
|
||||
| info | 一般信息 | 生产环境,记录重要操作 |
|
||||
| error | 错误信息 | 严重错误,需要关注 |
|
||||
|
||||
## 日志文件位置
|
||||
|
||||
### 默认位置
|
||||
```bash
|
||||
# 当前目录下的日志文件
|
||||
./zhub.log
|
||||
```
|
||||
|
||||
### 自定义位置
|
||||
```ini
|
||||
# app.ini 中指定日志目录
|
||||
[log]
|
||||
file=/var/log/zhub/zhub.log
|
||||
```
|
||||
|
||||
## 日志内容分析
|
||||
|
||||
### 连接接入日志
|
||||
|
||||
**连接建立**:
|
||||
```
|
||||
2024/01/15 10:30:15.123456 zbus.go:291: [Info] conn start: 127.0.0.1:12345 [1]
|
||||
```
|
||||
- 格式:`[Info] conn start: IP:端口 [连接序号]`
|
||||
- 连接序号:每个新连接递增的数字标识
|
||||
|
||||
**连接断开**:
|
||||
```
|
||||
2024/01/15 10:30:20.123456 zbus.go:302: [Info] conn closed: 127.0.0.1:12345 [ 1 ]
|
||||
```
|
||||
- 格式:`[Info] conn closed: IP:端口 [ 连接序号 ]`
|
||||
- 包含正常断开和异常断开
|
||||
|
||||
**认证过程**:
|
||||
```
|
||||
2024/01/15 10:30:15.123456 zbus-message-handler.go:84: [Info] [1] -Auth: publish [user-login]
|
||||
2024/01/15 10:30:15.123456 zbus-message-handler.go:122: [Info] [1] cmd: publish, auth [OK]
|
||||
```
|
||||
- `-Auth:` 表示权限不足
|
||||
- `auth [OK]` 表示认证成功
|
||||
|
||||
### 消息收发日志
|
||||
|
||||
**消息发布**:
|
||||
```
|
||||
2024/01/15 10:30:15.123456 zbus-message-handler.go:45: [1] cmd: publish user-login {"userId":"12345"}
|
||||
```
|
||||
- 格式:`[连接序号] cmd: publish 主题名 消息内容`(debug级别)
|
||||
- 仅在debug级别下显示
|
||||
|
||||
**消息订阅**:
|
||||
```
|
||||
2024/01/15 10:30:15.123456 zbus-message-handler.go:45: [1] cmd: subscribe user-login order-create
|
||||
2024/01/15 10:30:15.123456 zbus-message-handler.go:122: [Info] [1] cmd: subscribe, auth [OK]
|
||||
```
|
||||
- 格式:`[连接序号] cmd: subscribe 主题列表`(debug级别)
|
||||
- 支持多主题订阅,空格分隔
|
||||
|
||||
**广播消息**:
|
||||
```
|
||||
2024/01/15 10:30:15.123456 zbus-message-handler.go:45: [1] cmd: broadcast topic-abc hello!
|
||||
```
|
||||
- 格式:`[连接序号] cmd: broadcast 主题名 消息内容`(debug级别)
|
||||
|
||||
**延时消息**:
|
||||
```
|
||||
2024/01/15 10:30:15.123456 zbus-message-handler.go:45: [1] cmd: delay order-timeout 30s 订单超时
|
||||
```
|
||||
- 格式:`[连接序号] cmd: delay 主题名 延时时间 消息内容`(debug级别)
|
||||
|
||||
### RPC 调用日志
|
||||
|
||||
**RPC 调用**:
|
||||
```
|
||||
2024/01/15 10:30:15.123456 zbus-message-handler.go:45: [1] cmd: rpc user-get-info {"ruk":"app1::12345"}
|
||||
```
|
||||
- 格式:`[连接序号] cmd: rpc 服务名 RPC参数`(debug级别)
|
||||
- RPC参数包含ruk(回复标识)
|
||||
|
||||
**RPC 服务离线**:
|
||||
```
|
||||
2024/01/15 10:30:15.123456 zbus-message-handler.go:132: [1] : rpc user-get-info no subscribe
|
||||
```
|
||||
- 格式:`[连接序号] : rpc 服务名 no subscribe`
|
||||
- 表示没有客户端订阅该RPC服务
|
||||
|
||||
**RPC 权限不足**:
|
||||
```
|
||||
2024/01/15 10:30:15.123456 zbus-message-handler.go:84: [Info] [1] -Auth: rpc [user-get-info]
|
||||
```
|
||||
- 格式:`[Info] [连接序号] -Auth: rpc [服务名]`
|
||||
|
||||
### 定时任务日志
|
||||
|
||||
**定时任务执行**:
|
||||
```
|
||||
2024/01/15 10:30:00.123456 monitor.go:56: [Info] broadcast timer T:A 执行
|
||||
2024/01/15 10:30:05.123456 monitor.go:56: [Info] broadcast timer T:B 执行
|
||||
```
|
||||
- 格式:`[Info] broadcast timer 任务名 执行`
|
||||
- 来自monitor模块的定时任务执行日志
|
||||
|
||||
**定时任务订阅**:
|
||||
```
|
||||
2024/01/15 10:30:15.123456 zbus-message-handler.go:45: [1] cmd: timer T:A T:B
|
||||
```
|
||||
- 格式:`[连接序号] cmd: timer 任务列表`(debug级别)
|
||||
- 客户端订阅定时任务时记录
|
||||
|
||||
## Java 客户端日志
|
||||
|
||||
### 消息接收日志
|
||||
|
||||
**订阅消息**:
|
||||
```
|
||||
FINEST: topic[user.login]: {"userId":"12345","username":"张三"}
|
||||
```
|
||||
- 格式:`FINEST: topic[主题名]: 消息内容`
|
||||
- 记录接收到的订阅消息
|
||||
|
||||
**广播消息**:
|
||||
```
|
||||
FINEST: topic[topic-abc]: hello!
|
||||
```
|
||||
- 格式:`FINEST: topic[主题名]: 消息内容`
|
||||
|
||||
### 定时任务日志
|
||||
|
||||
**任务触发**:
|
||||
```
|
||||
FINEST: timer[T:A]:
|
||||
```
|
||||
- 格式:`FINEST: timer[任务名]: `
|
||||
|
||||
**任务执行完成**:
|
||||
```
|
||||
FINEST: timer [T:A] : elapsed time 15 ms
|
||||
```
|
||||
- 格式:`FINEST: timer [任务名] : elapsed time 耗时 ms`
|
||||
|
||||
### RPC 调用日志
|
||||
|
||||
**RPC响应**:
|
||||
```
|
||||
FINEST: rpc-back:[user.getInfo]: {"retcode":0,"result":"用户信息"}
|
||||
```
|
||||
- 格式:`FINEST: rpc-back:[服务名]: 响应内容`
|
||||
|
||||
**RPC错误**:
|
||||
```
|
||||
WARNING: rpc-back[user.getInfo] event accept error :{"retcode":500,"result":"服务错误"}
|
||||
```
|
||||
- 格式:`WARNING: rpc-back[服务名] event accept error :响应内容`
|
||||
|
||||
### 错误日志
|
||||
|
||||
**超时错误**:
|
||||
```
|
||||
SEVERE: timer [T:A] time out: 5 S
|
||||
```
|
||||
- 格式:`SEVERE: timer [任务名] time out: 超时时间 S`
|
||||
|
||||
**处理异常**:
|
||||
```
|
||||
WARNING: topic[user.login] event accept error :{"userId":"12345"}
|
||||
SEVERE: topic[user.login] event deal time out: 5 S, value: {"userId":"12345"}
|
||||
```
|
||||
- 格式:`WARNING: topic[主题名] event accept error :消息内容`
|
||||
- 格式:`SEVERE: topic[主题名] event deal time out: 超时时间 S, value: 消息内容`
|
||||
|
||||
## 日志分析
|
||||
|
||||
### 关键日志识别
|
||||
|
||||
**连接状态监控**:
|
||||
- `conn start:` - 新连接建立
|
||||
- `conn closed:` - 连接断开
|
||||
- `-Auth:` - 权限认证失败
|
||||
|
||||
**消息处理监控**:
|
||||
- `cmd: publish` - 消息发布(debug级别)
|
||||
- `cmd: subscribe` - 消息订阅
|
||||
- `cmd: rpc` - RPC调用
|
||||
- `no subscribe` - 服务离线
|
||||
|
||||
**Java客户端监控**:
|
||||
- `topic[主题名]:` - 消息接收
|
||||
- `timer[任务名]:` - 定时任务触发
|
||||
- `rpc-back:[服务名]:` - RPC响应
|
||||
- `time out:` - 超时错误
|
||||
- `event accept error` - 处理异常
|
||||
- `event deal time out` - 处理超时
|
||||
|
||||
**错误信息识别**:
|
||||
- `-Error:` - 系统错误
|
||||
- `Recovered:` - 异常恢复
|
||||
- `-Auth:` - 权限不足
|
||||
|
||||
### 监控要点
|
||||
|
||||
1. **连接稳定性**:关注连接建立和断开的频率
|
||||
2. **权限问题**:监控`-Auth:`日志,排查权限配置
|
||||
3. **服务可用性**:关注`no subscribe`日志,确保RPC服务正常
|
||||
4. **系统健康**:检查`-Error:`和`Recovered:`日志
|
||||
5. **客户端性能**:监控`time out:`日志,关注处理超时
|
||||
6. **消息处理**:观察`topic[主题名]:`日志,确保消息正常接收
|
||||
|
||||
## 日志轮转
|
||||
|
||||
### 手动轮转
|
||||
```bash
|
||||
# 重命名当前日志文件
|
||||
mv zhub.log zhub.log.$(date +%Y%m%d)
|
||||
|
||||
# 重启服务
|
||||
./zhub.sh restart
|
||||
```
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 常见问题
|
||||
|
||||
**1. 日志文件过大**
|
||||
- 定期清理旧日志文件
|
||||
- 调整日志级别为info
|
||||
|
||||
**2. 日志级别过高**
|
||||
- 生产环境建议使用info级别
|
||||
- 开发环境可使用debug级别
|
||||
|
||||
### 最佳实践
|
||||
|
||||
1. **定期检查**:关注错误和权限相关日志
|
||||
2. **监控连接**:观察连接建立和断开情况
|
||||
3. **服务状态**:确保RPC服务正常运行
|
||||
4. **日志轮转**:定期清理旧日志文件
|
||||
5. **级别设置**:生产环境使用info级别
|
||||
Reference in New Issue
Block a user