THRIFT 之 搭建环境和使用实例

  • 作者:邹祁峰
  • 邮箱:[email protected]
  • 博客:http://blog.csdn.net/qifengzou
  • 日期:2020.07.10 16:31
  • 转载请注明来自"祁峰"的CSDN博客

1.简单概述

Thrift is a lightweight, language-independent software stack for point-to-point RPC implementation. Thrift provides clean abstractions and implementations for data transport, data serialization, and application level processing. The code generation system takes a simple definition language as input and generates code across programming languages that uses the abstracted stack to build interoperable RPC clients and servers.
THRIFT 之 搭建环境和使用实例_第1张图片

Thrift makes it easy for programs written in different programming languages to share data and call remote procedures. With support for 28 programming languages, chances are Thrift supports the languages that you currently use.

Thrift is specifically designed to support non-atomic version changes across client and server code. This allows you to upgrade your server while still being able to service older clients; or have newer clients issue requests to older servers. An excellent community-provided write-up about thrift and compatibility when versioning an API can be found in the Thrift Missing Guide.

For more details on Thrift’s design and implementation, see the Thrift whitepaper included in this distribution, or at the README.md file in your particular subdirectory of interest.

2.安装流程

2.1 系统环境

由于不同的操作系统以及版本上的安装流程不一样,因此需要限定当前的系统环境:
操作系统:从docker库拉取centos7镜像(注:docker指令请自学

#docker pull centos:7 // 拉取centos7镜像, 假设镜像ID为"b5b4d78bc90c"
#docker run -it b5b4d78bc90c /bin/bash // 启动centos7容器, 假设容器ID为"e78bb3342abe"
#docker exec -it e78bb3342abe /bin/bash // 进入centos7容器

2.2 安装依赖

在centos7容器中执行如下指令安装thrift的依赖库:

#yum -y install automake libtool flex bison pkgconfig gcc-c++ boost-devel libevent-devel zlib-devel ruby-devel openssl-devel python-devel

2.3 编译安装

完成依赖环境的安装后,可在centos7容器中执行如下指令安装thrift程序:

#wget http://archive.apache.org/dist/thrift/0.13.0/thrift-0.13.0.tar.gz
#tar -zxvf thrift-0.13.0.tar.gz
#cd thrift-0.13.0
#./boostrash.sh
#./configure
#make
#make install

在进行编译的过程中,会出现各种问题。相关问题描述和解决方案如下:


  • 问题描述:执行make的过程中出现如下问题

g++: error: /usr/lib64/libboost_unit_test_framework.a: No such file or directory
make[4]: *** [Makefile:1275: processor_test] Error 1
make[4]: Leaving directory ‘/root/download/thrift-0.13.0/lib/cpp/test’
make[3]: *** [Makefile:1557: check] Error 2
make[3]: Leaving directory ‘/root/download/thrift-0.13.0/lib/cpp/test’
make[2]: *** [Makefile:1515: check-recursive] Error 1
make[2]: Leaving directory ‘/root/download/thrift-0.13.0/lib/cpp’
make[1]: *** [Makefile:585: check-recursive] Error 1
make[1]: Leaving directory ‘/root/download/thrift-0.13.0/lib’
make: *** [Makefile:686: check-recursive] Error 1

  • 解决方案:出现此问题的原因是操作系统版本不对,请拉取centos7的镜像并重新安装部署。

2.4 GOLANG环境

  • 安装GOLANG包

#wget https://golang.org/dl/go1.14.4.linux-amd64.tar.gz
#tar -zxvf go.1.14.4
#mv go /usr/local/src/go
#mkdir -p /data/go/src/

  • 设置环境变量
    在用户目录下的.bashrc中输入如下指令:

#export GOPATH=/data/go/
#export GOROOT=/usr/local/src/go/
#export PATH=$PATH:$GOROOT/bin/

  • 下载Thrift库

#yum -y install git
#go get https://github.com/apache/thrift.git

3.使用实例

假设当前我们想通过thrift实现的以下功能:

  • 功能描述:服务端将客户端传过来的数据将其转成大写,再返回给客户端。
  • 代码结构:以下代码结构在$GOPATH/src目录下
thrift
| - - client
|     `-- client.go
| - - example.thrift
` - - server
      `-- server.go
  • 定义远程过程
    example.thrift:客户端和服务端之间传输的数据结构,以及服务端提供的远程调用过程。其具体内容如下:
namespace go example // go表示golang

struct Data {
    1: string text
}

service format_data {
    Data do_format(1:Data data),
}

可通过thrift命令对该文件进行处理,生成指定语言的代码。比如生成golang代码:

#thrift --out . --gen go ./example.thrift

  • 客户端代码
    client.go:远程过程调用的客户端,客户端主动发起远程调用,并接收服务端处理后返回的结果。
package main

import (
    "fmt"
    "net"
    "context"

    "github.com/apache/thrift/lib/go/thrift"

    "thrift/example"
)

const (
    HOST = "127.0.0.1"
    PORT = "8080"
)

func main() {
    // 与服务端建立TCP长连接
    socket, err := thrift.NewTSocket(net.JoinHostPort(HOST, PORT))
    if err != nil {
        fmt.Printf("Create sokcet failed! errmsg:%s", err.Error())
        return
    }

    // 建立套接字与传输对象的关联
    transportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory())
    transport, err := transportFactory.GetTransport(socket)
    if nil != err {
        fmt.Printf("Get transport failed! errmsg:%s\n", err.Error())
        return
    }

    // 建立传输对象与自定义的远程过程的关联
    protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
    client := example.NewFormatDataClientFactory(transport, protocolFactory)
        
    if err := transport.Open(); err != nil {
        fmt.Printf("Open transport failed! errmsg:%s", err.Error())
        return
    }
    defer transport.Close()

    // 调用自定义的远程过程
    data := example.Data{Text: "hello, world!"}
    d, err := client.DoFormat(context.Background(), &data)
    if nil != err {
		fmt.Printf("Call rpc failed! errmsg:%s", err.Error())
		return
    }
    fmt.Println(d.Text)
}        
  • 服务端代码
    server.go:远程过程调用的服务端,服务端被动接收远程调用请求,并将处理后的结果返回给客户端。
package main

import (
    "context"
    "fmt"
    "strings"

    "github.com/apache/thrift/lib/go/thrift"

    "thrift/example"
)

// 实现远程过程
type FormatDataImpl struct{}

func (fdi *FormatDataImpl) DoFormat(ctx context.Context, data *example.Data) (r *example.Data, err error) {
    var data example.Data
    data.Text = strings.ToUpper(data.Text)

    return &data, nil
}

const (
    HOST = "127.0.0.1"
    PORT = "8080"
)

func main() {
    // 新建处理过程对象
    handler := &FormatDataImpl{}
    processor := example.NewFormatDataProcessor(handler)

    // 新建套接字对象
    socket, err := thrift.NewTServerSocket(HOST + ":" + PORT)
    if err != nil {
        fmt.Printf("Create socket failed! errmsg:%s", err.Error())
        return
    }

    // 新建传输对象
    transportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory())
    protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()

    // 新建服务对象:将处理过程、套接字、传输对象、协议类型进行关联
    server := thrift.NewTSimpleServer4(processor, socket, transportFactory, protocolFactory)
    fmt.Printf("Running! host:%s port:%s", HOST, PORT)

    // 启动服务
    server.Serve()
}

4.存在问题

在测试中,客户端能够正常的返回数据。但在实际生产环境中,存在多协程并发访问的情况,只有使用“连接池”才能真正发挥TCP长连接的高效优势。

你可能感兴趣的:(开发记录,远程过程调用)