appbox

package module
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 12, 2026 License: MIT Imports: 21 Imported by: 0

README

go-blackbox

go-blackbox 是一个供其他 Go 项目引用的组件化 Web 脚手架依赖库。项目通过根包 appbox 的 Builder 统一装配 Web、数据源、缓存、定时任务、日志、静态资源和启动钩子,同时提供 MongoDB、RabbitMQ、JWT、RSA、邮件、构建脚本等独立能力。

本仓库有意不提供固定业务 main 包。依赖方在自己的项目中创建入口程序,通过 Builder 按需启用 Web、数据库和中间件组件。

当前状态

  • Go 版本:1.20
  • Module:github.com/Connorig/go-blackbox
  • 根包名:appbox
  • 默认分支:main
  • 配置方式:Viper + TOML + 环境变量
  • Web 框架:Iris v12
  • 数据库:PostgreSQL + GORM
  • 日志:Zap + file-rotatelogs
  • 许可证:MIT

v1.2.0 开始,Go Module 地址统一为 github.com/Connorig/go-blackbox。旧的 github.com/Domingor/go-blackbox 引用需要更新后再执行 go mod tidy

项目已有较完整的组件雏形,但部分组件仍存在初始化、错误处理、测试隔离和配置一致性问题。新功能开发前请先阅读 项目分析与升级基线

各功能模块的实施顺序、当前状态和验收目标见 功能优化路线图

能力清单

能力 主要位置 当前接入方式 状态说明
Iris Web 服务 server/webiris EnableWeb / EnableWebWithConfig 已完成首轮生命周期与错误处理升级
PostgreSQL / GORM server/datasource EnableDb 已接入 Builder,仅支持 PostgreSQL
Redis 缓存 server/cache EnableCache 已接入 Builder,初始化逻辑待修复
MongoDB server/mongodb EnableMongoDB 客户端已实现,Builder 开关待修复
Cron 定时任务 server/cronjobs SetSeeds / InitCronJob SetSeeds 注册任务后自动启用 Cron
Zap 分级日志 server/zaplog InitLog 已接入 Builder,日志目录需提前准备
Web 生命周期回调 根包 Builder BeforeSetup / AfterSetup 分别在 Web 启动前和 Ready 后执行
静态资源服务 static_server/webiris EnableStaticSource 已接入 Builder
配置加载 server/apploader LoadConfig 支持配置文件和环境变量,错误传递待完善
RabbitMQ 重试队列 server/rabbitmqretry/rabbitmq 独立调用 尚未接入 Builder
JWT apputils/apptoken 独立调用 支持签发、验证、刷新,密钥配置待改造
RSA apputils/rsa 独立调用 支持密钥生成、PEM 与 Base64 处理
邮件发送 server/email 独立调用 当前固定使用 SMTP 465 端口
构建脚本生成 buildscript Generate 可生成 build.shDockerfile
前端代码 独立维护 未接入 v1.2.0 已移除不可构建的 UI 代码片段

启动流程

调用 appbox.New().Start(...) 后,当前启动顺序如下:

  1. 执行 Builder 回调,读取配置并标记需要启用的组件。
  2. 初始化 Zap 日志;未显式配置时使用默认日志配置。
  3. 按顺序初始化 PostgreSQL、Redis、MongoDB,并将实例写入简单 IOC 容器。
  4. 执行 BeforeSetup 注册的 Web 启动前回调。
  5. 在 goroutine 中启动 Iris Web 服务并等待 Ready。
  6. 执行 AfterSetup 注册的 Web Ready 后回调。
  7. 执行 SetSeeds 注册的 Cron 任务创建函数,并启动 Cron 调度器。
  8. 主 goroutine 等待 SIGINTSIGTERMshutdown.Exit(...)
  9. 收到退出请求后,在统一关闭期限内按逆序停止业务关闭钩子、Cron、Web 运行 Context、MongoDB 和 PostgreSQL。

Web 服务会在 Iris 路由构建完成且 TCP Listener 真正进入 Serve 阶段后发布 Ready 信号。未启用 Web 时不会执行 BeforeSetup 和 AfterSetup;SetSeeds 不依赖 Web,可用于 Cron-only 服务。

