TarsGo支持Protocol Buffer
Tars是腾讯从2008年到今天一直在使用的后台逻辑层的统一应用框架TAF(Total Application Framework),目前支持C++,Java,PHP,Nodejs,Golang语言。该框架为用户提供了涉及到开发、运维、以及测试的一整套解决方案,帮助一个产品或者服务快速开发、部署、测试、上线。 它集可扩展协议编解码、高性能RPC通信框架、名字路由与发现、发布监控、日志统计、配置管理等于一体,通过它可以快速用微服务的方式构建自己的稳定可靠的分布式应用,并实现完整有效的服务治理。目前该框架在腾讯内部,各大核心业务都在使用,颇受欢迎,基于该框架部署运行的服务节点规模达到上万个。
Tars 于2017年4月开源,并于2018年6月加入Linux 基金会,项目地址 https://github.com/TarsCloud 。
TarsGo 是Tars 的Go语言实现版本, 于2018年9月开源, 项目地址 https://github.com/TarsCloud/TarsGo
Tars协议是一种类c++标识符的语言,用于生成具体的服务接口文件,Tars文件是Tars框架中客户端和服务端的通信接口,通过Tars的映射实现远程对象调用。 Tars 协议是和语言无关,基于IDL接口描述语言的二进制编码协议。
详见 TarsProtocol
Protocol Buffers (简称 PB )是 Google 的一种数据交换的格式,它独立于语言,独立于平台,最早公布于 2008年7月。随着微服务架构的发展及自身的优异表现,ProtoBuf 可用于诸如网络传输、配置文件、数据存储等诸多领域,目前在互联网上有着大量应用。
PB协议是单独的协议,如果要支持RPC,可以定义service字段,并且基于protoc-gen-go 的grpc 插件生成相应的grpc编码。
以下面的 proto 文件为例
syntax = "proto3"; package helloworld; // The greeting service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) {} } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings message HelloReply { string message = 1; }
使用protoc生成相应的接口代码,以Go语言为例:
protoc --go_out=plugins=grpc:. helloworld.proto
如果对于现有已使用grpc,使用proto,想转换成tars协议的用户而言,需要将上面的proto文件翻译成Tars文件。对于Tars而言,Tars是编写tars文件,然后用相应的工具tars2xxx, 比如tars2go生成相应的接口代码。上面的proto文件翻译成tars文件是:
module helloworld{ struct HelloRequest { 1 require string name ; }; struct HelloReply { 1 require string message ; }; interface Greeter { int SayHello(HelloRequest req, out HelloReply resp); }; }
然后调用tars2go生成 相应的tarsgo接口:
tars2go --outdir ./ helloworld.tars
这种翻译会比较繁琐,而且容易出错。 为此我们决定编写插件支持proto直接生成tars的rpc逻辑。
有两种方案,一种是写protoc插件,直接读取protoc解析proto文件的二进制流,对service相应的字段进行解析,以便生成相应的rpc逻辑,其他交由protoc-gen-go处理
另外一种是直接编写protoc-gen-go的插件,类似gRPC插件,
这里决定采用方案2 。
protoc-gen-go 并没有插件编写的相关说明,但protoc-gen-go的代码逻辑里面是预留了插件编写的规范的,参照grpc,主要有 grpc/grpc.go 和一个导致插件包的link_grpc.go 。 这里我们编写 tarsrpc/tarsrpc.go 和 link_tarsrpc.go
代码逻辑基本上就是继承 generator.Generator,注册插件, 获取相应的service,method,和method的input和output,再调用P方法将要生成的代码输出即可
func init() { generator.RegisterPlugin(new(tarsrpc)) } // tarsrpc is an implementation of the Go protocol buffer compiler's // plugin architecture. It generates bindings for tars rpc support. type tarsrpc struct { gen *generator.Generator } func (t *tarsrpc) generateService(file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int) { originServiceName := service.GetName() serviceName := upperFirstLatter(originServiceName) t.P("// This following code was generated by tarsrpc") t.P(fmt.Sprintf("// Gernerated from %s", file.GetName())) t.P(fmt.Sprintf(`type %s struct { s model.Servant } `, serviceName)) t.P() ... ... }
这里主要是生成 service 转成相应的interface,然后interface里面有定义的rpc method, 用户可以实现自己真正业务逻辑的method,其余的都是tars相应的发包收包逻辑。Tars的请求包体:
type RequestPacket struct { IVersion int16 `json:"iVersion"` CPacketType int8 `json:"cPacketType"` IMessageType int32 `json:"iMessageType"` IRequestId int32 `json:"iRequestId"` SServantName string `json:"sServantName"` SFuncName string `json:"sFuncName"` SBuffer []uint8 `json:"sBuffer"` ITimeout int32 `json:"iTimeout"` Context map[string]string `json:"context"` Status map[string]string `json:"status"` }
我们只需要将rpc method的名字,放入RequestPacket 的SFuncName ,然后将请求参数调用proto的Marshal序列化后放到 SBuffer。
而对于回包,Tars的回包结构体:
type ResponsePacket struct { IVersion int16 `json:"iVersion"` CPacketType int8 `json:"cPacketType"` IRequestId int32 `json:"iRequestId"` IMessageType int32 `json:"iMessageType"` IRet int32 `json:"iRet"` SBuffer []uint8 `json:"sBuffer"` Status map[string]string `json:"status"` SResultDesc string `json:"sResultDesc"` Context map[string]string `json:"context"` }
同样,我们只需要将返回的结果,调用Marshal 将请求放入 SBuffer ,其他逻辑和tars保持一致。
编写完插件,就可以通过和grpc生成代码相同的方式,将proto 文件转化成tars的接口文件:
protoc --go_out=plugins=tarsrpc:. helloworld.proto
下面是简单的服务端例子
package main import ( "github.com/TarsCloud/TarsGo/tars" "helloworld" //上面工具生成的package ) type GreeterImp struct { } func (imp *GreeterImp) SayHello(input helloworld.HelloRequest)(output helloworld.HelloReply, err error) { output.Message = "hello" + input.GetName() return output, nil } func main() { //Init servant imp := new(GreeterImp) //New Imp app := new(helloworld.Greeter) //New init the A JCE cfg := tars.GetServerConfig() //Get Config File Object app.AddServant(imp, cfg.App+"."+cfg.Server+".GreeterTestObj") //Register Servant tars.Run() }
简单的客户端调用例子
package main import ( "fmt" "github.com/TarsCloud/TarsGo/tars" "helloworld" ) func main() { comm := tars.NewCommunicator() obj := fmt.Sprintf("StressTest.HelloPbServer.GreeterTestObj@tcp -h 127.0.0.1 -p 10014 -t 60000") app := new(helloworld.Greeter) comm.StringToProxy(obj, app) input := helloworld.HelloRequest{Name: "sandyskies"} output, err := app.SayHello(input) if err != nil { fmt.Println("err: ", err) } fmt.Println("result is:", output.Message) }
protoc-gen-go 的插件放在 TarsGo/tars/tools/pb2tarsgo , 需要要求Protocol Buffer 3.6.0以上。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
二, 跨语言微服务框架 - Istio环境搭建
当我们知道Istio是一个好东西,能够帮助我们快速实现微服务化中的一些关键节点,那么下一步就需要考虑怎么使用Istio了,Istio现在版本是和Kubernetes强关联在一起的,如果大家还不是太了解Kubernetes可以先从笔者的文章中了解,通过Kubernetes生态Istio可以非常方便的进行部署和使用。 附上: 喵了个咪的博客:w-blog.cn Istio官方地址:https://preliminary.istio.io/zh Istio中文文档:https://preliminary.istio.io/zh/docs/ PS : 此处基于当前最新istio版本1.0.3版本进行搭建和演示 一. Kubernetes准备工作 搭建部署Istio时需要先准备好Kubernetes环境,笔者这边使用的是Rancher进行环境的搭建,可以参考笔者的以下博文: Docker应用容器引擎介绍与搭建 - 喵了个咪博客空间 - 开源中国 Kubernetes(二) - 使用Rancher部署K8S集群(搭建Rancher) - 喵了个咪博客空间 - 开源中国 Kubernetes(三) ...
- 下一篇
聊聊LinkedHashMap
LinkedHashMap简介 LinkedHashMap是一个根据某种规则有序的hashmap。根据名字,我们也可以看出这个集合是有hash散列的功能的同时也有顺序。hashmap是无法根据某种顺序来访问数据的,例如放入集合的元素先后的顺序。list都有这个功能,可以根据放入集合的先后来访问具体的数据。这里大家也肯定是有疑问的,例如都已经使用了hash了,为什么还要去保证顺序访问。这个在后面的场景中解释。 LinkedHashMap的实现 当刚遇到这个集合的时候,我也疑惑,能同时满足条件的数据结构究竟是怎么样的。如果没有思考这个问题,还请看到这里好好想想。 ---------滑稽分割-------- 答案确实是没有这样的数据结构。他是两种结构的组合。一种是我们熟悉的hashmap。另外一种就是链表。数据存入集合的时候,先根据hashmap的流程存放入数组中。然后再根据链表的原则,进行链接。 如果看源码,也会发现其实没有多少方法。基本都是继承自hashmap的。 public class LinkedHashMap<K,V> extends HashMap<K,V&g...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- MySQL8.0.19开启GTID主从同步CentOS8
- Red5直播服务器,属于Java语言的直播服务器
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Hadoop3单机部署,实现最简伪集群
- CentOS8编译安装MySQL8.0.19
- CentOS7,8上快速安装Gitea,搭建Git服务器