這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
三個月沒在公司,回來後發現公司內部已經用上了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:// - ParaHelloString(para string) (r string, err error)// Parameters:// - ParaHelloInt(para int32) (r int32, err error)// Parameters:// - ParaHelloBoolean(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 errortransport, 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.goStarting 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.TTransportvar err errortransport, 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.gohello, world
參考文獻
- 【1】Apache Thrift - 可伸縮的跨語言服務開發架構 - developWorks
原文連結:Golang開發Thrift介面,轉載請註明來源!