下游 Worker 或其他自定义资源可以通过 OnShutdown 注册关闭函数,并使用 WithShutdownTimeout 设置全部资源共享的关闭期限。关闭函数必须响应传入 Context,且不得记录敏感连接信息。

目录结构

.
├── application.builder.go       # 组件启用与配置入口
├── application.starter.go       # 应用启动、服务初始化和退出等待
├── apputils/                    # JWT、RSA、GORM 条件、通用工具
├── buildscript/                 # Dockerfile / build.sh 模板生成器
├── seed/                        # 生命周期回调函数类型与兼容执行入口
├── server/
│   ├── apploader/               # Viper 配置加载
│   ├── cache/                   # Redis + 本地 TinyLFU 缓存
│   ├── cronjobs/                # Cron 调度器
│   ├── datasource/              # PostgreSQL / GORM
│   ├── email/                   # SMTP 邮件发送
│   ├── mongodb/                 # MongoDB 客户端封装
│   ├── rabbitmqretry/           # RabbitMQ 消息与失败重试
│   ├── shutdown/                # 信号监听与全局 Context
│   ├── webiris/                 # Iris Web 服务封装
│   └── zaplog/                  # Zap 日志和日志轮转
├── simpleioc/                   # 基于反射的全局实例容器
├── static_/                     # Go embed 静态资源示例
├── version/                     # 构建版本信息注入与输出
└── config.toml                  # 示例配置,禁止直接用于生产环境

快速开始

1. 环境准备

安装 Go 1.20 或兼容版本,然后下载依赖:

go mod download

当前日志实现会写入 <日志目录>/zap/,启动前需要确保目录存在:

mkdir -p zap
2. 创建入口程序

可以在独立应用中引用本仓库,也可以在仓库内新增 cmd/demo/main.go

package main

import (
	"context"
	"log"

	appbox "github.com/Connorig/go-blackbox"
	"github.com/kataras/iris/v12"
)

func main() {
	err := appbox.New().Start(func(_ context.Context, builder *appbox.ApplicationBuild) error {
		// 当前示例仅启用日志和 Web,避免依赖外部数据库、中间件服务。
		builder.
			InitLog(".", "info").
			EnableWeb(appbox.TimeFormat, ":9528", "info", func(app *iris.Application) {
				app.Get("/health", func(ctx iris.Context) {
					if _, err := ctx.WriteString("ok"); err != nil {
						log.Printf("write health response failed: %v", err)
					}
				})
			})

		return nil
	})
	if err != nil {
		log.Fatalf("start application failed: %v", err)
	}
}

启动后访问:

GET http://127.0.0.1:9528/health

使用 Ctrl+C 发送退出信号。

需要配置优雅关闭超时时,可使用结构化入口:

builder.EnableWebWithConfig(webiris.Config{
	Address:         ":9528",
	TimeFormat:      appbox.TimeFormat,
	LogLevel:        "info",
	ShutdownTimeout: 15 * time.Second,
}, registerRoutes)

配置加载

Builder 可通过 LoadConfig 使用 Viper 读取配置文件:

var cfg AppConfig

if err := builder.LoadConfig(&cfg, func(loader apploader.Loader) {
	loader.SetConfigFileSearcher("config", ".")
}); err != nil {
	return fmt.Errorf("load application config: %w", err)
}

建议业务项目定义自己的配置结构,并使用 mapstructure 标签与 Viper 对齐。仓库内置的 apploader.Configuration 只覆盖 Web、数据库、Redis 和日志的一部分字段,尚未覆盖 RabbitMQ 与 MongoDB。

config.toml 目前包含开发环境连接示例。使用前必须替换主机、账号和密码;生产密钥、数据库密码、SMTP 授权码等敏感信息应通过密钥管理系统或环境变量注入,不应提交到仓库。

组件访问

启用并成功初始化组件后,可以通过根包提供的访问函数获取全局实例:

db := appbox.GormDb()
redisCache := appbox.RedisCache()
mongoClient := appbox.MongoDb()
cron := appbox.CronJobSingle()
globalCtx := appbox.GlobalCtx()

