从TARS小白到熟练工的进阶实战

做者丨唐靖凯
编辑丨TARS小助手

做为一个应届毕业生,进入阅文集团,加入到通用平台中心以后,随着平常工做的逐步深刻,我渐渐了解阅文的技术体系,其中尤为以腾讯TARS平台最为重要。目前TARS平台承载了阅文内部绝大多数的服务,每日接口调用最大值近百亿,单业务峰值可在数万每秒,近300个业务服务。做为一个新人,我来说下我从TARS小白到熟练工的历程中整理的一些知识点。git

TARS文件

TARS做为一个服务治理框架,最基础的仍是要解决服务间调用的问题,这样就引入一个问题:如何在多个服务之间发布接口协议。TARS创新性的设计了一种接口描述语言,即TARS文件,在TARS文件中,能够编写模型、接口、枚举等。在服务提供方,咱们能够经过tars-maven-plugin解析TARS文件,生成对应的模型、接口、枚举代码,而后就能够在接口实现类中进行业务逻辑的编写。在对外提供服务时,调用方只须要拿到服务提供方的TARS文件,就能了解服务提供的全部接口及相关描述,从而生成客户端调用代码,进行服务接口调用。github

module TestApp
{
    interface Hello
    {
        string hello(int no, string name);
    };
};

在阅文内部,咱们也提供了统一的TARS管理中心,在这里咱们能够找到全部已经上传到管理中心的TARS文件,从而避免了经过线下传递TARS文件带来的不便;管理中心支持将TARS文件自动打包成jar包并发布到公司的Maven镜像上,省去了本身编译带来的麻烦。spring

服务部署

在TARS平台上进行服务部署,只需把代码仓库地址配置到TARS平台,选择分支、选择编译器、编译、打包、分批发布一条龙部署到TARS平台上。目前TARS平台支持物理机部署、Docker部署、物理机和Docker混合部署,极大地提高了使用的体验及知足了服务发布的多样性。同时,TARS平台还支持对每台服务器作特殊化处理,好比能够选择某台服务器设置为无流量作线上接口测试,能够修改某台服务器的私有模板进行服务设置、JVM设置、日志设置等配置的修改。这些都为平常工做中的开发、测试、问题排查提供了更多的方法及可能性。shell

在发布线上服务时,TARS平台只支持指定tag进行编译打包,从而在流程上规范了服务发布的操做。并且发布是能够自定义选择分批发布、无损发布,最大限度的下降因服务重启引发的线上服务抖动。数据库

服务监控

TARS平台提供了多维度、多样化的服务监控及特性监控。服务监控选项包含了流量、平均耗时、异常率、超时率等,能够自由选择时间范围、主调方业务名、主调方IP、被调方IP、接口名,从而缩小监控范围,方便定位问题。特性监控则针对每一台服务器提供了对JVM内存、堆使用状况、线程、请求队列等特性的监控,从而实现从服务器JVM级别进行问题定位。这些监控目前都是以5分钟为间隔,期待将来TARS平台能够提供更细粒度的时间间隔的监控。缓存

服务监控还提供了实时数据的功能,实现实时观测服务的秒级运行情况,在定位线上问题上发挥了重要的做用。springboot

日志

TARS-JAVA自带一套日志系统,提供了日志类的基础功能。它支持异步输出,支持多种日志级别,而且日志级别能够直接在TARS的管理平台经过修改私有模板或者给TARS服务发送设置日志级别命令来进行实时修改,实现平台一致性。它还支持异常输出,能够方便地打印异常日志。该日志系统不用额外的配置文件,不须要重写加载配置(在services.xml的应用中使用sl4j日志系统时,须要将日志系统的初始化安排到配置文件加载以后;在springboot的应用中使用sl4j日志系统时,须要写从新加载配置文件的逻辑)。目前TARS提供的日志系统在不少项目中都做为惟一日志系统使用。服务器

不过须要注意的是默认的日志系统输出的日志编码是GBK格式的,当你使用以UTF-8解析的远程shell工具查看日志时常常会发现有些日志内容丢失或者时乱码。则能够根据须要,将远程工具的编码格式调整为与GBK兼容的编码,或者使用iconv等工具转换日志编码进行查看。session

# encoding converting
cat xx.log | iconv -f=gbk

配置文件

TARS平台提供了服务配置中心来管理配置文件,在这里能够添加多个配置文件。在TARS平台上部署服务时,每台服务器会自动将全部配置文件加载到本地(前提是在服务代码中配置了加载配置文件),放在Classpath路径下,供JAVA服务读取解析。对于每一个配置文件,TARS平台还提供了文件内容变动时触发的回调函数。经过回调函数机制,咱们能够在修改完一个配置文件以后,在TARS平台上进行配置文件推送,从而触发代码中预先设定的回调函数,达到配置文件热更新的效果。固然,对于数据库链接信息、Redis链接信息这些须要重建链接的配置信息仍是推荐经过重启服务来更新。并发

