本文作者:陈明杰(sandyskies)

Tars是腾讯从2008年到今天一直在使用的后台逻辑层的统一应用框架,目前支持C++,Java,PHP,Nodejs,Golang语言。该框架为用户提供了涉及到开发、运维、以及测试的一整套解决方案,帮助一个产品或者服务快速开发、部署、测试、上线。 它集可扩展协议编解码、高性能RPC通信框架、名字路由与发现、发布监控、日志统计、配置管理等于一体,通过它可以快速用微服务的方式构建自己的稳定可靠的分布式应用,并实现完整有效的服务治理。目前该框架在腾讯内部,各大核心业务都在使用,颇受欢迎,基于该框架部署运行的服务节点规模达到上万个。
Tars 于2017年4月开源,并于2018年6月加入Linux 基金会。
TarsGo 是Tars 的Go语言实现版本, 于2018年9月开源, 项目地址 https://github.com/TarsCloud/TarsGo ,欢迎star 。

TarsGo 新版本发布

在上次开源之后,有些用户反馈了一些需求,基于用户反馈的需求,我们进行了实现,并发布了1.1.0版本。 本次发布新增了:支持pb、支持zipkin分布式追踪、支持filter(自定义插件编写)、支持context 等,除此之外还做了一系列优化和bugfix。

新功能:PB支持

Protocol Buffers (简称 PB )是 Google 的一种数据交换的格式,它独立于语言,独立于平台,最早公布于 2008年7月。随着微服务架构的发展及自身的优异表现,ProtoBuf 可用于诸如网络传输、配置文件、数据存储等诸多领域,目前在互联网上有着大量应用。
如果对于现有已使用grpc,使用proto文件,想转换成tars协议的用户而言,需要将上面的proto文件翻译成Tars文件。这种翻译会比较繁琐,而且容易出错。 为此我们决定编写插件支持proto文件直接生成tars的rpc逻辑。protoc-gen-go的代码逻辑里面是预留了插件编写的规范的,参照grpc,主要有 grpc/grpc.go 和一个导入插件的link_grpc.go 。 这里我们编写 tarsrpc/tarsrpc.go 和 link_tarsrpc.go
使用方面:

  • 将这两个文件放到protoc-gen-go 下面,go install重新生成protoc-gen-go 二进制
  • 定义proto 文件
  • 使用重新编译安装的protoc-gen-go生成序列化和rpc相关接口代码
protoc --go_out=plugins=tarsrpc:. helloworld.proto

  

  • 编写tars 客户端和服务端代码,参数使用pb生成的结构体,其余代码逻辑和正常的tars服务一致。

新功能: filter机制, 支持zipkin分布式追踪

为了支持用户编写插件,我们支持了filter机制,分为服务端的过滤器和客户端过滤器,用户可以基于这个机制,实现自己的TarsGo插件。

//服务端过滤器, 传入dispatch,和f, 用于调用用户代码, req, 和resp为传入的用户请求和服务端相应包体
type ServerFilter func(ctx context.Context, d Dispatch, f interface{}, req *requestf.RequestPacket, resp *requestf.ResponsePacket, withContext bool) (err error)
//客户端过滤器, 传入msg(包含obj信息,adapter信息,req和resp包体), 还有用户设定的调用超时
type ClientFilter func(ctx context.Context, msg *Message, invoke Invoke, timeout time.Duration) (err error)
//注册服务端过滤器
//func RegisterServerFilter(f ServerFilter)
//注册客户端过滤器
//func RegisterClientFilter(f ClientFilter)

  有了过滤器,我们就能对服务端和客户端的请求做一些过滤,比如使用 hook用于分布式追踪的opentracing 的span。 我们来看下客户端filter的例子:

