Jupiter 框架入口介绍
概述
这篇我们来介绍一下jupiter微服务框架的应用入口,之所以写这篇文章是为了深入了解 jupiter 框架的运行机制。
数据结构介绍
下面我们来看一下 jupiter 的 Application 对象,
// Application is the framework's instance, it contains the servers, workers, client and configuration settings.
// Create an instance of Application, by using &Application{}
// Jupiter 框架的入口结构体
type Application struct {
cycle *xcycle.Cycle // 一些管理运行生命周期的函数管理
smu *sync.RWMutex
initOnce sync.Once
startupOnce sync.Once
stopOnce sync.Once
servers []server.Server // 各种服务,http, grpc 等
workers []worker.Worker // 任务
jobs map[string]job.Runner // 任务
logger *xlog.Logger // 日志对象
registerer registry.Registry // 服务注册接口对象
hooks map[uint32]*xdefer.DeferStack
configParser conf.Unmarshaller // 系统配置对象
disableMap map[Disable]bool
HideBanner bool
}
application 对象可以分为一下几个组成部分:
- cycle、smu、initOnce、startupOnce、stopOnce 关于运行机制的帮助字段。
- servers、workers、jobs 这三个字段是用于存储各种服务的,只要服务实现了接口,框架就能根据一样的流程来启动这些服务。
- registerer 是服务发现与注册策略的实际对象,可以是 etcd、consul,只要实现 Registry 接口。
- hooks 保存在框架运行时的各个钩子函数
- configParser 这个字段保存着配置信息,配置信息的来源可以是文件、配置中心地址等。
- logger 日志对象,xlog 包是 zap 日志库的一个二次修改。
应用流程
这一节我们介绍一下框架的启动流程,流程图如下:
Application 对象是 Jupiter 框架的应用入口,
- SetRegistry() 是用于注入服务发现与注册的,例如 registry 包中的 etcdv3 模块。
- Startup() 方法是各个服务的初始化方法。
- Serve()、Schedule()、Job() 是各类服务的注入方法。
- RegisterHooks() 是注册钩子的方法。例如在启动前后进行一些行为,就可以通过这个方法。
- Run() 方法则是启动应用的各个服务和框架自定义的一些服务,例如监控等。
- Stop() 是接收到系统信号后进行一些退出操作。
方法介绍
下面介绍几个启动流程中主要的方法。
Startup()方法
//Startup 应用启动前的初始化工作方法
func (app *Application) Startup(fns ...func() error) error {
app.initialize() // 初始化 app 的各个字段
// 执行框架定义的初始化方法
if err := app.startup(); err != nil {
return err
}
// 执行自定义的初始化方法
return xgo.SerialUntilError(fns...)()
}
Startup() 方法相当于 Application 的初始化。初始化分为两个部分,一部分是框架定义的初始化顺序,包括解析启动传参、加载配置、设置链路追踪、流量监控服务、服务治理等。另一部分是由框架使用者自行定义的各个服务的初始化,这部分函数一般是 Serve()、Job()、Schedule() 几个方法的调用函数。
RegisterHooks() 方法
//RegisterHooks register a stage Hook
func (app *Application) RegisterHooks(k uint32, fns ...func() error) error {
hooks, ok := app.hooks[k]
if ok {
hooks.Push(fns...)
return nil
}
return fmt.Errorf("hook stage not found")
}
这个方法主要是执行一些框架的钩子方法,例如在启动前后打印一些日志等等。
Run() 方法
// Run run application
// 应用启动方法
func (app *Application) Run(servers ...server.Server) error {
app.smu.Lock()
app.servers = append(app.servers, servers...)
app.smu.Unlock()
app.waitSignals() //start signal listen task in goroutine
defer app.clean()
// todo jobs not graceful
app.startJobs()
// start servers and govern server
app.cycle.Run(app.startServers)
// start workers
app.cycle.Run(app.startWorkers)
//blocking and wait quit
if err := <-app.cycle.Wait(); err != nil {
app.logger.Error("jupiter shutdown with error", xlog.FieldMod(ecode.ModApp), xlog.FieldErr(err))
return err
}
app.logger.Info("shutdown jupiter, bye!", xlog.FieldMod(ecode.ModApp))
return nil
}
这个方法是应用启动方法。Run() 方法可以传入各个实现了 server.Server 接口的对象。waitSignals() 会启动一个 goroutine 来监听系统的信号量用的。接着会依次启动定时任务、各个服务(grpc,http,govern)、任务队列。
在这个方法中,grpc、http、govern 服务会往注册中心注册每个服务的信息。用于服务发现。
Stop() 方法
Stop() 方法会程序退出时,调用各个服务的关闭方法,来关掉和断开各个服务。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。