使用thrift作为go和C++中间rpc及问题(一)
hgd7123 · · 8150 次点击 · · 开始浏览这两天因为工作需要查了一些跨语言的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 同样没有问题我就不截图了。
后面文章说下遇到的问题及分析。
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
这两天因为工作需要查了一些跨语言的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 同样没有问题我就不截图了。
后面文章说下遇到的问题及分析。