zoukankan      html  css  js  c++  java
  • Go thrift使用举例

    thrift 最初是 facebook 开发使用的 rpc 通信框架,后来贡献给了 apache 基金会,出来得比较早,几乎支持所有的后端语言,使用非常广泛,是不可不知的一个网络框架。

    和 grpc 一样,需要先定义通信协议,然后实现自己业务逻辑。

    下面介绍其使用方法。

    下载go thrift 库

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

    注意:此时的版本库时间是2017.7,因此当时不支持context。

    下载协议转换工具thrift

    $ wget http://www-us.apache.org/dist/thrift/0.10.0/thrift-0.10.0.tar.gz
    $ tar -xzvf thrift-0.10.tar.gz
    $ cd thrift-0.10.0
    $ ./configure  --prefix=/usr
    $ make -j8
    $ [sudo] make install 
    

    thrift工具安装过程中可能会报错,关于如何安装依赖,请参看Building Apache Thrift on CentOS 6.5.

    另外,一个问题,编译thrift时报错:

    GOPATH=pwd /home/lanyang/work/pkgs/go/bin/go get github.com/golang/mock/gomock
    package golang.org/x/net/context: unrecognized import path "golang.org/x/net/context" (https fetch: Get https://golang.org/x/net/context?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)

    网上各种方法都试过,无法搞定。

    根据报错提示,注释掉 test/go/Makefile 文件中

    #GOPATH=pwd $(GO) get github.com/golang/mock/gomock

    然后,手动下载gomock。
    由于gomock依赖net,所以先下载net。
    直接 go get golang.org/x/net 会失败,是由于被墙。
    可采用
    从https://github.com/golang/net下载(可以直接 go get github.com/golang/net),然后把目录改成golang.org/x/net。

    完成net下载和配置后,接着下载mock

    $ go get github.com/golang/mock/gomock
    

    最后编译通过。

    定义协议文件echo.thrift

    在GOPATH目录下创建thriftExample目录,在该目录创建文件echo.thrift,内容如下:

    namespace go echo
    
    struct EchoReq {
        1: string msg;
    }
    
    struct EchoRes {
        1: string msg;
    }
    
    service Echo {
        EchoRes echo(1: EchoReq req);
    }
    

    协议转换

    命令格式

    thrift --gen <language> <Thrift filename>
    

    至于thrift的用法,可以使用thrift -help查看帮助。

    执行以下命令会生成 gen-go 文件夹,这个过程其实是将上面的协议翻译成 golang 代码。

    $ thrift -r --gen go echo.thrift 
    

    生成的gen-go 文件夹包括以下文件

    [lanyang@localhost thriftExample]$ ll gen-go/ -R
    gen-go:
    total 4
    drwxrwxr-x. 3 lanyang lanyang 4096 May 13 23:18 echo
    
    gen-go/echo:
    total 28
    -rw-rw-r--. 1 lanyang lanyang   349 May 13 23:18 echo-consts.go
    -rw-rw-r--. 1 lanyang lanyang 16161 May 13 23:18 echo.go
    drwxrwxr-x. 2 lanyang lanyang  4096 May 13 23:18 echo-remote
    -rw-rw-r--. 1 lanyang lanyang   159 May 13 23:18 GoUnusedProtection__.go
    
    gen-go/echo/echo-remote:
    total 4
    -rwxr-xr-x. 1 lanyang lanyang 4017 May 13 23:18 echo-remote.go
    

    其中,echo.go是生成的类型和方法定义,echo-remote是client示例代码。

    示例代码

    下面简单举例说明其使用。

    服务端代码

    服务端代码server.go如下:

    package main
    
    import (
    
        "fmt"
        "git.apache.org/thrift.git/lib/go/thrift"
    
        "thriftExample/gen-go/echo"
    
    )
    
    
    type EchoServer struct {
    }
    
    func (e *EchoServer) Echo(req *echo.EchoReq) (*echo.EchoRes, error) {
        fmt.Printf("message from client: %v
    ", req.GetMsg())
    
        res := &echo.EchoRes{
            Msg: "success",
        }
    
        return res, nil
    }
    
    func main() {
        transport, err := thrift.NewTServerSocket(":9898")
        if err != nil {
            panic(err)
        }
    
        handler := &EchoServer{}
        processor := echo.NewEchoProcessor(handler)
    
        transportFactory := thrift.NewTBufferedTransportFactory(8192)
        protocolFactory := thrift.NewTCompactProtocolFactory()
        server := thrift.NewTSimpleServer4(
            processor,
            transport,
            transportFactory,
            protocolFactory,
        )
    
        if err := server.Serve(); err != nil {
            panic(err)
        }
    }
    

    客户端代码

    客户端代码client.go如下

    package main
    
    import (
    	"fmt"
    	"log"
    	"net"
    	"os"
    
    	"git.apache.org/thrift.git/lib/go/thrift"
    
    	"thriftExample/gen-go/echo"
    )
    
    func main() {
    	transportFactory := thrift.NewTBufferedTransportFactory(8192)
    	protocolFactory := thrift.NewTCompactProtocolFactory()
    
    	transport, err := thrift.NewTSocket(net.JoinHostPort("127.0.0.1", "9898"))
    	if err != nil {
    		fmt.Fprintln(os.Stderr, "error resolving address:", err)
    		os.Exit(1)
    	}
    
    	useTransport, err := transportFactory.GetTransport(transport)
    	client := echo.NewEchoClientFactory(useTransport, protocolFactory)
    	if err := transport.Open(); err != nil {
    		fmt.Fprintln(os.Stderr, "Error opening socket to 127.0.0.1:9898", " ", err)
    		os.Exit(1)
    	}
    	defer transport.Close()
    
    	req := &echo.EchoReq{Msg:"You are welcome."}
    	res, err := client.Echo(req)
    	if err != nil {
    		log.Println("Echo failed:", err)
    		return
    	}
    
    	log.Println("response:", res.Msg)
    	fmt.Println("well done")
    
    }
    

    server ouput:

    $ ./server
    message from client: You are welcome.

    client output:

    $ ./client
    2018/05/19 11:12:37 response: success
    well done

    注意:服务端和客户端进行通信时使用的协议一定要相同,例如上例中的,transport factory是 buffer transport factroy,protocol factory 是compact protcol。

    参考

    github
    https://github.com/apache/thrift/

    github go thrift
    https://github.com/apache/thrift/tree/master/lib/go

    Building Apache Thrift on CentOS 6.5
    http://thrift.apache.org/docs/install/centos

    不同系统如何安装thrift工具
    http://thrift.apache.org/docs/install/

    go thrift example(很有参考价值)
    https://github.com/apache/thrift/tree/master/tutorial/go/src

    golang 网络框架之 thrift
    https://segmentfault.com/a/1190000013127570

    Golang通过Thrift框架完美实现跨语言调用
    https://my.oschina.net/qinerg/blog/165285

    安装thrift
    http://www.cnblogs.com/yjf512/p/4334622.html

    https://thrift.apache.org/tutorial/go

  • 相关阅读:
    文件和目录之文件访问权限
    文件和目录之设置用户ID和设置组ID
    文件和目录之文件类型
    文件和目录之stat、fstat和lstat函数
    实用编程技术之多个头文件中变量的重复定义
    带缓冲I/O和不带缓冲I/O的区别与联系
    如何使用nodejs发邮件
    cosmic_download-AsyncPool待修正
    python性能分析之line_profiler模块
    python性能分析之cProfile模块
  • 原文地址:https://www.cnblogs.com/lanyangsh/p/9059894.html
Copyright © 2011-2022 走看看