什么是Tars
Tars是基于名字服务使用Tars协议的高性能RPC开发框架,同时配套一体化的服务治理平台,帮助个人或者企业快速的以微服务的方式构建自己稳定可靠的分布式应用。
TarsGo
TarsGo就是Tars的Golang版本,我们可以通过使用TarsGo完成构建Tars的rpc服务。接下来我将进一步对其实现进行分析,深入学习TarsGo的设计原理与思想,有兴趣的可以关注一下。
TarsRun
上一篇《Tars源码分析—基础环境搭建》我们完成了基础环境的搭建,也能够初始化一个TarsGo Server了,解析来,我们将进一步分析研究Tars的启动流程,从而加深对Tars的认识。
下面的代码就是一个TarsGoServer的启动代码,非常的简洁明了。
- 读取tars配置。
- 注册Serrvant。
- tarts Run启动服务。
func main() {
cfg := tars.GetServerConfig()
imp := new(SayHelloImp)
app := new(TestApp.SayHello)
app.AddServant(imp, cfg.App+"."+cfg.Server+".SayHelloObj")
tars.Run()
}
这里其实涉及到一些概念,比如Servant和Objt是啥,后面如果有时间,可以专题填坑。
接下来就是详细分析每一个部分。
首先触发tars.GetServerConfig(),会执行Init方法,去读取对于的配置文件。这里简单来说就是初始化加载配置文件
func Init() {
initOnce.Do(func() {
initConfig()
})
}
获取到对应的cfg之后,会被用于后续的Servant注册,已经Server的启动。读取完配置文件之后,就进行对应server的Servant的注册工作。
Servant的注册也十分的简单,就是将Server和Obj(调用key)加入到RunList,tarsConfig和goSvrs中,方便后续调用。
func addServantCommon(v dispatch, f interface{}, obj string, withContext bool) {
objRunList = append(objRunList, obj)
cfg, ok := tarsConfig[obj]
jp := NewTarsProtocol(v, f, withContext)
s := transport.NewTarsServer(jp, cfg)
goSvrs[obj] = s
}
完成添加后就执行启动,TarsServer的启动十分的清晰明了大概流程如下:
1.读取配置文件获取到在AddServant阶段注册Server对象。
2.遍历RunList根据objKey去取出对应的Server,判断是否有http服务,如果有,就在内部建立http服务。
3.进入mainLoop完成最后的启动工作,并将信息上报到平台,这里依赖的是NodeFHelper服务。
具体的启动流程如下图所示。
mainLoop方法解析
mainLoop中就是Tars循环保持心跳的逻辑所在,具体代码如下所示,为了方便理解,我就直接把解析添加到了代码中。
func mainLoop() {
// 初始化一个NodeHelper工具方法
ha := new(NodeFHelper)
// 创建一个NodeServer的基本信息
comm := NewCommunicator()
// GetServerConfig 是一开始Init的时候获取的
node := GetServerConfig().Node
app := GetServerConfig().App
server := GetServerConfig().Server
container := GetServerConfig().Container
// 添加节点信息
ha.SetNodeInfo(comm, node, app, server, container)
go ha.ReportVersion(GetServerConfig().Version)
// 处理心跳
go ha.KeepAlive("") //first start
// 处理标识位事件
go handleSignal()
// 设定循环检测的事件
loop := time.NewTicker(GetServerConfig().MainLoopTicker)
//线程挂起循环检测
for {
select {
case <-shutdown:
// 上报停止时间
ReportNotifyInfo(NotifyNormal, "stop")
return
case <-loop.C:
// 检测是否终止中
if atomic.LoadInt32(&isShutdowning) == 1 {
continue
}
// 循环发送KeepAlive
for name, adapter := range svrCfg.Adapters {
if adapter.Protocol == "not_tars" {
// TODO not_tars support
ha.KeepAlive(name)
continue
}
if s, ok := goSvrs[adapter.Obj]; ok {
if !s.IsZombie(GetServerConfig().ZombieTimeout) {
ha.KeepAlive(name)
}
}
}
}
}
}
NodeFHelper
NodeFHelper是一个针对ServerNode的扩展方法,其主要作用就是提供一些工具方法,让业务代码更快的注册自己的服务到线上,这个思想就是ServerNode其实也是一个RPC服务,然后用户可以通过Rpc调用ServerNode实现一些注册,和心跳包的操作。
type interface NodeFHelperInterface {
SetNodeInfo // 注册节点信息
KeepAlive // 向节点发送心跳包
ReportVersion // 向节点上报Tars版本
}
到此就完成了服务的启动