|博客文章你不知道的TARS,助力阅文集团完成技术架构改造!——TARS开启阅文集团技术架构变革之门作者简介|欧亮后端研发架构师,目前就职于阅文集团技术部基础服务研发组,一直致力于Java应用架构设计和业务架构演进研发.深入理解分布式系统架构。0x00什么是TARSTARS是腾讯从2008年至今一直在使用的后端逻辑层统一应用框架(TotalApplicationFramework)的开源版本。目前支持三种语言:C++、Java和NodeJs。该框架为用户提供了开发、运维、测试等一整套解决方案,帮助产品或服务快速开发、部署、测试、上线。它集成了可扩展的协议编码和解码、高性能的RPC通信框架、名称路由和发现、发布监控、日志统计和配置管理。通过它,你可以以微服务的形式快速构建属于自己的稳定可靠的分布式应用,并实现完整有效的服务治理。目前,该框架正在腾讯内部各大核心业务中使用,并颇受欢迎。基于该框架部署和运营的服务节点规模已达数万个。内部版本和外部版本在代码结构和功能上基本相同。本文基于私有云版本的TARS,部分功能可能与目前开源和公有云的TARS版本有所不同。0x01使用TARS的原因一年半前,公司后端服务技术栈是.net加上各种Oracle存储过程,有300多台windows服务器配备了当年的顶级服务器。不管好坏,都支撑了10多年的网络文学情怀。如今,随着IP热潮的涌动,公司业务的迅速扩张,不言而喻,必须进行重组。于是乎,我们选择了90%的人都会选择,而且技术圈成熟的JAVA来做这件事。秉承快速建设、共同发展、持续集成、快速迭代的理念,顺其自然起步。去年年初的某一天,运维方强烈推荐了TARS。顿时掀起了一阵波澜,“这东西的学习成本是多少?”,“跟腾讯那边一样吗?”,“适合在线使用吗?”。带着疑惑和担忧,我阅读了内部使用资料和压力测试报告(现在官方纪念碑在这里https://github.com/Tencent/TA...),开始了TARS之旅。0x02业务集现状公司TARS业务服务集日最大接口调用近百亿,单业务峰值每秒数万,业务服务近300个。对于常规的开发部署方式来说,统一编码、部署、运维,必然会花费大量资金。使用TARS更容易。正是TARS出色的服务表现,公司APP才抵挡住了515书友粉丝节、百万红包、手Q联动跨年等过亿用户的活动。][2]业务集合结构0x03TARS在哪里?TARS是一个庞大而全面的分布式应用程序。抛开开发和部署习惯的改变不说,使用TARS之后,确实省了很多,也方便了很多。在服务容错方面,TARS有基本的容错和负载均衡,可以让我们忽略间歇性、偶发性、永久性的设备故障。任何服务器宕机都不会影响业务访问。在测试和流量重定向之间切换的能力。在高性能方面,TARS采用Reactor模型,可以高效支持百万级别的句柄监控——EpollET。为TARS帧提供高达41w/s的吞吐量。在可扩展性方面,扩容是业务发展必不可少的过程。TARS为平滑扩容提供了良好的支持,基于流程的配置可以完成无感知的业务扩容和升级。在管理和运维方面,TARS有自己的监控模块,实时统计主Tuner的反馈情况,并在管理界面提供多维度的性能数据图。用于开发运维判断当前服务状态,可配置参数阈值短信或微信告警通知。0x04如何使用TARSTARS开发流程01.开发TARS,你必须知道如何编写JCE接口文件效率和网络带宽使用之间的折衷考虑。TARS的JCE接口描述语言文件以.tars后缀结尾。JCE文件如下图所示:[1]什么是ICE:ICE,InternetCommunicationsEngine,是一个适用于异构环境的面向对象的中间件平台。一个JCE文件为一个上层业务服务调用5-6个基础TARS是很常见的。找到产品业务后,分别找到对应服务的开发。由于每个服务基本上都是一个TARS服务,所以与一个服务通信只需要3个步骤:1.“我可以下载××服务的JCE吗?!”;2.发送一个JCE文件;3.“谢谢”;JCE的内容都是约定俗成的,对应的结构体和接口也做了相应的注解。因此,沟通如此简洁明了。02.JCE和TARSserver实际开发是通过jce-maven-plugin编译的,可以生成具体的Servant接口。业务逻辑可以通过继承接口来实现。Servant接口继承类在遵循TARS规范的java项目的services.xml中配置。services.xmlTARS项目有特定的目录结构,具体结构在网关中如下图所示。服务项目是一个普通的java项目。本地开发通过后,发布jar类库,导入到网关中。TARS容器只需要编译网关即可。TARS目录结构TARS目录结构和严格的mavenization消除了开发逻辑代码单独打包的需要。同时严格区分开发和上线测试流程,对规范研发管理流程有很大帮??助。03、TARS客户端调用流程获取Communicator实例CommunicatorConfigcfg=CommunicatorConfig.load("config.conf");通讯器communicator=CommunicatorFactory.getInstance().getCommunicator(cfg);获取ServantProxyConfig实例并配置ServantProxyConfigproxyConfig=newServantProxyConfig(taf.serverName);TARSconfig对象常用参数设置调用Communicator的stringToProxy方法并传入ServantProxyConfig实例,最后返回Jce生成的动态代理对象,及调用相应的方法。communicator.stringToProxy(api,proxyConfig);ServantProxyFactory中创建的动态代理对象TARS支持同步或异步接口调用。通过设置config对象的超时时间,可以实现软件层面的服务过载保护。同步调用:HelloPrxprx=c.stringToProxy("TestApp.HelloServer.HelloObj");//发起远程调用prx.hello(1000,"helloword");异步调用:HelloPrxprx=c.stringToProxy("TestApp.HelloServer.HelloObj");//发起远程调用ex){}@Overridepublicvoidcallback_hello(Stringret){System.out.println(ret);}},1000,"helloword");从去年到现在,公司的迁移转型如火如荼。主要目标是从.net代码中读取逻辑,并用JAVA重写成TARS服务。同时提供更高的易用性,为公司APP相关新需求的迭代保驾护航。在这个过程中,app的接口提供层(Tomcat部署)发生了很大的变化。从原来直接访问数据持久层到每个TARS微服务的调用,问题很多。有一段时间,TARS访问采用了最简单有效的同步方式,使用TARS提供的客户端同步超时配置来处理接口超时。这样一来,由于网络传输的不稳定性,频繁访问的读取接口会导致链式处理线程的垄断,从而降低整个服务的吞吐量,并伴有重启。经过jvm、gc等分析,使用TARS提供的异步方式获取接口返回,以及编码层面的细粒度超时控制,基本解决了上述问题。目前业务层调用总量也翻了一番(峰值从当时的120W左右,到现在的250W),节省了一半的设备。TARS调整方式的多样性也为不同的业务场景提供了更全面的支持。JCE-WUP协议TARS不仅可以支持客户端通过JCE生成类的调用方式,还可以发起WUP包协议调用。什么是WUP:WUP(wirelessuni-protocol)无线统一协议是基于UniPacket的JCE编码的Command层协议封装,实现对请求和响应报文对象的封装支持协议动态扩展序列化数据,可用于网络传输或persistence存储支持直接调用TARSPacket方法的服务器JAVA版本TafUniPacketuniPacket=newTafUniPacket();uniPacket.setTafVersion(Const.VERSION_WUP3);uniPacket.setEncodeName("UTF-8");uniPacket.setServantName("TestApp.HelloServer.HelloObj");uniPacket.setFuncName("你好");uniPacket.put("word","HelloWorld");byte[]sendPackect=uniPacket.encode();然后使用Socket发送包调用信息服务物理机为TARSURL,而不是masterURL。TARS通过轮询或健康统计来选择可用的URL。具体逻辑可以查看tars-core源码,com.qq.TARS.client.cluster.DefaultLoadBalance类:对应WUP,TARS与TUP概念相同。相关工具类为TARSUniPacket,打包、解包、调用TARS服务的方法完全相同。https://github.com/Tencent/TA...05。结合版本控制工具编译发布TARS支持常用版本控制管理工具:SVN/GIT的关联编译。输入SVN路径,可以扫描路径下的有效分支。输入GIT路径以扫描此目录中的有效TAG分支。TARS编译接口发布的相关日志管理也集成在平台中,可以实时判断发布状态。TARS发布接口所有的TARS项目都使用一套编译发布,通过一定的队列分配进行操作。编译产生一个唯一的发布版本。历史发布记录存储,可追溯,易于回滚。团队中有很多业务并行开发,会创建很多分支。有时候你想学习别人的代码,却发现网上有很多分支无法确定当前运行的版本。可以通过releaselog查询最新版本分支。06.TARS提供容器接口测试功能。服务正常发布后,按照TARS自定义输入输出参数的格式,调用JCE中定义的方法进行自测。TARS接口测试对于一个接口的开发,经过本地测试,只能说这个接口在逻辑上是连通的。放到线上可能会出现各种问题,比如环境配置、接口性能、接口不满足分布式的考虑等等,这个测试功能无疑是验证线上是否正确的好手段。此外,TARS的接口可以转换并暴露给HTTP。所以QA和我们达成了协议,每个测试的接口都必须提供HTTP调用。这样既方便了功能验证,又沿用了原有的压测形式。07.服务多维度监控服务量和性能指标监控直观反映服务运行状态。通过不同维度的设置和查询,可以快速评估流量峰值,定位响应异常,查看调用路径,优化调用毛刺。TARS监控成为我们定位问题的第一切入点。流量抖动和耗时增加基本上一眼就能看出来。监控也细化到界面维度,为“闲暇”界面优化提供参考。08.TARS提供了丰富的参数配置。TARS的默认配置基本足够日常开发和维护。TARS还支持针对特殊服务进行特定配置,可以通过调整各种参数来提升服务性能。例如TARS-JAVA可以通过节点服务管理来增加Reactor模型工作线程的数量,也可以通过修改配置模板来调整jvm参数或者服务超时等特性。记得某次业务服务从Tomcat切换到TARS。原因不用多说,主要是因为TARS默认的高吞吐和容错能力。跑了一天突然收到短信提醒,平均耗时超过阈值。开启TARS监控观察,调用量并没有明显增加,调用曲线也符合之前的业务特点。“耗时多少一直在慢慢上升。”当时第一反应是是不是代码层面的问题。经过一轮排查,除了适配TARS入口调用的代码外,基本确定与原版“汤姆猫”上运行的代码一致。查看物理机的监控,CPU/IO/MEM都没有异常。通过查看TARS特性监控,发现相关监控中的req.queue.waitingtime(请求在队列中等待时间)和jvm.thread.num(jvm当前线程总数)确实异常。等待时间曲线阶段性增加,但线程数不多。初步判断应该和服务器处理线程有关。“都是应用服务器,为什么处理能力这么低?如果是Tomcat,它会调整maxConnections,acceptCount等。”搞了半天,原来TARS也支持容器性能的细粒度修改。于是我把工作线程数从默认配置的5个改为32个,重启观察了一会儿,没有再出现这种现象。TARS还提供了私有模板功能,可以用于更细粒度的配置,甚至是jvm层面的调优。为用户提供无保留的配置能力也是优秀架构易用性的重要体现。0x05TARS展望腾讯于2017年4月10日在github上正式开放开源版TARS,并提供技术讨论群(qq技术交流群:579079160),并表示将继续对内使用,对外维护.可以预见,TARS将能够支持更多无约束的产品需求,对业务支持和线上极端情况的容忍度会越来越大。希望这篇科普能够引起大家的兴趣,帮助大家早日加入使用TARS的行列。