//生成客户端tars filter,通过注册这个filter来实现span的注入
func ZipkinClientFilter() tars.ClientFilter {
return func(ctx context.Context, msg *tars.Message, invoke tars.Invoke, timeout time.Duration) (err error) {
var pCtx opentracing.SpanContext
req := msg.Req
//先从客户端调用的context 里面看下有没有传递来调用链的信息,
//如果有,则以这个做为父span,如果没有,则起一个新的span,span名字是RPC请求的函数名
if parent := opentracing.SpanFromContext(ctx); parent != nil {
pCtx = parent.Context()
}
cSpan := opentracing.GlobalTracer().StartSpan(
req.SFuncName,
opentracing.ChildOf(pCtx),
ext.SpanKindRPCClient,
)
defer cSpan.Finish()
cfg := tars.GetServerConfig() //设置span的信息,比如我们调用的客户端的ip地址,请求的接口,方法,协议,客户端版本等信息
cSpan.SetTag("client.ipv4", cfg.LocalIP)
cSpan.SetTag("tars.interface", req.SServantName)
cSpan.SetTag("tars.method", req.SFuncName)
cSpan.SetTag("tars.protocol", "tars")
cSpan.SetTag("tars.client.version", tars.TarsVersion) //将span注入到 请求包体的 Status里面,status 是一个map[strint]string 的结构体
if req.Status != nil {
err = opentracing.GlobalTracer().Inject(cSpan.Context(), opentracing.TextMap, opentracing.TextMapCarrier(req.Status))
if err != nil {
logger.Error("inject span to status error:", err)
}
} else {
s := make(map[string]string)
err = opentracing.GlobalTracer().Inject(cSpan.Context(), opentracing.TextMap, opentracing.TextMapCarrier(s))
if err != nil {
logger.Error("inject span to status error:", err)
} else {
req.Status = s
}
}
//没什么其他需要修改的,就进行客户端调用
err = invoke(ctx, msg, timeout)
if err != nil {
//调用错误,则记录span的错误信息
ext.Error.Set(cSpan, true)
cSpan.LogFields(oplog.String("event", "error"), oplog.String("message", err.Error()))
} return err
}

服务端也会注册一个filter,主要功能就是从request包体的status 提取调用链的上下文,以这个作为父span,进行调用信息的记录。整体的一个效果:

详细代码参见 TarsGo/tars/plugin/zipkintracing完整的zipkin tracing的客户端和服务端例子,详见 TarsGo/examples下面的ZipkinTraceClient和ZipkinTraceServer

新功能: 支持context

TarsGo 之前在生成的客户端代码,或者用户传入的实现代码里面,都没有使用context。 这使得我们想传递一些框架的信息,比如客户端ip,端口等,或者用户传递一些调用链的信息给框架,都很难于实现。 通过接口的一次重构,支持了context,这些上下文的信息,将都通过context来实现。 这次重构为了兼容老的用户行为,采用了完全兼容的设计。

服务端使用context

type ContextTestImp struct {
}
//只需在接口上添加 ctx context.Context参数
func (imp *ContextTestImp) Add(ctx context.Context, a int32, b int32, c *int32) (int32, error) {
//我们可以通过context 获取框架传递的信息,比如下面的获取ip, 甚至返回一些信息给框架,详见tars/util/current下面的接口
ip, ok := current.GetClientIPFromContext(ctx)
if !ok {
logger.Error("Error getting ip from context")
}
return 0, nil
}
//以前使用AddServant ,现在只需改成AddServantWithContext
app.AddServantWithContext(imp, cfg.App+"."+cfg.Server+".ContextTestObj")

客户端使用context

 ctx := context.Background()
c := make(map[string]string)
c["a"] = "b"
//以前使用app.Add 进行客户端调用,这里只要变成app.AddWithContext ,就可以传递context给框架,如果要设置给tars请求的context
//可以多传入参数,比如c,参数c是可选的,格式是 ...[string]string
ret, err := app.AddWithContext(ctx, i, i*2, &out, c)

服务端和客户端的完整例子,详见 TarGo/examples

其他优化和修复

  • 将request package 的Sbuffer字段由vector<unsigned byte> 改成vector<byte>,解决和其他语言通信问题
  • 修复stat监控上报问题
  • 日志级别从远端更新
  • 修复路由刷新协程极端情况下死锁问题
  • 优化协程池方案,并添加协程池方案
  • 修复go协程启动顺序导致panic问题
  • golint大部分代码

TarsGo新版本发布,支持protobuf,zipkin和自定义插件的更多相关文章

  1. 深蓝词库转换2.5发布——支持微软五笔,支持Linux和macOS和更多命令行功能

    最近利用晚上的时间,对很久没有新版本发布的深蓝词库转换进行了版本升级.本次升级主要包含的功能包括: 一.支持Win10自带的微软五笔输入法用户自定义短语的导入导出. 1.在转换输入法词库列表中选择“W ...

  2. xmake v2.5.2 发布, 支持自动拉取交叉工具链和依赖包集成

    xmake 是一个基于 Lua 的轻量级跨平台构建工具,使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对新手非常友好,短时间内就能 ...

  3. 新版本SpringCloud sleuth整合zipkin

    SpringCloud Sleuth 简介 Spring Cloud Sleuth为Spring Cloud实现了分布式跟踪解决方案. Spring Cloud Sleuth借鉴了Dapper的术语. ...

  4. [转帖]2018年的新闻: 国内首家!腾讯主导Apache Hadoop新版本发布

    国内首家!腾讯主导Apache Hadoop新版本发布   https://blog.csdn.net/weixin_34194317/article/details/88811258 腾讯也挖了很多 ...

  5. React Native之(支持iOS与Android)自定义单选按钮(RadioGroup,RadioButton)

    React Native之(支持iOS与Android)自定义单选按钮(RadioGroup,RadioButton) 一,需求与简单介绍 在开发项目时发现RN没有给提供RadioButton和Rad ...

  6. TensorFlow 1.2.0新版本完美支持Python3.6,windows在cmd中输入pip install tensorflow就能下载应用最新tensorflow

    TensorFlow 1.2.0新版本完美支持Python3.6,windows在cmd中输入pip install tensorflow就能下载应用最新tensorflow 只需在cmd中输入pip ...

  7. 修改gorm支持protobuf

    gorm的功能很强大,支持很多很多特性,打算在项目中用上它. 但gorm不支持protobuf,如果idl用的是protobuf,需要对每个message做一个重新定义一个内部的struct,使得可以 ...

  8. Cordova - 与iOS原生代码交互2(使用Swift开发Cordova的自定义插件)

    在前一篇文章中我介绍了如何通过 js 与原生代码进行交互(Cordova - 与iOS原生代码交互1(通过JS调用Swift方法)),当时是直接对Cordova生成的iOS工程项目进行编辑操作的(添加 ...

  9. ionic3使用cordova创建自定义插件

    1 安装 plugman 插件 npm --registry https://registry.npm.taobao.org install -g plugman 2 新建组件 新建一个插件文件夹,进 ...

随机推荐

  1. HTML利用posotion属性定位 小技巧

    1.居中效果 父级DIV (index-top )属性设置为 text-align:center; 子级DIV( tabIndex-main)属性设置为 margin:0 auto;   2.左右对齐 ...

  2. 在已配置成功的opencv3.2.0下配置opencv_contrib模块

    简介: 之前在Ubuntu下配置OpenCV时,因为对opencv3..0不是特别了解,没有把opencv_contrib进行安装,这里提醒大家尽量要一次性安装完毕,减少不必要的麻烦. .0文件夹 ( ...

  3. elixir 基础数据结构

     Elixir中的一些基础的数据结构:整数,浮点数,字符串,原子,列表,元组  整数,浮点数,字符串 跟其他语言差不多  原子:名字为值的常量  在ruby类似Symbols  在erlang是用大写 ...

  4. PS改变图像颜色

    由于写的一个页面主色调变了,里面的一些图标颜色也要相应改变,自己难得重新去psd里面截图,就想着用ps,看能否直接能变换一下图标颜色.其实方法也很简单的. 1:用ps打开需要改变图标颜色的文件,然后选 ...

  5. node(6)angular介绍

    一.angular 的介绍 AngularJS[1]  诞生于2009年,由Misko Hevery 等人创建,后为Google所收购.是一款优秀的前端JS框架,已经被用于Google的多款产品当中. ...

  6. Pig group用法举例

        group语句可以把具有相同键值的数据聚合在一起,与SQL中的group操作有着本质的区别,在SQL中group by字句创建的组必须直接注入一个或多个聚合函数.在Pig Latin中grou ...

  7. zabbix系列之四——快速使用

    https://www.zabbix.com/documentation/3.4/manual/quickstart/login Quickstart 1login and configuring u ...

  8. java vector的多线程安全是否有用

    在网上搜了不少文章,发现有不少没讲清楚的,也有不少好文,本文希望更易懂地描述该问题.如有不对的地方,请多多指正~~ vector的使用主要有如下两种场景:(1)vector所谓的多线程安全,只是针对单 ...

  9. Windows+Git+TortoiseGit+COPSSH 安装教程及问题收集

    准备工作: 1. git-1.8.1.2-preview20130201.exe 下载地址: https://code.google.com/p/msysgit/downloads/list 2. C ...

  10. 《CDN 之我见》原理篇——CDN的由来与调度

    CDN是将源站内容分发至全国所有的节点,从而缩短用户查看对象的延迟,提高用户访问网站的响应速度与网站的可用性的技术.它能够有效解决网络带宽小.用户访问量大.网点分布不均等问题. 为了让大家更全面的了解 ...