Thrift RPC Example
run
Please be directly used without pulling any dependencies.
cd $GOPATH/src
git clone https://github.com/hunterhug/thrift_example.git
go build server.gp
go build client.go
./server
./client
$GOPATH
Environment variables, replace your local path.
Specific use, details
gRPC transmission scheme is RPC Google research, thrift is facebook, we have to regulate the input and output via IDL (Interface Definition Language) interface definition language.
Download: https://thrift.apache.org/download
Ubuntu system installation
sudo apt-get install automake bison flex git libboost-all-dev libevent-dev libssl-dev libtool make pkg-config build-essential g++
tar xvf thrift-0.12.0.tar.gz
./bootstrap.sh
./configure
make
sudo make install
sudo ldconfig
Please install Windows system binaries directly.
Establish thrift file
New timeRPC.thrift
:
service timeServe {
i32 getCurrtentTime()
}
C ++ server
You can ignore the C++
section, jump directly to the Golang
section.
carried out:
thrift --gen cpp timeRPC.thrift
In the current directory called "gen-cpp" folder, which contains the code needed.
├── timeRPC_constants.cpp
├── timeRPC_constants.h
├── timeRPC_types.cpp
├── timeRPC_types.h
├── timeServe.cpp
├── timeServe.h
└── timeServe_server.skeleton.cpp
Modify timeServe_server.skeleton.cpp
:
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.
#include "timeServe.h"
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
class timeServeHandler : virtual public timeServeIf {
public:
timeServeHandler() {
// Your initialization goes here
}
int32_t getCurrtentTime() {
// Your implementation goes here
auto t = time(nullptr);
printf("getCurrtentTime: %ld\n", t);
return t;
}
};
int main(int argc, char **argv) {
int port = 9090;
::apache::thrift::stdcxx::shared_ptr<timeServeHandler> handler(new timeServeHandler());
::apache::thrift::stdcxx::shared_ptr<TProcessor> processor(new timeServeProcessor(handler));
::apache::thrift::stdcxx::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
::apache::thrift::stdcxx::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
::apache::thrift::stdcxx::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
server.serve();
return 0;
}
We achieved getCurrtentTime
this way.
Compile:
g++ -std=c++11 -o cpp-server timeRPC_constants.cpp timeRPC_types.cpp timeServe.cpp timeServe_server.skeleton.cpp -lthrift
View:
ldd cpp-server
linux-vdso.so.1 => (0x00007ffee83b4000)
libthrift-0.12.0.so => /usr/local/lib/libthrift-0.12.0.so (0x00007f0200e34000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f0200ab2000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f020089c000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f02004d2000)
libssl.so.1.0.0 => /lib/x86_64-linux-gnu/libssl.so.1.0.0 (0x00007f0200269000)
libcrypto.so.1.0.0 => /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f01ffe24000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f01ffc07000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f01ff8fe000)
/lib64/ld-linux-x86-64.so.2 (0x00007f02010fe000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f01ff6fa000)
run:
./cpp-server
C ++ client
In gen-cpp
upper New client.cpp
:
// system
#include <iostream>
// lib
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TTransportUtils.h>
#include <boost/shared_ptr.hpp>
using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using boost::shared_ptr;
// project
#include "gen-cpp/timeServe.h"
int main() {
std::shared_ptr<TTransport> socket(new TSocket("localhost", 9090));
std::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
timeServeClient client(protocol);
// open connect
transport->open();
auto timeNow = client.getCurrtentTime();
std::cout << timeNow << std::endl;
transport->close();
return 0;
}
Compile it:
g++ -std=c++11 -o cpp-client client.cpp gen-cpp/timeServe.cpp -lthrift
run:
./cpp-client
1553223392
Golang server
Modify timeRPC.thrift
:
service timeServe {
i32 getCurrtentTime()
}
service time2Serve {
i32 getCurrtentTime()
}
View:
go env
GOPATH="/opt/gocode"
Which $GOPATH
is /opt/gocode
.
To prepare the necessary library:
mkdir -p $GOPATH/src/github.com/apache
cd $GOPATH/src/github.com/apache
git clone https://github.com/apache/thrift.git
carried out:
thrift --gen go timeRPC.thrift
In the current directory called "gen-go" folder, which contains the code needed.
└── timerpc
├── GoUnusedProtection__.go
├── timeRPC-consts.go
├── timeRPC.go
└── time_serve-remote
└── time_serve-remote.go
In gen-go
upper New server.go
:
package main
import (
"context"
"fmt"
"github.com/apache/thrift/lib/go/thrift"
"net"
"os"
"thrift_example/gen-go/timerpc"
"time"
)
type MyTime struct{}
func (s *MyTime) GetCurrtentTime(_ context.Context) (r int32, err error) {
t := int32(time.Now().Unix())
fmt.Printf("come on:%d\n", t)
return t, nil
}
type MyTime2 struct{}
func (s *MyTime2) GetCurrtentTime(_ context.Context) (r int32, err error) {
t := int32(time.Now().Unix())
fmt.Printf("come on2:%d\n", t)
return t, nil
}
func main() {
// 创建服务器
serverTransport, err := thrift.NewTServerSocket(net.JoinHostPort("127.0.0.1", "9090"))
if err != nil {
fmt.Println("Error!", err)
os.Exit(1)
}
// 创建二进制协议
protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
transportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory())
// 创建Processor,用一个端口处理多个服务
multiProcessor := thrift.NewTMultiplexedProcessor()
MyTimeProcessor := timerpc.NewTimeServeProcessor(new(MyTime))
MyTime2Processor := timerpc.NewTimeServeProcessor(new(MyTime2))
// 给每个service起一个名字
multiProcessor.RegisterProcessor("mytime", MyTimeProcessor)
multiProcessor.RegisterProcessor("mytime2", MyTime2Processor)
server := thrift.NewTSimpleServer4(multiProcessor, serverTransport, transportFactory, protocolFactory)
fmt.Println("start")
if err := server.Serve(); err != nil {
panic(err)
}
// 退出时停止服务器
defer server.Stop()
}
Compile and run:
go build server.go
./server
Golang client
In gen-go
upper New client.go
:
package main
import (
"context"
"fmt"
"github.com/apache/thrift/lib/go/thrift"
"net"
"os"
"thrift_example/gen-go/timerpc"
)
func main() {
// 先建立和服务器的连接的socket,再通过socket建立Transport
socket, err := thrift.NewTSocket(net.JoinHostPort("127.0.0.1", "9090"))
if err != nil {
fmt.Println("Error opening socket:", err)
os.Exit(1)
}
transport := thrift.NewTFramedTransport(socket)
// 创建二进制协议
protocol := thrift.NewTBinaryProtocolTransport(transport)
// 打开Transport,与服务器进行连接
if err := transport.Open(); err != nil {
fmt.Fprintln(os.Stderr, "Error opening socket to "+"localhost"+":"+"9090", err)
os.Exit(1)
}
defer transport.Close()
// 接口需要context,以便在长操作时用户可以取消RPC调用
ctx := context.Background()
// 使用Mytime服务
MyTimeProtocol := thrift.NewTMultiplexedProtocol(protocol, "mytime")
// 创建代理客户端,使用TMultiplexedProtocol访问对应的服务
c := thrift.NewTStandardClient(MyTimeProtocol, MyTimeProtocol)
client := timerpc.NewTimeServeClient(c)
res, err := client.GetCurrtentTime(ctx)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(res)
// 使用其他服务
// 步骤与上面的相同
// 使用Mytime服务
MyTime2Protocol := thrift.NewTMultiplexedProtocol(protocol, "mytime2")
c2 := thrift.NewTStandardClient(MyTime2Protocol, MyTime2Protocol)
client2 := timerpc.NewTimeServeClient(c2)
res, err = client2.GetCurrtentTime(ctx)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(res)
}
Compile and run:
go build client.go
./client
Reproduced please specify: http://www.lenggirl.com/cap/thrift.html