三个月没在公司,回来后发现公司内部已经用上了facebook开源的Apache Thrift。大概看了一下介绍,传统接口编写是使用json或者xml作为信息格式进行传输。一般Web Service里面,SOAP这种,使用的就是xml(不过我从来没用过。。);而轻量级网络服务REST,则用的是json作为传输媒介。json相较于xml,传输的内容变少了许多,传输更加便捷。这两种都是基于HTTP的传输方式。
而Apache Thrift,是更加轻量级的Web Service。本科做网络游戏的时候也接触过,叫RPC(Remote Procudure Call,远程过程调用)。这应该也算是一种RPC吧。调用起来更加简单,根本不需要发送HTTP请求,解析返回结果这些操作。只需要预先定义好类和对应函数,调用的时候创建一个类,调用函数即可。返回内容也是直接映射到类当中的。
完整地了解了一下Apache Thrift,这篇文章主要介绍hello, world的编写。如果你之前还没接触过Thrift,可以参考我之前写过的几篇文章所谓参考。
- Apache Thrift安装——如何离线完成go get——安装Apache Thrift有感
- 编译官方例子时会涉及到命令行参数的解析——Golang 处理命令行启动参数
- 服务器端要实现定义好的接口,接口相关知识——Golang 接口实现
Apache Thrift给了一个完整的例子,包含很多语言版本的,Golang的完整代码可以看这里。文档方面官网没对这个例子介绍多少,代码也没贴全,找到这个就好办多了,直接复制下来编译就行了。其他语言的实现,返回向上一级目录即可。
这篇文章要讲的hello, world 主要根据developWorks的文章Apache Thrift - 可伸缩的跨语言服务开发框架进行介绍。
Thrfit文件定义如下:Hello.thrift。接口Hello,包含五个函数,五个都必须实现,否则编译器会认为该接口并没有被实现。
namespace java service.demo
service Hello{
string helloString(1:string para)
i32 helloInt(1:i32 para)
bool helloBoolean(1:bool para)
void helloVoid()
string helloNull()
}
.thrfit
文件就是定义了一套接口。通过命令可以生成对应语言的接口定义。会在当前目录下生成gen-go
文件夹,把里面的内容放到gopath
里即可。
$ thrift --gen go Hello.thrift
自动生成的接口定义如下hello.go
:
type Hello interface {
// Parameters:
// - Para
HelloString(para string) (r string, err error)
// Parameters:
// - Para
HelloInt(para int32) (r int32, err error)
// Parameters:
// - Para
HelloBoolean(para bool) (r bool, err error)
HelloVoid() (err error)
HelloNull() (r string, err error)
}
上述操作用来生成接口,有了接口之后,就是要实现接口、开发客户端和开发服务器端这三个部分。参考的例子是使用大Java实现的,果断用Go重写helloimpl.go
。Go语言实现接口可以参考Golang 接口实现。
type HelloHandler struct {
}
func NewHelloHandler() *HelloHandler {
return &HelloHandler{}
}
func (h *HelloHandler) HelloString(para string) (string, error) {
return "hello, world", nil
}
func (h *HelloHandler) HelloBoolean(para bool) (r bool, err error) {
return para, nil
}
func (h *HelloHandler) HelloInt(para int32) (r int32, err error) {
return para, nil
}
func (h *HelloHandler) HelloVoid() (err error) {
return nil
}
func (h *HelloHandler) HelloNull() (r string, err error) {
return "hello null", nil
}
服务器端的实现helloserver.go
func runServer(transportFactory thrift.TTransportFactory, protocolFactory thrift.TProtocolFactory, addr string) error {
var err error
transport, err = thrift.NewTServerSocket(addr)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%T\n", transport)
handler := NewHelloHandler()
processor := hello.NewHelloProcessor(handler)
server := thrift.NewTSimpleServer4(processor, transport, transportFactory, protocolFactory)
fmt.Println("Starting the simple server... on ", addr)
return server.Serve()
}
func main() {
transportFactory := thrift.NewTTransportFactory()
protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
transportFactory = thrift.NewTBufferedTransportFactory(8192)
runServer(transportFactory, protocolFactory, "localhost:9090")
}
启动服务器
$ go run helloserver.go helloimpl.go
Starting the simple server... on localhost:9090
客户端代码helloclient.go
func handleClient(client *hello.HelloClient) error {
str, err := client.HelloString("")
fmt.Println(str)
fmt.Println("----------------")
return err
}
func runClient(transportFactory thrift.TTransportFactory, protocolFactory thrift.TProtocolFactory, addr string) error {
var transport thrift.TTransport
var err error
transport, err = thrift.NewTSocket(addr)
if err != nil {
fmt.Println("Error opening socket:", err)
return err
}
transport = transportFactory.GetTransport(transport)
defer transport.Close()
if err := transport.Open(); err != nil {
return err
}
fmt.Println(transport, protocolFactory)
return handleClient(hello.NewHelloClientFactory(transport, protocolFactory))
}
func main() {
transportFactory := thrift.NewTTransportFactory()
protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
transportFactory = thrift.NewTBufferedTransportFactory(8192)
runClient(transportFactory, protocolFactory, "localhost:9090")
}
启动客户端及运行结果:
$ go run helloclient.go
hello, world
参考文献
原文链接:Golang开发Thrift接口,转载请注明来源!
有疑问加站长微信联系(非本文作者)