使用thrift作为go和C++中间rpc及问题(一)

hgd7123 · · 7400 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

这两天因为工作需要查了一些跨语言的rpc接口。我这里指的是包含序列化和tcp交互的。

主要查了一下以下三类:

1.ICE 这玩意不支持go,直接放弃。

2.GRPC,这玩意刚刚发布,还且全面使用C++11特性,我们生产环境目前还没升级,他依赖于protobuf 3.0.0版本,这个还是beta版,拿过来编译了下,依赖google的gmock。我的虚拟机上连不上去,只能暂时作罢。

3.Thrift,这个从0.9.1 就开始完美(官方)支持go语言了,那就拿这个操刀吧。

 

注:C++测试环境ubuntu12.04LTS  内核 3.2.0-23 GCC版本4.6.3  Go就在win7笔记本上跑的。

第一件事安装thrift,从官网下载最新thrift0.9.2版本。

编译安装参考 http://my.oschina.net/zc741520/blog/399049

libevent库我这边前段时间用到了就不用安装了,使用的版本是2.0.22-stable

 

GO版本thrift从这个地址

git-wip-us.apache.org/repos/asf/thrift.git/lib/go/thrift获取哦 
git.apache.org/thrift.git/lib/go/thrift永远超时。

thrift文件如下:

namespace cpp helloword
namespace go helloword

service Test
{
	string hello(1: string data);
}

我把world写错了...=_=!

thrift --gen cpp helloword.thrift  

thrift --gen go helloword.thrift

生成的C++文件么有问题,go里面要修改下test.go和contants.go的thrift库的位置

import(
	"helloword"
	"fmt"
	"git-wip-us.apache.org/repos/asf/thrift.git/lib/go/thrift"
	"os"
	"net"
)

 

下面开始撸C++代码了。

C++ server端代码

 1 #include <thrift/concurrency/ThreadManager.h>
 2 #include <thrift/concurrency/PosixThreadFactory.h>
 3 #include <thrift/protocol/TBinaryProtocol.h>
 4 #include <thrift/server/TSimpleServer.h>
 5 #include <thrift/server/TThreadPoolServer.h>
 6 #include <thrift/server/TThreadedServer.h>
 7 #include <thrift/transport/THttpServer.h>
 8 #include <thrift/transport/TServerSocket.h>
 9 #include <thrift/concurrency/ThreadManager.h>
10 #include <thrift/concurrency/PosixThreadFactory.h>
11 #include <thrift/protocol/TBinaryProtocol.h>
12 #include <thrift/server/TSimpleServer.h>
13 #include <thrift/server/TThreadPoolServer.h>
14 #include <thrift/server/TThreadedServer.h>
15 #include <thrift/transport/THttpServer.h>
16 #include <thrift/transport/TServerSocket.h>
17 #include <thrift/transport/TTransportUtils.h>
18 #include <thrift/TToString.h>
19 #include <iostream>
20 #include <string>
21 #include "Test.h"
22 #include <boost/bind.hpp>
23 #include <boost/function.hpp>
24 #include <thrift/protocol/TBinaryProtocol.h>
25 #include <thrift/transport/TSocket.h>
26 #include <thrift/transport/TTransportUtils.h>
27 using namespace std;
28 using namespace apache::thrift;
29 using namespace apache::thrift::concurrency;
30 using namespace apache::thrift::protocol;
31 using namespace apache::thrift::transport;
32 using namespace apache::thrift::server;
33 using namespace ::apache::thrift;
34 using namespace ::apache::thrift::protocol;
35 using namespace ::apache::thrift::transport;
36 using namespace ::boost;
37 using namespace ::helloword;
38 using ::boost::bind;
39 
40 class TestHandler : virtual public TestIf {
41  public:
42   TestHandler() { }
43 
44   void hello(std::string& _return, const std::string& data) {
45 //    if(data=="ping")
46       printf("[%d] recv ping\n", (int)time(NULL));
47   _return = "pong";
48   printf("[%d] send pong\n", (int)time(NULL));
49 }};
50 
51 int main(int argc, char **argv) {
52   int port = 9000;
53   shared_ptr<TestHandler> handler(new TestHandler());
54   shared_ptr<TProcessor> processor(new TestProcessor(handler));
55   shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
56   shared_ptr<TTransportFactory> transportFactory(new TTransportFactory());
57   shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
58   TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
59   server.serve();
60   return 0;
61 }

