前言
如果系统中基础公共资源比较多,并且每个基础资源都有自己特定的构造和初始化,启动方法,有些简单有些复杂,有些基础公共资源之间还可能存在依赖,所以就要设计基础资源管理程序来管理基础资源的启动过程。
基础资源上下文结构体
- 首先定义一个基础资源上下文结构体,用于管理基础资源启动过程上下文依赖资源的传递,(结构化设计和编程实例),定义一个启动器接口,抽象和定义了各种资源加载和启动的阶段,各种基础资源实现这个启动器接口,完成资源自身的启动逻辑
// 资源启动器,每个应用都少不了依赖其他资源,比如数据库,缓存,消息中间件等等服务
// 启动器实现类, 不需要实现所有方法,只要实现对应的阶段方法即可,可以嵌入BaseStarter
// 通过实现资源启动器接口和资源启动注册器,友好的管理这些资源的初始化,安装,启动和停止
// Starter对象注册器,所有需要在系统启动时需要实例化和运行的逻辑,都可以实现这个接口
// 只有Start方法才能被阻塞,如果是阻塞Start(),同时StartBlocking()要返回true
// 基础公共资源上下结构体
type StartContext map[string]interface{}
// 基础资源启动接口
type Starter interface {
// 1. 系统启动,初始化一些资源,准备资源放在这里运行
Init(StartContext)
// 2. 系统基础资源的安装,所有启动所需要的条件可以放在这里
SetUp(StartContext)
// 3. 启动基础资源,达到可以使用的状态
Start(StartContext)
// 启动器启动的时候是否阻塞,如果存在多个阻塞启动器时,只有最后一个阻塞,之前的会通过goroutine来异步启动
// 要规划好启动器的注册顺序
StartBlocking() bool
// 4. 资源停止和销毁
// 通常在启动时遇到异常时或者启动远程管理时,用于释放资源和终止资源的使用
// 通常要优雅的释放,等待正在进行的任务继续,但是不再接受新的任务
Stop(StartContext)
}
空实现
// 我们可以定义一个空的实现,因为不同的启动器不一定都要实现所有的方法
// 定义一个空的,然后其他的启动器嵌套这个空实现,就可以只实现需要实现的
// 基础空实现,方便资源启动器的代码实现
type BaseStarter struct{}
func (b BaseStarter) Init(context StartContext) {}
func (b BaseStarter) SetUp(context StartContext) {}
func (b BaseStarter) Start(context StartContext) {}
func (b BaseStarter) StartBlocking() bool { return false }
func (b BaseStarter) Stop(context StartContext) {}
启动注册器
- 用于把各种资源实现注册在该资源里面,以方便基础资源的集中管理。
// 启动器注册器
// 不需要外部构造,全局只有一个
type starterRegister struct {
noBlockingStarters []Starter
blockingStarters []Starter
}
func (r *starterRegister) Register(s Starter) {
if s.StartBlocking() {
r.blockingStarters = append(r.blockingStarters, s)
} else {
r.noBlockingStarters = append(r.noBlockingStarters, s)
}
}
func (r *starterRegister) AllStarter() []Starter {
starters := make([]Starter, 0)
starters = append(starters, r.noBlockingStarters...)
starters = append(starters, r.blockingStarters...)
return starters
}
//
//全局只有一个注册器
var StarterRegister *starterRegister = new(starterRegister)
func Register(s Starter) {
StarterRegister.Register(s)
}
// 系统基础资源的启动管理
func SystemRun() {
ctx := StartContext{}
// 初始化
for _, starter := range StarterRegister.AllStarter() {
starter.Init(ctx)
}
// 安装
for _, starter := range StarterRegister.AllStarter() {
starter.SetUp(ctx)
}
// 启动 阻塞的应该要异步处理!!! 这里就不展开了
for _, starter := range StarterRegister.AllStarter() {
starter.Start(ctx)
}
}
例子 实现
package infra
import "fmt"
func init(){
// 注册进去
Register(&ConfStarter{})
}
type ConfStarter struct {
BaseStarter
}
func (c *ConfStarter) Init(ctx StartContext) {
fmt.Println("配置初始化")
}
func (c *ConfStarter) SetUp(ctx StartContext) {
fmt.Println("配置安装")
}
func (c *ConfStarter) Start(ctx StartContext) {
fmt.Println("配置启动")
}
启动
package main
func main(){
infra.SystemRun()
}