调用前必须确认对应组件已经启用且初始化成功。当前 IOC 容器不会为缺失实例返回结构化错误,直接使用空实例可能产生 panic,后续将改为显式依赖和错误返回。

静态资源

static_ 使用 embed.FS 嵌入静态文件:

builder.
	EnableStaticSource(static_.StaticFile).
	EnableWeb(appbox.TimeFormat, ":9528", "info", registerRoutes)

Iris 会将嵌入文件映射到 /。如果同时注册根路径路由,需要提前确认路由优先级和 SPA fallback 行为。

测试说明

当前测试同时包含单元测试、真实中间件集成测试和人工演示用例。以下测试依赖外部环境或会长时间阻塞:

  • application.builder_test.go:真实 Web 集成测试,默认跳过;设置 GO_BLACKBOX_WEB_INTEGRATION=1 后执行。
  • server/mongodb/*_test.goserver/mongdbdemo/*_test.go:连接真实 MongoDB。
  • server/rabbitmqretry/*_test.go:连接真实 RabbitMQ,最长等待数分钟。
  • server/email/index_test.go:连接真实 SMTP 并发送邮件。
  • 部分 Cron、IOC 测试包含固定 Sleep

因此,在完成测试分层和隔离前,不建议无条件执行 go test ./...。优先执行无外部依赖且可快速结束的目标测试,例如:

go test ./seed
go test ./simpleioc -run 'TestName|TestName2'

后续应通过 build tag、环境开关、容器化依赖或 mock 将集成测试与单元测试分离。

构建与部署

buildscript.Generate(...) 可以生成:

  • build.sh:读取 Git 标签、Commit 和构建时间,构建或推送镜像。
  • Dockerfile:多阶段构建 Go 服务,可选构建 UI,并通过 ldflags 注入版本信息。

推送 v* Tag 时,GitHub Actions 会校验 Module 地址、执行全包编译检查、生命周期单元测试和 go vet,验证通过后自动创建 GitHub Release。当前仓库作为依赖库发布,不再要求根目录存在 Dockerfile。

开发约定

  • 每次修改前必须阅读并遵守仓库根目录的 AGENTS.md
  • 所有业务功能返回的 error 必须被处理,不允许静默丢弃。
  • 错误日志应包含功能点、关键上下文和原始错误,包装错误时使用 %w 保留错误链。
  • 不在日志中输出密码、Token、私钥、完整连接串等敏感信息。
  • 关键功能注释需要说明用途、输入约束、执行时机、失败行为和资源释放方式。
  • 新增外部依赖能力时,需要同时提供超时、取消、重试边界、健康检查和关闭逻辑。
  • 新增功能必须补充可重复执行的测试,真实外部服务测试与单元测试分离。

后续优化

已确认的问题、风险等级和建议实施顺序见 docs/PROJECT_ANALYSIS.md。建议首先处理启动生命周期、敏感配置、测试隔离和错误处理,再扩展新业务功能。

Documentation

Index

Constants

View Source
const AfterSecond = time.Second

AfterSecond 是 Web 启动结果的观察窗口,用于同步捕获端口占用等快速失败。 该常量为兼容现有调用保留,后续会迁移为可配置的启动超时。

View Source
const (
	// TimeFormat 日期格式
	TimeFormat = webiris.DefaultTimeFormat
)

Variables

This section is empty.

Functions

func CronJobSingle

func CronJobSingle() *cron.Cron

CronJobSingle 获取定时任务执行器实例

func GlobalCtx

func GlobalCtx() *simpleioc.GlobalContext

GlobalCtx 获取context上下文

func GormDb

func GormDb() *gorm.DB

GormDb 获取操作数据库-Gorm实例

func MongoDb

func MongoDb() *mongodb.Client

MongoDb 获取MongoDB实例

func RedisCache

func RedisCache() cache.Rediser

RedisCache 获取Redis缓存实例

Types

type Application

type Application interface {
	// Start 执行 Builder 回调、初始化启用的组件,并等待应用退出信号。
	Start(builder func(ctx context.Context, builder *ApplicationBuild) error) error
}

Application 定义脚手架应用的启动入口。

func New

func New() Application

New 返回进程级 Application 单例。 当前版本保持历史单例语义,重复配置和可重入能力将在生命周期模块中统一优化。

type ApplicationBuild

type ApplicationBuild struct {

	//=========================================》 启动标识
	// 是否启动定时服务,在enableCronjob后为true,会自动start(),即开始调用定时Cron表达式函数
	IsRunningCronJob bool

	// 静态服务文件系统
	StaticFs http.FileSystem
	// 是否开启web
	IsEnableWeb bool
	// 是否开启数据库
	IsEnableDB bool
	// 是否开启redis
	IsEnableCache bool
	// 是否开始RabbitMq
	IsEnableRabbitMq bool
	// 是否开始定时任务
	IsEnableCronTask bool
	// 是否开启mongoDB
	IsEnableMongoDB bool
	// 是否开启静态服务文件
	IsEnableStaticFileServe bool
	// 是否开启日志zapLogs
	IsEnableZapLogs bool
	// contains filtered or unexported fields
}

ApplicationBuild 保存依赖项目通过 Builder 选择的组件配置和启用状态。 字段由各 Enable 方法写入,并由 Application.Start 在单线程启动阶段读取。

func (*ApplicationBuild) AfterSetup

func (app *ApplicationBuild) AfterSetup(setupFuncs ...SetupFunc) *ApplicationBuild

AfterSetup 注册 Web Ready 后回调。 回调仅在启用 Web 且发布 Ready 后执行,任一回调失败都会停止已启动的 Web 服务。

func (*ApplicationBuild) BeforeSetup

func (app *ApplicationBuild) BeforeSetup(setupFuncs ...SetupFunc) *ApplicationBuild

BeforeSetup 注册 Web 启动前回调。 回调仅在启用 Web 时执行,适合完成路由依赖检查、内存数据预热等启动前准备。

func (*ApplicationBuild) EnableCache

func (app *ApplicationBuild) EnableCache(redConfig cache.RedisOptions) *ApplicationBuild

EnableCache 启动缓存

func (*ApplicationBuild) EnableDb

func (app *ApplicationBuild) EnableDb(dbConfig *datasource.PostgresConfig, models ...interface{}) *ApplicationBuild

EnableDb 启动数据库操作对象

func (*ApplicationBuild) EnableMongoDB

func (app *ApplicationBuild) EnableMongoDB(dbConfig *mongodb.MongoDBConfig) *ApplicationBuild

EnableMongoDB 配置MongoDB客户端

func (*ApplicationBuild) EnableStaticSource

func (app *ApplicationBuild) EnableStaticSource(file embed.FS) *ApplicationBuild

EnableStaticSource 加载web服务静态资源文件

func (*ApplicationBuild) EnableWeb

func (app *ApplicationBuild) EnableWeb(timeFormat, port, logLevel string, components webiris.PartyComponent) *ApplicationBuild

EnableWeb 启动Web服务

func (*ApplicationBuild) EnableWebWithConfig

func (app *ApplicationBuild) EnableWebWithConfig(config webiris.Config, components webiris.PartyComponent) *ApplicationBuild

EnableWebWithConfig 使用结构化配置启动 Web 服务。 该方法在保留 EnableWeb 兼容性的同时,允许依赖方设置优雅关闭超时等新增参数。 配置校验错误会在 Application.Start 阶段通过 WebIris.Run 返回并记录日志。

func (*ApplicationBuild) InitCronJob

func (app *ApplicationBuild) InitCronJob() *ApplicationBuild

InitCronJob 初始化定时任务对象,存放入IOC

func (*ApplicationBuild) InitLog

func (app *ApplicationBuild) InitLog(outDirPath, level string) *ApplicationBuild

InitLog 初始化自定义日志

func (*ApplicationBuild) LoadConfig

func (app *ApplicationBuild) LoadConfig(configStruct interface{}, loaderFun func(apploader.Loader)) error

LoadConfig 加载配置文件、环境变量值

func (*ApplicationBuild) OnShutdown

func (app *ApplicationBuild) OnShutdown(name string, shutdownFunc ShutdownFunc) *ApplicationBuild

OnShutdown 注册应用退出时执行的资源关闭函数。 注册顺序应与资源初始化顺序一致,Application 会在启动失败或退出时按逆序执行。 空名称或 nil 函数会被忽略,避免把不可定位或不可执行的关闭任务带入运行阶段。

func (*ApplicationBuild) SetSeeds

func (app *ApplicationBuild) SetSeeds(seedFuncs ...SetupFunc) *ApplicationBuild

SetSeeds 注册 Cron 定时任务创建回调。 至少注册一个有效回调时会自动启用 Cron,调用方无需再显式调用 InitCronJob。

func (*ApplicationBuild) SetupToken

func (app *ApplicationBuild) SetupToken(AMinute, RHour time.Duration, TokenIssuer string) *ApplicationBuild

SetupToken 设置系统token有效期

func (*ApplicationBuild) WithShutdownTimeout

func (app *ApplicationBuild) WithShutdownTimeout(timeout time.Duration) *ApplicationBuild

WithShutdownTimeout 设置应用关闭的总超时时间。 非正数恢复为默认值,避免错误配置造成无限等待或关闭流程立即超时。

type ApplicationBuilder

type ApplicationBuilder interface {
	// EnableWeb 使用兼容参数配置 Iris Web 服务。
	EnableWeb(timeFormat, port, logLevel string, components webiris.PartyComponent) *ApplicationBuild
	// EnableWebWithConfig 使用结构化配置启用 Iris Web 服务。
	EnableWebWithConfig(config webiris.Config, components webiris.PartyComponent) *ApplicationBuild
	// EnableDb 配置 PostgreSQL、GORM 和需要迁移的 Model。
	EnableDb(dbConfig *datasource.PostgresConfig, models ...interface{}) *ApplicationBuild
	// EnableCache 配置 Redis 缓存客户端。
	EnableCache(redConfig cache.RedisOptions) *ApplicationBuild
	// LoadConfig 通过调用方提供的 Loader 配置读取目标结构体。
	LoadConfig(configStruct interface{}, loaderFun func(apploader.Loader)) error
	// InitLog 初始化脚手架全局日志。
	InitLog(outDirPath, level string) *ApplicationBuild
	// EnableMongoDB 配置 MongoDB 客户端。
	EnableMongoDB(dbConfig *mongodb.MongoDBConfig) *ApplicationBuild
	// InitCronJob 显式启用 Cron 调度器,保留给未使用 SetSeeds 的兼容场景。
	InitCronJob() *ApplicationBuild
	// SetupToken 配置 JWT 有效期和签发者。
	SetupToken(AMinute, RHour time.Duration, TokenIssuer string) *ApplicationBuild
	// EnableStaticSource 配置 Web 根路径使用的嵌入式静态资源。
	EnableStaticSource(file embed.FS) *ApplicationBuild
	// BeforeSetup 注册 Web 启动前回调。
	BeforeSetup(setupFuncs ...SetupFunc) *ApplicationBuild
	// AfterSetup 注册 Web Ready 后回调。
	AfterSetup(setupFuncs ...SetupFunc) *ApplicationBuild
	// SetSeeds 注册 Cron 任务创建回调并自动启用调度器。
	SetSeeds(seedFuncs ...SetupFunc) *ApplicationBuild
	// OnShutdown 注册应用退出时需要逆序执行的资源关闭函数。
	OnShutdown(name string, shutdownFunc ShutdownFunc) *ApplicationBuild
	// WithShutdownTimeout 设置全部资源共享的应用关闭期限。
	WithShutdownTimeout(timeout time.Duration) *ApplicationBuild
}

ApplicationBuilder 定义依赖项目可选择的组件和生命周期注册能力。

type SetupFunc

type SetupFunc = seed.SeedFunc

SetupFunc 是应用生命周期回调函数。 脚手架负责传入运行 Context、按注册顺序调用,并在错误发生时终止后续启动流程。

type ShutdownFunc

type ShutdownFunc func(context.Context) error

ShutdownFunc 定义应用退出时执行的资源关闭函数。 关闭函数必须响应传入 Context 的超时或取消,并返回资源释放过程中发生的错误。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL