Files
shiran aa9f892a32 feat: 添加数据库集成、定时任务调度器和事件Hook体系
- 新增数据库配置项(DB_TYPE, DB_HOST, DB_PORT等),支持MySQL和PostgreSQL
- 集成GORM实现数据库连接和自动迁移功能
- 添加定时任务调度器(cmd/scheduler),基于robfig/cron实现秒级调度
- 实现事件Hook体系,支持同步/异步处理和优先级排序
- 更新构建脚本,编译server、cli、scheduler三个二进制文件
- 配置systemd服务管理定时任务调度器
- 重构项目结构,新增crontab和hooks目录模块
- 更新README文档,完善各组件使用说明和部署配置
2026-04-15 12:39:59 +08:00

340 lines
10 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.
# apiServer 微服务模板
基于 [CloudWego Hertz](https://github.com/cloudwego/hertz) 的 Go 微服务脚手架,集成 Nacos 服务注册/发现 + gRPC 客户端 + 访问日志上报(Redis → ES)+ 定时任务 + 事件 Hook 体系。
## 项目结构
```
├── apps/ # 业务处理层 (Handler)
├── cmd/
│ ├── main_program/ # 主程序入口 (HTTP 服务)
│ ├── cli_control/ # CLI 工具入口 (httplog 上报)
│ └── scheduler/ # 定时任务调度器 (独立进程)
├── crontab/ # 定时任务框架
│ └── tasks/ # 具体任务实现
├── hooks/ # 事件 Hook 体系
│ └── registers/ # Hook 注册入口
├── middleware/ # HTTP 中间件 (Recovery, AccessLog, CORS)
├── models/
│ ├── database/ # 数据库连接 & ORM 模型 (GORM)
│ └── request_models/ # 请求参数模型
├── proto/ # Protobuf 生成代码
├── routes/ # 路由定义
├── utils/
│ ├── httplog/ # HTTP 访问日志采集 & ES 上报
│ ├── logger/ # 日志工具 (logrus,主服务/定时任务分离)
│ ├── nacos/ # Nacos 服务注册/发现/配置
│ ├── redis_tools/ # Redis 连接 & 通用操作
│ ├── request/ # 请求绑定 & 统一响应
│ └── server_cli/ # gRPC 客户端
├── deploy/ # systemd 服务单元
├── start.sh / stop.sh / restart.sh / install.sh
├── .env.example # 环境变量示例
└── go.mod
```
## 快速开始
```bash
# 1. 复制配置
cp .env.example .env
# 编辑 .env 填入实际配置
# 2. 安装依赖
go mod tidy
# 3. 开发运行
go run ./cmd/main_program # HTTP 服务
go run ./cmd/cli_control # httplog 上报
go run ./cmd/scheduler # 定时任务调度器
# 4. 构建
go build -ldflags="-s -w" -o server ./cmd/main_program
go build -ldflags="-s -w" -o cli ./cmd/cli_control
go build -ldflags="-s -w" -o scheduler ./cmd/scheduler
```
## 模板使用步骤
1. 拉取该项目仓库
2. 复制 `.env.example``.env` 并修改配置
3. 全局替换 `apiServer_service` 为你的项目模块名
4. 修改 `go.mod` 中的 module 名称
5. 新建 Gitea 仓库,修改本地仓库地址
---
## 模块说明
### cmd/main_program — HTTP 主服务
启动 Hertz HTTP 服务,绑定路由和中间件,可选连接数据库、注册到 Nacos。
```bash
go run ./cmd/main_program
```
启动流程:加载 `.env` → 校验 `HOST`/`PORT` → 连接数据库(可选)→ 注册中间件 → 绑定路由 → Nacos 注册(可选)→ HTTP 监听 → 等待信号优雅关闭。
### cmd/cli_control — httplog 日志上报
独立后台进程,从 Redis 队列消费访问日志,批量写入 Elasticsearch。
```bash
go run ./cmd/cli_control
```
### cmd/scheduler — 定时任务调度器
独立进程运行定时任务,使用专用日志文件 `logs/cron_*.log`
```bash
go run ./cmd/scheduler # 常驻模式
go run ./cmd/scheduler list # 列出已注册任务
go run ./cmd/scheduler run-once # 立即执行所有任务一次
go run ./cmd/scheduler run 健康检查 # 立即执行指定任务
```
### crontab — 定时任务框架
基于 `robfig/cron` 的调度器,支持秒级 cron 表达式,内置 panic 恢复。
**新增任务三步走:**
```go
// 1. 在 crontab/tasks/ 下新建文件,实现 Task 接口
type MyTask struct{}
func (t *MyTask) Name() string { return "我的任务" }
func (t *MyTask) Spec() string { return "0 */10 * * * *" } // 每10分钟
func (t *MyTask) Run() {
logger.CronInfo("MyTask", "执行中...")
}
// 2. 在 crontab/tasks/register.go 注册
func RegisterTasks(scheduler *crontab.Scheduler) {
scheduler.Register(&HealthCheckTask{})
scheduler.Register(&MyTask{}) // 新增
}
// 3. 完成,scheduler 进程会自动调度
```
定时任务日志独立写入 `logs/cron_YYYYMMDD.log`,不与主服务日志混合。
### hooks — 事件 Hook 体系
发布-订阅模式的业务事件系统,支持同步/异步处理和优先级排序。
**触发事件:**
```go
import "apiServer_service/hooks"
hooks.DefaultManager().Trigger(ctx, hooks.EventType("order_paid"), &hooks.EventPayload{
UserID: 123,
Extra: map[string]any{"order_id": 456, "amount": 99.9},
})
```
**注册 Handler**
```go
// hooks/registers/register.go
func RegisterHooks(m *hooks.Manager) {
// 同步处理(按优先级顺序执行,阻塞直到完成)
m.Register(hooks.EventType("order_paid"), hooks.HandlerFunc(OnOrderPaid))
// 异步处理(不阻塞主流程)
m.RegisterAsync(hooks.EventType("order_paid"), hooks.HandlerFunc(SendNotification))
// 指定优先级(数值越大越先执行)
m.RegisterWithPriority(hooks.EventType("order_paid"), 10, hooks.HandlerFunc(DeductInventory))
}
func OnOrderPaid(ctx context.Context, event hooks.EventType, payload *hooks.EventPayload) error {
// 业务逻辑
return nil
}
```
**特性:**
| 能力 | 说明 |
|------|------|
| 同步执行 | `Register` — 按优先级顺序执行,阻塞调用方 |
| 异步执行 | `RegisterAsync` — goroutine 执行,不阻塞 |
| 优先级 | `RegisterWithPriority` — 数值越大越先执行 |
| panic 安全 | 异步 handler panic 不影响主流程 |
| 函数适配 | `HandlerFunc` 可直接用匿名函数注册 |
### middleware — HTTP 中间件
`cmd/main_program/routs.go` 中统一注册:
```go
r.Use(middleware.Recovery()) // panic 恢复
r.Use(middleware.AccessLog()) // 请求日志
r.Use(middleware.CORS()) // 跨域支持
```
### models/database — 数据库 (GORM)
支持 MySQL 和 PostgreSQL`DB_TYPE` 为空时跳过连接。
```go
import db "apiServer_service/models/database"
db.GetDB().Where("parent_id = ?", 0).Find(&groups)
db.GetDB().Create(&db.HostGroup{Name: "生产环境"})
```
新增模型在 `models/database/` 下定义结构体,在 `init.go``Migrate()` 中注册。
### utils/httplog — 访问日志采集
Hertz Tracer 实现,采集访问事件通过 Redis List 异步缓冲,由 `cli` 进程批量写入 ES。
```go
rdb := redis_tools.ConnectRedis()
tracer := httplog.NewRedisAccessLogTracer(rdb, "access_log", "my-service",
httplog.WithSkipPrefix("/health"),
httplog.WithMaxResponseBody(4096),
httplog.WithUserIDExtractor(func(c *app.RequestContext) uint { return 0 }),
)
h := server.Default(server.WithTracer(tracer))
```
### utils/redis_tools — Redis 工具
```go
redis_tools.SetCache("key", "value", 10*time.Minute)
val, _ := redis_tools.GetCache("key")
redis_tools.Del("key1", "key2")
redis_tools.Exists("key")
redis_tools.AddToList("queue", "item")
```
### utils/nacos — Nacos 服务注册/发现/配置
```go
nacos.RegisterService()
instance, _ := nacos.DiscoverService("user-service")
content := nacos.GetConfig("app.yaml", "DEFAULT_GROUP")
```
### utils/server_cli — gRPC 客户端
```go
err := server_cli.ReportVisit(token, note, ip, os, point, userId)
defer server_cli.CloseGrpcConn()
```
### utils/request — 请求绑定 & 统一响应
```go
request.BindRequestStruct(c, &req) // 失败自动 400
request.Success(c, data) // 200
request.BadRequest(c, "参数错误") // 400
request.Unauthorized(c, "未登录") // 401
request.NotFound(c, "不存在") // 404
request.Error(c, 500, "错误") // 自定义
request.FileResponse(c, path, name) // 文件下载
```
### routes — 路由定义
```go
func SetupRoutes(r *server.Hertz) {
r.Use(middleware.Recovery(), middleware.AccessLog(), middleware.CORS())
api := r.Group("/api")
{
routes.RegisterIndexRoutes(api)
// routes.RegisterUserRoutes(api) // 新增模块在此注册
}
}
```
---
## 生产部署
### 构建
```bash
go build -ldflags="-s -w" -o server ./cmd/main_program
go build -ldflags="-s -w" -o cli ./cmd/cli_control
go build -ldflags="-s -w" -o scheduler ./cmd/scheduler
```
### 首次安装(systemd 服务注册)
```bash
chmod +x install.sh start.sh stop.sh restart.sh server cli scheduler
sudo bash install.sh
```
### 日常运维
```bash
bash start.sh # 启动全部 (server + cli + scheduler)
bash stop.sh # 停止全部
bash restart.sh # 重启全部
```
单独管理:
```bash
systemctl status server # 主服务状态
systemctl status scheduler # 调度器状态
systemctl restart scheduler # 只重启调度器
journalctl -u server -f # 主服务实时日志
journalctl -u scheduler -f # 调度器实时日志
```
### systemd 服务特性
| 特性 | 说明 |
|------|------|
| 开机自启 | `install.sh` 执行后自动启用 |
| 崩溃自动重启 | `Restart=always`server 3s / cli 5s / scheduler 5s |
| 优雅关闭 | `SIGTERM`server 10s / scheduler 15s 超时 |
| 环境变量 | `EnvironmentFile` 加载 `.env` |
| 文件描述符 | `LimitNOFILE=65536` |
### 部署目录结构
```
/root/
├── server # HTTP 主服务
├── cli # httplog 上报
├── scheduler # 定时任务调度器
├── .env # 环境配置
├── deploy/
│ ├── server.service
│ ├── cli.service
│ └── scheduler.service
├── install.sh / start.sh / stop.sh / restart.sh
└── logs/
├── server.out # 主服务输出
├── cli.out # httplog 输出
├── scheduler.out # 调度器输出
└── cron_*.log # 定时任务专用日志
```
## 内置功能清单
- Hertz HTTP 框架 + 路由分组
- Recovery / AccessLog / CORS 中间件
- 统一 JSON 响应格式 + 参数绑定校验
- GORM 数据库(MySQL / PostgreSQL,自动迁移)
- 事件 Hook 体系(同步/异步、优先级、发布-订阅)
- 定时任务调度器(秒级 cron、独立进程、专用日志)
- HTTP 访问日志采集 → Redis 缓冲 → ES 批量上报
- Redis 工具(单例连接池)
- Nacos 服务注册、发现、配置管理
- gRPC 客户端(连接复用)
- 彩色日志 + 文件日志(主服务/定时任务分离)
- 优雅关闭 (Graceful Shutdown)
- systemd 服务管理(开机自启 + 崩溃自动重启)