Skip to main content

thrift rpc 协议

· 5 min read

support

thrift 1.0.0-dev

Building C++ Library ......... : no
Building C (GLib) Library .... : no
Building Java Library ........ : no
Building C# Library .......... : no
Building Python Library ...... : no
Building Ruby Library ........ : no
Building Haxe Library ........ : no
Building Haskell Library ..... : no
Building Perl Library ........ : no
Building PHP Library ......... : yes
Building Dart Library ........ : no
Building Erlang Library ...... : no
Building Go Library .......... : yes
Building D Library ........... : no
Building NodeJS Library ...... : yes
Building Lua Library ......... : no

demo1


git clone https://github.com/apache/thrift.git

./bootstrap.sh
./configure --with-boost=/usr/local

yum install -y libtool
yum install -y byacc #yacc: command not found

make
make install

go get git.apache.org/thrift.git/lib/go/thrift
新建项目目录testphp,然后把thrift/lib/php/lib复制到testphp目录下面

batu.thrift

namespace go batu.demo
namespace php batu.demo

/**
* 结构体定义
*/
struct Article{
1: i32 id,
2: string title,
3: string content,
4: string author,
}

const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'}

service batuThrift {
list<string> CallBack(1:i64 callTime, 2:string name, 3:map<string, string> paramMap),
void put(1: Article newArticle),
}

server.go

package main

import (
"fmt"
"os"
"time"

"./batu/demo" //注意导入Thrift生成的接口包
"git.apache.org/thrift.git/lib/go/thrift"
)

const (
NetworkAddr = "192.168.1.101:9090" //监听地址&端口
)

type batuThrift struct {
}

func (this *batuThrift) CallBack(callTime int64, name string, paramMap map[string]string) (r []string, err error) {
fmt.Println("-->from client Call:", time.Unix(callTime, 0).Format("2006-01-02 15:04:05"), name, paramMap)
r = append(r, "key:"+paramMap["a"]+" value:"+paramMap["b"])
return
}

func (this *batuThrift) Put(s *demo.Article) (err error) {
fmt.Printf("Article--->id: %d\tTitle:%s\tContent:%t\tAuthor:%d\n", s.ID, s.Title, s.Content, s.Author)
return nil
}

func main() {
transportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory())
protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
//protocolFactory := thrift.NewTCompactProtocolFactory()

serverTransport, err := thrift.NewTServerSocket(NetworkAddr)
if err != nil {
fmt.Println("Error!", err)
os.Exit(1)
}

handler := &batuThrift{}
processor := demo.NewBatuThriftProcessor(handler)

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

client.go

package main

import (
"fmt"
"net"
"os"
"strconv"
"time"

"./batu/demo"
"git.apache.org/thrift.git/lib/go/thrift"
)

const (
HOST = "127.0.0.1"
PORT = "9090"
)

func main() {
startTime := currentTimeMillis()

transportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory())
protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()

transport, err := thrift.NewTSocket(net.JoinHostPort(HOST, PORT))
if err != nil {
fmt.Fprintln(os.Stderr, "error resolving address:", err)
os.Exit(1)
}

useTransport := transportFactory.GetTransport(transport)
client := demo.NewBatuThriftClientFactory(useTransport, protocolFactory)
if err := transport.Open(); err != nil {
fmt.Fprintln(os.Stderr, "Error opening socket to "+HOST+":"+PORT, " ", err)
os.Exit(1)
}
defer transport.Close()

for i := 0; i < 10; i++ {
paramMap := make(map[string]string)
paramMap["a"] = "batu.demo"
paramMap["b"] = "test" + strconv.Itoa(i+1)
r1, _ := client.CallBack(time.Now().Unix(), "go client", paramMap)
fmt.Println("GOClient Call->", r1)
}

model := demo.Article{1, "Go第一篇文章", "我在这里", "liuxinming"}
client.Put(&model)
endTime := currentTimeMillis()
fmt.Printf("本次调用用时:%d-%d=%d毫秒\n", endTime, startTime, (endTime - startTime))

}

func currentTimeMillis() int64 {
return time.Now().UnixNano() / 1000000
}

client.php

<?php
namespace batu\testDemo;
header("Content-type: text/html; charset=utf-8");
$startTime = getMillisecond();//记录开始时间

$ROOT_DIR = realpath(dirname(__FILE__) . '/');
$GEN_DIR = realpath(dirname(__FILE__) . '/') . '/gen-php';
require_once $ROOT_DIR . '/Thrift/ClassLoader/ThriftClassLoader.php';

use Thrift\ClassLoader\ThriftClassLoader;
use Thrift\Protocol\TBinaryProtocol;
use Thrift\Transport\TBufferedTransport;
use Thrift\Transport\TFramedTransport;
use Thrift\Transport\TSocket;
use Thrift\Transport\TSocketPool;

$loader = new ThriftClassLoader();
$loader->registerNamespace('Thrift', $ROOT_DIR);
$loader->registerDefinition('batu\demo', $GEN_DIR);
$loader->register();

// $thriftHost = '127.0.0.1'; //UserServer接口服务器IP
$thriftHost = '192.168.1.101'; //UserServer接口服务器IP
$thriftPort = 9090; //UserServer端口

$socket = new TSocket($thriftHost, $thriftPort);
$socket->setSendTimeout(10000);#Sets the send timeout.
$socket->setRecvTimeout(20000);#Sets the receive timeout.
//$transport = new TBufferedTransport($socket); #传输方式:这个要和服务器使用的一致 [go提供后端服务,迭代10000次2.6 ~ 3s完成]
$transport = new TFramedTransport($socket); #传输方式:这个要和服务器使用的一致[go提供后端服务,迭代10000次1.9 ~ 2.1s完成,比TBuffer快了点]
$protocol = new TBinaryProtocol($transport); #传输格式:二进制格式
$client = new \batu\demo\batuThriftClient($protocol);# 构造客户端

$transport->open();
$socket->setDebug(TRUE);

for ($i = 1; $i < 11; $i++) {
$item = array();
$item["a"] = "batu.demo";
$item["b"] = "test" . $i;
$result = $client->CallBack(time(), "php client", $item); # 对服务器发起rpc调用
echo "PHPClient Call->" . implode('', $result) . "\n";
}

$s = new \batu\demo\Article();
$s->id = 1;
$s->title = '插入一篇测试文章';
$s->content = '我就是这篇文章内容';
$s->author = 'liuxinming';
$client->put($s);

$s->id = 2;
$s->title = '插入二篇测试文章';
$s->content = '我就是这篇文章内容';
$s->author = 'liuxinming';
$client->put($s);

$endTime = getMillisecond();

echo "本次调用用时: :" . $endTime . "-" . $startTime . "=" . ($endTime - $startTime) . "毫秒\n";

function getMillisecond() {
list($t1, $t2) = explode(' ', microtime());
return (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000);
}

$transport->close();