接口测试

TARS平台提供了对TARS接口进行测试的页面。在测试页面,咱们能够为每一个接口添加多个测试用例数据,能够任意选择服务所在的一台机器进行测试用例调用。这种调用方式方便、快捷,可是对于自动化脚本不甚友好。针对这种状况,阅文内部提供了使用HTTP接口调用TARS接口的方式,更方便地进行自动化接口测试。期待TARS平台后续能对自动化接口测试提供更多的支持。

编码问题

在开发TARS服务时,尤为须要注意各类编码问题,这里整理了一些可能出现的编码问题以及解决方案。

服务配置文件编码

上面提到TARS平台提供了服务配置中心来管理配置文件,服务配置默认的编码是GBK,而且不支持修改,但阅文这边部署服务所使用的的机器(包括物理机和Docker)通常使用的编码是UTF-8。GBK和UTF-8都对ASCII码兼容,因此当配置文件不涉及中文或其余超过ASCII码覆盖范围的字符时,部署的微服务程序中采用系统默认编码读取配置文件时不会发生问题;可是当配置文件中涉及中文字符时,可能因为操做系统默认编码不与GBK兼容时,程序会读到错误的信息。

解决办法: 在本身写的服务代码中使用GBK编码打开配置文件;使用Unicode编码过的字符串代替原中文字符串。

TARS-JAVA的编码

你想尝试一下TARS,因而你把TARS-Java部署在刚刚调教好的Linux上(把本地语言设置成了zh_CN.UTF-8时),当你发布应用时,你会遇到一些奇怪的错误。当你查找缘由时,你会发现原来在发布程序使用了GBK去读取Linux的命令行输出。这个时候你只须要改一下TARS-JAVA的源码,将读取命令行输出的编码改为UTF-8,而后从新编译一下便可,很是快捷。固然,也能够不将操做系统的编码设置成zh_CN.UTF-8,不少工具可能没法正确显示中文字符。

服务器文件编码

服务器默认文件编码有时候会出现不是UTF-8的诡异的现象(每每是locale没有配置对UTF-8的支持),这个时候若是代码中使用了默认编码,就会出现乱码的现象。

解决方法:不要使用默认编码,在须要使用编码的时候,必定手动指定编码。

一些Trick分享

在实践TARS服务开发的过程当中,积累了一些小技巧,挑选一些献丑。

系统关闭钩子

在TARS平台管理中能够将特定服务的选中实例设置为无流量,以方便作发布、线上验证等操做。不过惋惜的是,在TARS服务中没法感知平台的无流量配置,这也就意味着本身编写的TARS服务没法在无流量状态配置先后作一些特别的动做,好比在无流量开启时同时去屏蔽队列消费操做等。可是,TARS服务支持系统的关闭钩子,能够在系统退出前对申请资源进行清理以及确保某些任务完成后再退出。退出TARS服务只须要经过平台对服务的AdminObj发送shutdown命令来完成,而后经过System.exit退出系统。因而能够利用Runtime.getRuntime().addShutdownHook方法,给TARS服务增长系统关闭的钩子。

获取调用方的IP

有时候须要记录调用方的IP,但因为TARS为了高效等目的,没有办法从服务端获取到客户端的标识信息。咱们能够从TCP/UDP链接获取调用方的IP和端口信息。

Session session = ContextManager.getContext().request().getIoSession();

String remoteIp = session.getRemoteIp();

int remotePort = session.getRemotePort();

如何规避Communicator实例重用所带来的问题

在TARS服务的实现中,不可避免地会去调用其余现成的服务,而且绝大多数状况下会调用多个服务。这些被调服务可能会要求在调用时使用不一样的编码,有的须要使用UTF-8,而有的须要使用GBK。当多种不一样编码的客户端混合调用时,可能会遇到编码问题。追本溯源,发如今获取Communicator实例时,会对其使用Map进行缓存,Map的键为locator或者CommunicatorConfig实例,而CommunicatorConfig只使用了locator和moduleName做为hashCode和equals方法的计算要素。因而当使用locator和moduleName相同的CommunicatorConfig实例去获取Communicator实例时,会获得同一个实例,即使charsetName并不一致。 解决的办法通常有两种:

  1. 继承CommunicatorConfig,并重写hashCode和equals方法,加入charsetName做为计算要素,再由这个派生类获得的实例去获取Communicator实例;
  2. 为须要特别配置其余属性的CommunicatorConfig实例设置不一样的moduleName。

小编有话说

感谢这位同窗的精彩分享,看完这位同窗从TARS小白到熟练工的进阶过程当中积攒的经验,你是否也想分享一下本身的经验?欢迎向 tarscloud@qq.com 投稿。

若是你尚未了解过TARS,欢迎到GitHub上围观、交流,以为好的话请给TARS点个star哦~!

GitHub地址:https://github.com/TarsCloud

相关文章
相关标签/搜索