golang 網路框架之 thrift

hatlonely發表於2018-02-04

thrift 最初是 facebook 開發使用的 rpc 通訊框架,後來貢獻給了 apache 基金會,出來得比較早,幾乎支援所有的後端語言,使用非常廣泛,是不可不知的一個網路框架

grpc 一樣,需要先定義通訊協議,然後實現自己業務邏輯,下面還是通過一個簡單示例(之前的 echo 程式)說明 thrift 的用法,下面示例使用的完整程式碼在下列地址: 實現檔案:<https://github.com/hatlonely/hellogolang/tree/master/cmd/thrift> 協議檔案:<https://github.com/hatlonely/hellogolang/tree/master/api/echo_thrift>

簡單 echo 服務

獲取 thrift

go get git.apache.org/thrift.git/lib/go

定義協議檔案

namespace go echo

struct EchoReq {
    1: string msg;
}

struct EchoRes {
    1: string msg;
}

service Echo {
    EchoRes echo(1: EchoReq req);
}

執行 thrift -r --gen go echo.thrift 命令會生成 gen-go 資料夾,這個過程其實是將上面的協議翻譯成 golang 程式碼

這個命令依賴於 thrift 工具,可以通過下面命令獲取

Mac

brew install thrift

Linux

wget http://www-us.apache.org/dist/thrift/0.11.0/thrift-0.11.0.tar.gz
tar -xzvf thrift-0.11.0.tar.gz
cd thrift-0.11.0
./configure
make -j8
[sudo] make install 

實現服務端

type EchoServerImp struct {
}

func (e *EchoServerImp) Echo(ctx context.Context, req *echo.EchoReq) (*echo.EchoRes, error) {
    fmt.Printf(&quot;message from client: %v\n&quot;, req.GetMsg())

    res := &amp;echo.EchoRes{
        Msg: req.GetMsg(),
    }

    return res, nil
}

func main() {
    transport, err := thrift.NewTServerSocket(&quot;:3000&quot;)
    if err != nil {
        panic(err)
    }

    processor := echo.NewEchoProcessor(&amp;EchoServerImp{})
    server := thrift.NewTSimpleServer4(
        processor,
        transport,
        thrift.NewTBufferedTransportFactory(8192),
        thrift.NewTCompactProtocolFactory(),
    )
    if err := server.Serve(); err != nil {
        panic(err)
    }
}

這個過程和 grpc 類似,不同的地方在於,thrift 支援更多的伺服器型別,支援不同的協議打包方式,方便使用者選擇,這裡的 compact 協議是一種壓縮的協議,使用比較多

實現客戶端

func main() {
    var transport thrift.TTransport
    var err error
    transport, err = thrift.NewTSocket(&quot;localhost:3000&quot;)
    if err != nil {
        fmt.Errorf(&quot;NewTSocket failed. err: [%v]\n&quot;, err)
        return
    }

    transport, err = thrift.NewTBufferedTransportFactory(8192).GetTransport(transport)
    if err != nil {
        fmt.Errorf(&quot;NewTransport failed. err: [%v]\n&quot;, err)
        return
    }
    defer transport.Close()

    if err := transport.Open(); err != nil {
        fmt.Errorf(&quot;Transport.Open failed. err: [%v]\n&quot;, err)
        return
    }

    protocolFactory := thrift.NewTCompactProtocolFactory()
    iprot := protocolFactory.GetProtocol(transport)
    oprot := protocolFactory.GetProtocol(transport)
    client := echo.NewEchoClient(thrift.NewTStandardClient(iprot, oprot))

    var res *echo.EchoRes
    res, err = client.Echo(context.Background(), &amp;echo.EchoReq{
        Msg: strings.Join(os.Args[1:], &quot; &quot;),
    })
    if err != nil {
        fmt.Errorf(&quot;client echo failed. err: [%v]&quot;, err)
        return
    }

    fmt.Printf(&quot;message from server: %v&quot;, res.GetMsg())
}

這個 client 相對複雜一些,需要和 server 端設定一致的打包方式,如果不一致會出現通訊失敗,這一點需要特別注意一下

參考連結

> 轉載請註明出處 > 本文連結:<http://hatlonely.github.io/2018/02/04/golang-%E7%BD%91%E7%BB%9C%E6%A1%86%E6%9E%B6%E4%B9%8B-thrift/>

更多原創文章乾貨分享,請關注公眾號
  • golang 網路框架之 thrift
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章