Thrift 新版(>0.10.0)补漏

Thrift新版(>0.10.0)补漏

自从gRPC出来,Thrift与gPRC竞争日益激烈,他们都有不同的适合的应用场景,就目前来看,我个人更喜欢Thrift一点,最近使用了新版0.11.0以及未正式发布的0.12.0,发现了很大的问题:

  1. golang版本生成的package无法编译通过
  2. 客户端调用接口改变,变化很大
  3. 服务端接口函数改变

下面来解决这些问题:
首先,需要注意的是,package版本和thrift版本并不是严格的一一对应,除了C++版本,其他版本多多少少都会有与golang版本类似问题。这些问题产生的核心原因是后期版本对于Context的支持,导致接口和调用都产生了变化。

参考之前的博客点这里,我以类似项目为例,一步步解释:

  1. 新建golang项目thrifttest

  2. thrift文件,内容不变:

// mydef.thrift
service MathService {
    i32 Add(1:i32 A, 2:i32 B)
}
  1. 使用0.11.0版本thrift,在项目根目录生成package:
    thrift -0 . -out commdef --gen go mydef.thrift

  2. 参考之前博客,编写server文件

首先,你会发现,好多地方编译不过,对比如下可用代码,进行说明:

// server.go
package main

import (
	"context"
	"fmt"
	"thrifttest/commdef/mydef"
	"os"
	"git.apache.org/thrift.git/lib/go/thrift"
)

const (
	NetWorkAddr = "127.0.0.1:9090"
)

type MyMathService struct {
	mydef.MathService   // <<< 这里
}

func (this *MyMathService) Add(ctx context.Context, A int32, B int32) (r int32, err error) {  // <<< 这里
	r = A + B
	err = nil
	fmt.Println("Add", A, B)
	return
}

func main() {
	handler := &MyMathService{}
	processor := mydef.NewMathServiceProcessor(handler)

	serverTransport, err := thrift.NewTServerSocket(NetWorkAddr)
	if err != nil {
		fmt.Println("Error!", err)
		os.Exit(1)
	}
	transportFactory := thrift.NewTBufferedTransportFactory(512) // c++版本默认大小是512
	//protocolFactory := thrift.NewTCompactProtocolFactory()
	protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()

	server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory)
	fmt.Println("thrift server in", NetWorkAddr)
	server.Serve()
}

type MyMathService struct { 这里,是之前就不妥,没有实现接口(类似继承)关系
func (this *MyMathService) Add(ctx context.Context, A int32, B int32) (r int32, err error) { 之前版本没有ctx相关内容,这里需要加上。

按照如上修改,仍然无法编译,错误是not enough arguments in call to oprot.Flush, 这是thrift的go生成器的问题,没有添加对ctx的支持,我们手工找到,添加上。具体做法是将所有oprot.Flush()替换为oprot.Flush(ctx)

最终,服务端可以正常运行。关键的修改都在于ctx的处理问题。

  1. 参考之前博客,编写client

到这里你会发现,问题更严重,之前客户端的好多函数被声明取消,使用NewMathServiceClient替代,这里经过查找api,替换函数,完毕。
然后,问题又来了,在client调用时,也需要提供ctx参数,我们没有,这里可以使用一个空的ctx占位,context.Background()

完整代码如下:

package main

import (
	"context"
	"thrifttest/commdef/mydef"
	"fmt"
	"os"
	"git.apache.org/thrift.git/lib/go/thrift"
)

func main() {
	client_socket, _ := thrift.NewTSocket("127.0.0.1:9090")
	client_transport := thrift.NewTBufferedTransport(client_socket, 512)
	protocol := thrift.NewTBinaryProtocolTransport(client_transport)
	client_t := thrift.NewTStandardClient(protocol,protocol)

	client := mydef.NewMathServiceClient(client_t)

	if err := client_transport.Open(); err != nil {
		fmt.Fprintln(os.Stderr, "Error opening socket", err)
		os.Exit(1)
	}
	defer client_transport.Close()

	for i := int32(0); i < 100; i++ {
		nRet, _ := client.Add(context.Background(),i, i)
		fmt.Println(i, "Add", nRet)
	}
	fmt.Println("Over!")
}

服务器,客户端连接测试,完美!

这里出问题的ctx到底起什么作用呢?

建议多看看github上的issue,我了解到的大概意思是用来传递上下文环境,比如在http通信和普通通信时,添加额外参数,用来进行认证/校验…, 使用起来比较灵活,类似UI编程里面的UserData,以后遇到类似场景可以酌情使用。

你可能感兴趣的:(跨平台,Thrift,RPC,Thrift)