• Go -- RPC 之 Thrift


    Thrift 简介:

    Thrift 是一款高性能、开源的 RPC 框架,产自 Facebook 后贡献给了 Apache,Thrift 囊括了整个 RPC 的上下游体系,自带序列化编译工具,因为 Thrift 采用的是二进制序列化,并且与 gRPC 一样使用的都是长连接建立 client 与 server 之间的通讯,相比于比传统的使用XML,JSON,SOAP等短连接的解决方案性能要快得多。
    本篇只介绍 Golang 关于 Thrift 的基础使用。

    安装

    • 安装 Thrift 的 Golang 库有两种方案:

      1. 直接通过 go get 命令安装,缺点是因为不可抗拒的网络因素大部分人可能会失败:$ go get git.apache.org/thrift.git/lib/go/thrift
      2. 通过源码安装:
        • 在 $GOPATH 的 src 目录下创建多层级目录:git.apache.org/thrift.git/lib/go
        • 从 github 上下载 thrift 0.10.0 的源码 ,解压后进入 thrift-0.10.0/lib/go 目录下,将 thrift 目录 copy 到刚创建的 $GOPATH/src/git.apache.org/thrift.git/lib/go 目录下
        • 在任意目录下执行 $ go install git.apache.org/thrift.git/lib/go/thrift 就完成了 golang 的 thrift 库的安装
    • 安装 Thrift 的 IDL 编译工具(可省去)

      1. windows 平台下安装:

        直接下载:thrift complier 下载地址,下载完成后改名为:thrift.exe 并将其放入到系统环境变量下即可使用

      2. Linux 平台下安装:

        从 github 上下载 thrift 0.10.0 的源码,解压后进入:thrift-0.10.0/compiler/cpp 目录执行如下命令完成编译后,将其放入到系统环境变量下即可使用:
        $ mkdir cmake-build
        $ cd cmake-build
        $ cmake ..
        $ make

    • 验证是否安装成功:

      $ thrift -version,如果打印出来:Thrift version 0.10.0 表明 complier 安装成功

    实践:

    下面我们使用 Thrift 定义一个接口,该接口实现对传入的数据进行大写的格式化处理。

    • 创建 golang 项目 ThriftDemo 工程:

    Paste_Image.png
    1. client目录下的 client.go 实现了客户端用于发送数据并打印接收到 server 端处理后的数据
    2. server 目录下的 server.go 实现了服务端用于接收客户端发送的数据,并对数据进行大写处理后返回给客户端
    3. thrift_file 用于存放 thrift 的 IDL 文件: *.thrift
    • 定义 Thrift RPC 接口

    example.thrift:

    namespace py example
    
    struct Data {
        1: string text
    }
    
    service format_data {
        Data do_format(1:Data data),
    }
    • 编译 thrift 文件

      进入 thrift_file 目录执行:$ thrift -out .. --gen go example.thrift,就会在 thrift_file 的同级目录下生成 golang 的包:example,其中 format_data-remote 是生成的测试代码可以不用特别关注


    Paste_Image.png
    • 实现 server 端:
    package main
    
    import (
        "ThriftDemo/example"
        "strings"
        "git.apache.org/thrift.git/lib/go/thrift"
        "fmt"
        "log"
    )
    
    type FormatDataImpl struct {}
    
    func (fdi *FormatDataImpl) DoFormat(data *example.Data) (r *example.Data, err error){
        var rData example.Data
        rData.Text = strings.ToUpper(data.Text)
    
        return &rData, nil
    }
    
    const (
        HOST = "localhost"
        PORT = "8080"
    )
    
    func main() {
    
        handler := &FormatDataImpl{}
        processor := example.NewFormatDataProcessor(handler)
        serverTransport, err := thrift.NewTServerSocket(HOST + ":" + PORT)
        if err != nil {
            log.Fatalln("Error:", err)
        }
        transportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory())
        protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
    
        server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory)
        fmt.Println("Running at:", HOST + ":" + PORT)
        server.Serve()
    }
    • 实现 client 端
    package main
    
    import (
        "git.apache.org/thrift.git/lib/go/thrift"
        "net"
        "fmt"
        "ThriftDemo/example"
        "log"
    )
    
    const (
        HOST = "localhost"
        PORT = "8080"
    )
    
    func main()  {
        tSocket, err := thrift.NewTSocket(net.JoinHostPort(HOST, PORT))
        if err != nil {
            log.Fatalln("tSocket error:", err)
        }
        transportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory())
        transport := transportFactory.GetTransport(tSocket)
        protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
    
        client := example.NewFormatDataClientFactory(transport, protocolFactory)
    
        if err := transport.Open(); err != nil {
            log.Fatalln("Error opening:", HOST + ":" + PORT)
        }
        defer transport.Close()
    
    
        data := example.Data{Text:"hello,world!"}
        d, err := client.DoFormat(&data)
        fmt.Println(d.Text)
    }
    • 执行验证结果:
      1. 先启动 server,之后再执行 client
      2. client 侧控制台如果打印的结果为: HELLO,WORLD! ,证明 Thrift 的 RPC 接口定义成功
  • 相关阅读:
    Python生成随机数
    Python安装包国内镜像源
    SpringMVC之从ExceptionHandlerExceptionResolver源码解析之参数解析器和返回值处理器
    SpringMVC是怎么把get请求参数封装到对象中的?
    SpringMVC之全局异常解析之ExceptionHandler注解与RestControllerAdvice注解
    【转载】利用 IDEA HTTP 请求文件访问 API 接口
    Dubbo整合ZooKeeper3.6.x时出现zookeeper not connected
    Java中如何根据值获取泛型枚举对象及EnumUtil的必要性
    SpringBoot整合Dubbo3.x关于curator和zookeeper版本选型的思考
    SpringMVC之从ExceptionHandlerMethodResolver源码解析与@ExceptionHandler的使用注意点
  • 原文地址:https://www.cnblogs.com/mafeng/p/6813236.html
Copyright © 2020-2023  润新知