C++ Client端代码

 1 #include <iostream>
 2 #include <string>
 3 #include <thrift/protocol/TBinaryProtocol.h>
 4 #include <thrift/transport/TSocket.h>
 5 #include <thrift/transport/TTransportUtils.h>
 6 #include "Test.h"
 7 using namespace std;
 8 using namespace apache::thrift;
 9 using namespace apache::thrift::protocol;
10 using namespace apache::thrift::transport;
11 using namespace helloword;
12 int main(int argc,char ** argv) {
13         string server = "127.0.0.1";
14         if(argc>1)server= argv[1];
15         boost::shared_ptr<TTransport> socket(new TSocket(server, 9000));
16         boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
17         boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
18         TestClient client(protocol);
19 try {
20         transport->open();
21         string cao="haha";
22         client.hello(cao,cao);
23         cout << "Hello"<< cao << endl;
24 }
25 catch(apache::thrift::TApplicationException &e)
26 {
27 cout<<e.what()<<endl;
28 }
29         return 0;
30 }

 

编译server端

g++ -o server server.cpp Test.cpp helloword_constants.cpp helloword_types.cpp -lthrift -lboost_system

编译Client端

g++ -o client client.cpp Test.cpp helloword_constants.cpp helloword_types.cpp -lthrift -lboost_system

测试C++没有问题。


写GO的代码:

GO server端

package main

import(
	"helloword"
	"fmt"
	"git-wip-us.apache.org/repos/asf/thrift.git/lib/go/thrift"
	"os"
	
)

const (
	NetworkAddr = "192.168.20.76:9000"
)

type Test struct{
}

func (this *Test) Hello(data string)(r string, err error){  //注意这里,我的thrift代码里面写的接口时小写的hello 在test.go里面被fmt成大写。
	fmt.Println("rec", data)
	r = data+"haha"
	fmt.Println("send", r)
	return
}

func main(){
	transportFactory := thrift.NewTTransportFactory()
    protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
    //protocolFactory := thrift.NewTCompactProtocolFactory()
 
    serverTransport, err := thrift.NewTServerSocket(NetworkAddr)
    if err != nil {
        fmt.Println("Error!", err)
        os.Exit(1)
    }
 
    handler := &Test{}
    processor := helloword.NewTestProcessor(handler)
 
    server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory)
    fmt.Println("thrift server in", NetworkAddr)
    server.Serve()
}

GO client代码

package main

import(
	"helloword"
	"fmt"
	"git-wip-us.apache.org/repos/asf/thrift.git/lib/go/thrift"
	"os"
	"net"
)

func main (){
	transportFactory := thrift.NewTTransportFactory()
	protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
	transport ,err := thrift.NewTSocket(net.JoinHostPort("127.0.0.1","9000"))
	
	if err != nil {
        fmt.Fprintln(os.Stderr, "error resolving address:", err)
        os.Exit(1)
    }
	
	 useTransport := transportFactory.GetTransport(transport)
	 client := helloword.NewTestClientFactory(useTransport, protocolFactory)
	if err := transport.Open(); err != nil {
        fmt.Fprintln(os.Stderr, "Error opening socket to server", " ", err)
        os.Exit(1)
    }
    defer transport.Close()
	
	for i := 0; i < 2; i++ {
        r1, e1 := client.Hello("hello")
        fmt.Println(i, "Call->", r1, e1)
    }
	
 
}

当然测试也没有问题。

 

下面就是交叉访问了。

当然基于以上代码同样没有问题,哈哈哈哈,因为问题被我K了啊 。附上截图。

C++ client端 与 GO server端

 

GO client VS C++ server 同样没有问题我就不截图了。

后面文章说下遇到的问题及分析。

 


有疑问加站长微信联系(非本文作者)

本文来自:博客园

感谢作者:hgd7123

查看原文:使用thrift作为go和C++中间rpc及问题(一)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

7400 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传