背景
工作中一直使用TAF,但对底层原理缺少了解,感觉以后工作中不理解原理不太好,但又一直懒着不想看。最近有了契机,就看看吧,希望能坚持下去,之前的levelDB暂时放一边。
官方简介文档:https://tarscloud.gitbook.io/tarsdocs/rumen/tars-intro
文档里有的就不再赘述了,本系列学习主要是为了看源码,框架概念方面的知识官方文档才是最好的。
基础概念
APP
APP是应用名,是一组服务的集合,通常可以表示实现某个业务的系统名称。
在Tars系统中APP名必须唯一。
Server
Server是服务名,是提供服务的进程名称。
一个Server必须属于某个APP,一个APP下的所有Server名都应具备唯一性。
一个Server代表一个独立的程序,绑定至少一个ip,实现一组相关的接口。
Servant
Servant是服务提供者,提供了一个或多个具体接口给客户端调用。
Servant对应代码中的一个类,继承于tars文件中的interface。
一个Servant必须属于某个Server,一个Server下的所有Servant名都应具备唯一性。
也就是说,一个tars协议文件对应的其实是一个Servant,而不是我之前理解的一个Server!
一个Server下可以有多个Servant,可以在Server的initialize方法下使用addServant添加!具体可以看手上的YUDS代码!
终于分清Server和Servant的区别了……
获取配置
发布之后登陆机器,运行ps -efww | grep ${your server name}
命令可以看到服务运行的命令行,可以看到配置文件。
client创建通信器
之前就在代码里见过两种方式,但没有深究,现在看来原来一种是自己直接指定ip和端口,也是我比较常用的,另一种就是将通信器指定到框架主控中,由主控来帮忙寻址,就不用自己指定ip和port了,但是这种方式没有上报信息,如果需要上报信息的话也需要向指定主控一样指定其他相关属性。1
2
3
4
5
6
7
8
9
10
11
12// 第一种
Communicator *communicator = new Communicator();
HelloPrx helloPrx = communicator->stringToProxy<HelloPrx>("Test.HelloServer.HelloObj@tcp -h xxx -p yyy:tcp -h www -p zzz");
helloPrx->call();
// 第二种
Communicator *communicator = new Communicator();
communicator->setProperty("locator", "tars.tarsregistry.QueryObj@tcp -h xxxx -p 17890");
communicator->setProperty("stat", "tars.tarsstat.StatObj");//指定stat状态信息
communicator->setProperty("property", "tars.tarspropery.PropertyObj");//指定自定义属性信息
HelloPrx helloPrx = communicator->stringToProxy<HelloPrx>("Test.HelloServer.HelloObj");
helloPrx->call();
模板配置
tarsnode会从平台拉取服务对应的模板(服务部署时配好的),然后根据模板生成服务对应的配置,并用这个配置启动服务。
模板配置里,就会有比如这个服务的端口、启动的线程数之类的东西。
入门
每个Servant(Obj)对象对应一个业务处理线程,所以如果是Imp的成员变量,且只被当前的Imp对象处理,就不需要加锁。
枚举类是有stoe和etos两个方法的。
tars文件中还有key这个关键字,可以用来定义小于比较符号。
数据编码是由头信息和实际数据组成的。
TUP是Tars统一协议,最早就用来方便各语言客户端调用Tars服务,只提供编解码,并不提供网络通讯。当然如果Tars已经提供了某种语言的客户端,那么就不再需要使用TUP来调用Tars服务了。
使用指南(c++)
所有接口函数中的最后一个参数都是TarsCurrentPtr,通过这个结构体可以获取请求包的所有原始内容。
对于同一个Obj名称,多次调用stringToProxy返回的是proxy其实是同一个,多线程调用是安全的,且不会影响性能。
原来还可以针对接口设置超时时间。
调用
寻址方式按照是否在主控注册可以分为两类,不在主控注册就是直接按照ip寻址,在主控注册的服务的寻址方式是基于服务名进行的,由主控去帮忙寻址,但是需要在生成通信器的时候指定register的地址。
还可以指定set调用。
还有hash调用,会使同一个请求落在同一个机器上。
染色
染色的功能主要是可以在某服务某接口中对特定用户号码的消息进行染色,方便实时察看该用户引起后续所有相关调用信息流的日志。
染色日志有主动打开和被动打开两种方法。
主动打开是指在请求的客户端打开框架中的染色日志开关,被动打开是指在请求的服务端预先设定染色条件,判断收到的key值,由服务端打开染色开关。
被动打开中就会在jce文件中用到routekey关键字定义key。
tars协议数据包大小
客户端对发出去的包大小没有限制,但是收到的回包默认不能超过10000000字节,差不多10M。
服务端也一样,对发出去的包没有限制,收到的包默认不能超过100000000字节,差不多100M。
服务管理
Tars还可以支持动态接收命令,来处理相关的业务逻辑。
有两个宏:TARS_ADD_ADMIN_CMD_PREFIX
和TARS_ADD_ADMIN_CMD_NORMAL
。
通常注册的接口处理有两种:全局的接口处理和基于对象的接口处理。
感觉全局的接口处理就是taf平台上用的发送自定义命令呀!
其他
Tars还支持一些其他操作,比如统计上报、异常上报、属性统计和查看tars调用链。
服务线程
Tars C++框架服务是单进程多线程RPC系统。
有7个固定线程,然后加上服务端网络线程数、业务处理线程数、客户端网络线程数以及每个客户端的异步回调线程数。
7个固定线程:主线程、端口业务逻辑线程、时间辅助线程、滚动日志线程、本地日志线程、远程日志线程、统计属性上报线程。
protobuf协议
现在tars已经支持proto文件了,能够从proto生成rpc相关代码。
注意,要在proto文件中加上option cc_generic_services=false;
tars会生成tars.h文件
协议解析器
协议解析器使得TarsCpp实现的Server几乎能支持任何协议,包括我们自定义的网络协议。