Documentation
¶
Overview ¶
Package bootstrap 定义组件化启动编排。
本文件保留组件接口与轻量组件;重量级组件(metrics/tracing/NNS) 位于嵌套 module:github.com/oekit/bootstrap/obs 与 github.com/oekit/bootstrap/nacos,以 BootstrapperOption 注入。
Package bootstrap 提供 oekit 微服务的启动编排——纯编排壳,零重依赖。
职责:App 生命周期(ctx/资源注册/后台任务)、组件化 Bootstrapper、 信号监听与优雅关闭、WorkerManager。
组件化接入 ¶
重量级能力以嵌套 module 形式提供,经 BootstrapperOption 函数注入:
import (
"github.com/oekit/bootstrap"
"github.com/oekit/bootstrap/nacos" // Nacos/NNS 注册(按需)
"github.com/oekit/bootstrap/obs" // Prometheus/OTel(按需)
)
b, _ := bootstrap.New(
bootstrap.WithServiceName("my-service"),
nacos.WithNNS(cfg.Nacos, cfg.Port, cfg.DepServices),
obs.WithMetrics(),
obs.WithTracing(tracing.Config{Endpoint: "otel:4317"}),
)
_ = b.Run(userFn)
第三方集成实现 Component 接口后经 WithComponent 注入即可。
多 Server 场景 ¶
启动多个 server,通过 AddResource 注册关闭函数(逆序执行):
app.AddResource("hertz", func(ctx context.Context) error { return h.Shutdown(ctx) })
BeforeServe(引擎启动前) ¶
WithBeforeServe(fn) 在组件初始化后、userFn 之前执行;失败中止启动。 用于 listener fd 收养、pid 交接等「必须在 serve 前」的动作。bootstrap 不接管 listener——自备时用 server.WithListener(ln) 即可。
attach 模式(NewApp) ¶
bootstrap.NewApp(mgr *shutdown.Manager) 是 **attach 模式**入口:只把 app-lifecycle 四阶段挂到调用方的 shutdown.Manager 上,**不接管信号与 server**——不调用 signal.Notify、不调用 h.Spin,SIGINT/SIGTERM 与服务 启停由宿主负责。适合宿主已有 Spin/OnShutdown 生命周期(如 hertz), 只想补上「ctx 取消 + 资源关闭 + 后台任务 drain」的场景:
teardown := shutdown.New(30 * time.Second)
app := bootstrap.NewApp(teardown)
app.GoBackground("outbox", outbox.Run)
app.AddResource("redis", func(ctx context.Context) error { return rdb.Close() })
h.OnShutdown = append(h.OnShutdown, func(ctx context.Context) {
teardown.Shutdown(ctx)
})
h.Spin()
四阶段 job 名为 app-lifecycle:{cancel,drain,close,wait},按注册顺序在 mgr.Shutdown 时执行;caller 自己 mgr.Add 的任务同样按注册顺序插入: NewApp 之前 Add 的排在四阶段前,之后 Add 的排在四阶段后。AddResource 的 closer 在 close 阶段逆序释放;GoBackground 的 goroutine 在 wait 阶段 被等待退出。
Index ¶
- type App
- func (a *App) AddResource(name string, closer func(context.Context) error)
- func (a *App) Context() context.Context
- func (a *App) GoBackground(name string, fn func(ctx context.Context))
- func (a *App) IsReady() bool
- func (a *App) Ready()
- func (a *App) ReadyChan() <-chan struct{}
- func (a *App) RequestShutdown()
- func (a *App) SetWaitTimeout(d time.Duration)
- type Bootstrapper
- type BootstrapperOption
- func WithBeforeServe(fn func() error) BootstrapperOption
- func WithComponent(c Component) BootstrapperOption
- func WithServiceName(name string) BootstrapperOption
- func WithShutdownHook(name string, hook func(ctx context.Context) error) BootstrapperOption
- func WithShutdownTimeout(d time.Duration) BootstrapperOption
- type Component
- type ServiceNameAware
- type ShutdownHookComponent
- type WorkerManager
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type App ¶
type App struct {
// contains filtered or unexported fields
}
App 是应用生命周期管理器,统一管理资源注册、后台任务和优雅关闭。
用法:
app := bootstrap.NewApp(shutdownMgr)
app.AddResource("db", db.Close)
app.GoBackground("poller", func(ctx context.Context) { ... })
// shutdown 时自动按注册逆序关闭所有资源和等待后台任务退出
func NewApp ¶
NewApp 创建应用生命周期管理器,挂到调用方传入的 lifecycle.Manager 上(attach 模式)。
契约:NewApp 只做生命周期编排,**不接管信号与 server**——不调用 signal.Notify、不调用 h.Spin/RunServer;SIGINT/SIGTERM 与服务启停 一律由宿主(如 hertz.Server + OnShutdown)负责,宿主停机回调里再调 mgr.Shutdown 即可。
四阶段顺序语义:NewApp 立即向 mgr 注册 app-lifecycle:{cancel,drain,close,wait} 四个 job;lifecycle.Manager 按 **注册顺序**执行,因此调用方在 NewApp **之前** mgr.Add 的任务先于四阶段执行, 在 NewApp **之后** mgr.Add 的任务排在四阶段之后。应用自身资源请用 AddResource/GoBackground(分别落在 close / wait 阶段),不要在 NewApp 之后 直接 mgr.Add(会排到 wait 之后,错过 close 窗口)。
func (*App) AddResource ¶
AddResource 注册需要在关闭时释放的资源。 name 用于日志标识,closer 是关闭函数。
func (*App) GoBackground ¶
GoBackground 启动一个带 panic recovery 的后台 goroutine。 关闭时通过 ctx 取消信号通知退出,并等待所有后台任务完成。
func (*App) Ready ¶ added in v0.6.0
func (a *App) Ready()
Ready 标记应用就绪(server 已监听、健康检查通过)。幂等,并发安全。 延迟注册型组件(如 bootstrap/nacos 的 NNS 组件)在收到就绪信号后 才执行注册——服务须在 server 就绪后调用本方法,否则不会进入注册中心。
func (*App) ReadyChan ¶ added in v0.6.0
func (a *App) ReadyChan() <-chan struct{}
ReadyChan 返回就绪信号;未 Ready 时阻塞,已 Ready 立即返回。
func (*App) RequestShutdown ¶
func (a *App) RequestShutdown()
RequestShutdown 请求应用进入关闭流程:取消根 context,解除 userFn 中 `<-app.Context().Done()` 的阻塞,使其返回并触发 lifecycle.Manager 的优雅 关闭序列。幂等;在关闭序列中再次调用是安全的(cancel 本身幂等)。 典型用途见 lifecycle.App.RequestShutdown。
func (*App) SetWaitTimeout ¶
SetWaitTimeout 设置 GoBackground goroutine 的 drain 超时。 超时后 wg.Wait 被跳过,日志警告仍在运行的 goroutine 数量。 默认 30s;传 0 禁用超时(无限等待,仅在确信所有 goroutine 会自行退出时使用)。
type Bootstrapper ¶
type Bootstrapper struct {
// contains filtered or unexported fields
}
Bootstrapper 是组件化应用编排器。
通过函数选项配置启动组件;重量级集成(Nacos/NNS、Prometheus/OTel) 位于嵌套 module,以 Option 函数形式注入,根包保持零重依赖:
b, err := bootstrap.New(
bootstrap.WithServiceName("my-service"),
nacos.WithNNS(nacosCfg, 8080, deps), // github.com/oekit/bootstrap/nacos
obs.WithMetrics(), // github.com/oekit/bootstrap/obs
obs.WithTracing(tracing.Config{...}),
)
if err != nil { log.Fatal(err) }
b.Run(func(app *bootstrap.App) error {
h := server.New(server.WithHostPorts(":8080"))
app.AddResource("hertz", h.Shutdown)
return h.Run()
})
本地开发和测试场景可不添加任何外部依赖组件。
func (*Bootstrapper) AddComponent ¶
func (b *Bootstrapper) AddComponent(c Component)
AddComponent 追加启动组件(动态注入)。 导出以支持嵌套 module 与第三方实现注入,与 WithComponent 等价。
func (*Bootstrapper) Run ¶
func (b *Bootstrapper) Run(userFn func(*App) error) error
Run 启动服务,阻塞直到收到关闭信号或 userFn 返回。
执行顺序:
创建 lifecycle.Manager 和 App
按注册顺序初始化所有 Component 2.5 BeforeServe 钩子(引擎启动前的定制准备)
调用 userFn(app) 启动用户服务——server 就绪后应调用 app.Ready() 触发就绪门:延迟注册型组件(如 bootstrap/nacos 的 NNS 组件, nacos/v0.3.0 起)在收到就绪信号后才注册,且关停时反注册先于 server 关闭执行(对齐 go-kratos Stop 语义)
**就绪门漏接的可观测性**(bootstrap#33):漏调 app.Ready() 时服务 不会注册到注册中心——推荐经 hertz/kitex RunServer 的 WithOnReady 胶水触发;自建启动骨架(直接 h.Spin())必须自己调。漏接时 bootstrap/nacos 的就绪门看门狗会在超时后打 ERROR 日志点明此事, 并可用 nacos 组件的 RegistrationState() 查询注册状态。
监听 SIGINT/SIGTERM
优雅关闭
type BootstrapperOption ¶
type BootstrapperOption func(*Bootstrapper)
BootstrapperOption 配置 Bootstrapper。
func WithBeforeServe ¶ added in v0.5.4
func WithBeforeServe(fn func() error) BootstrapperOption
WithBeforeServe 注册「引擎启动前」钩子:在组件初始化之后、userFn 之前 按注册顺序执行;任一返回 error 则中止启动(已初始化组件走优雅回滚)。
典型用途:零断点重启的 listener fd 收养(SCM_RIGHTS → restart.Adopt)、 pid 文件交接、启动前配置校验。这些动作必须发生在「进程已知自己角色」 之后、「HTTP 引擎开始 serve」之前——userFn 是引擎跑起来之后的逻辑, 装不下这段。
调用方自备 listener 时也可不经过本钩子,直接:
h := server.New(server.WithListener(ln), ...)
bootstrap 不接管 listener 的创建/收养,只提供时机保证。
func WithComponent ¶
func WithComponent(c Component) BootstrapperOption
WithComponent 添加自定义组件——第三方集成注入的标准入口。
实现 Component 接口的任意类型都可通过本方法接入启动编排; 嵌套 module(bootstrap/nacos、bootstrap/obs)的 WithXxx 选项 内部即委托此方法。
func WithServiceName ¶
func WithServiceName(name string) BootstrapperOption
WithServiceName 设置服务名称(必填)。
func WithShutdownHook ¶
func WithShutdownHook(name string, hook func(ctx context.Context) error) BootstrapperOption
WithShutdownHook 添加自定义关闭钩子。
func WithShutdownTimeout ¶
func WithShutdownTimeout(d time.Duration) BootstrapperOption
WithShutdownTimeout 设置优雅关闭超时,默认 10 秒。
type Component ¶
type Component interface {
// Name 返回组件标识,用于日志。
Name() string
// Init 执行组件初始化,可通过 app 和 mgr 注册资源和关闭钩子。
Init(ctx context.Context, app *App, mgr *lifecycle.Manager) error
}
Component 是可插拔的启动组件接口。 每个组件负责一项启动任务(如指标注册、追踪初始化、服务注册等), 并可通过 mgr 注册关闭钩子。
type ServiceNameAware ¶
type ServiceNameAware interface {
SetServiceName(name string)
}
ServiceNameAware 需要感知服务名的组件实现此接口; New() 在应用完全部选项后统一回填(与 WithServiceName 的调用顺序无关)。 嵌套 module 中的组件实现它即可参与回填,根包无需感知具体组件类型。
type ShutdownHookComponent ¶
ShutdownHookComponent 通用关闭钩子组件,用于注册自定义资源释放逻辑。
type WorkerManager ¶
type WorkerManager struct {
// contains filtered or unexported fields
}
WorkerManager 管理一组周期性后台任务。
用法:
wm := bootstrap.NewWorkerManager(ctx)
wm.AddTicker("timeout-checker", 60*time.Second, func(ctx context.Context) {
buildSvc.CheckBuildTimeout(ctx)
deploySvc.CheckDeployTimeout(ctx)
})
wm.AddTicker("metrics-reporter", 30*time.Second, func(ctx context.Context) {
common.ReportQueueMetrics(ctx)
})
// ctx 取消时所有 worker 自动退出
func NewWorkerManager ¶
func NewWorkerManager(ctx context.Context) *WorkerManager
NewWorkerManager 创建后台任务管理器。 ctx 取消或 Close() 调用时所有任务自动退出。
func (*WorkerManager) AddOnce ¶
func (w *WorkerManager) AddOnce(name string, fn func(ctx context.Context))
AddOnce 注册一个一次性任务,在后台执行。
func (*WorkerManager) AddTicker ¶
func (w *WorkerManager) AddTicker(name string, interval time.Duration, fn func(ctx context.Context))
AddTicker 注册一个周期性任务,按 interval 间隔执行 fn。 ctx 取消时自动退出。
func (*WorkerManager) Close ¶
func (w *WorkerManager) Close()
Close 取消 context、阻止新任务注册并等待所有已启动的任务退出。 多次调用是安全的。