目录:
一、什么是Thrift?
1) Thrift内部框架一瞥
2) 支持的数据传输格式、数据传输方式和服务模型
3) Thrift IDL
二、Thrift的官方网站在哪里?
三、在哪里下载?需要哪些组件的支持?
四、如何安装?
五、Golang、Java、Python、PHP之间通过Thrift实现跨语言调用
1) Golang 客户端和服务端的实现及交互
2) python 客户端的实现与golang 服务端的交互
3) php 客户端的实现与golang 服务端的交互
4) java 客户端的实现与golang 服务端的交互
六、扩展阅读
一、什么是Thrift
Thrift是一种可伸缩的跨语言服务的发展软件框架。它结合了功能强大的软件堆栈的代码生成引擎,以建设服务。
Thrift是facebook开发的,07年4月开放源代码,08年5月进入apache孵化器。创造Thrift是为了解决facebook系统中各系统间大数据量的传 输通信以及系统之间语言环境不同需要跨平台的特性。所以thrift可以支持多种程序语言,例如: C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml. (
目前0.9.1版本已经开始支持golang语言)在多种不同的语言之间通信thrift可以作为二进制的高性能的通讯中间件,支持数据(对象)序列化和多种类型的RPC服务。
Thrift允许你定义一个简单的定义文件中的数据类型和服务接口。以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨编程语言。简而言之,开发者只需准备一份thrift脚本,通过thrift code generator(像gcc那样输入一个命令)就能生成所要求的开发语言代码。
类似Thrift的工具,还有Avro、protocol buffer,但相对于Thrift来讲,都没有Thrift支持全面和使用广泛。
1) thrift内部框架一瞥
按照官方文档给出的整体框架,Thrift自下到上可以分为4层:
+-------------------------------------------+
| Server | -- 服务器进程调度
| (single-threaded, event-driven etc) |
+-------------------------------------------+
| Processor | -- RPC接口处理函数分发,IDL定义接口的实现将挂接到这里面
| (compiler generated) |
+-------------------------------------------+
| Protocol | -- 协议
| (JSON, compact etc) |
+-------------------------------------------+
| Transport | -- 网络传输
| (raw TCP, HTTP etc) |
+-------------------------------------------+
Thrift实际上是实现了C/S模式,通过代码生成工具将接口定义文件生成服务器端和客户端代码(可以为不同语言),从而实现服务端和客户端跨语言的支持。用户在Thirft描述文件中声明自己的服务,这些服务经过编译后会生成相应语言的代码文件,然后用户实现服务(客户端调用服务,服务器端提服务)便可以了。其中protocol(协议层, 定义数据传输格式,可以为二进制或者XML等)和transport(传输层,定义数据传输方式,可以为TCP/IP传输,内存共享或者文件共享等)被用作运行时库。
2)支持的数据传输格式、数据传输方式和服务模型
(a)支持的传输格式
TBinaryProtocol – 二进制格式.
TCompactProtocol – 压缩格式
TJSONProtocol – JSON格式
TSimpleJSONProtocol –提供JSON只写协议, 生成的文件很容易通过脚本语言解析。
TDebugProtocol – 使用易懂的可读的文本格式,以便于debug
(b) 支持的数据传输方式
TSocket -阻塞式socker
TFramedTransport – 以frame为单位进行传输,非阻塞式服务中使用。
TFileTransport – 以文件形式进行传输。
TMemoryTransport – 将内存用于I/O. java实现时内部实际使用了简单的ByteArrayOutputStream。
TZlibTransport – 使用zlib进行压缩, 与其他传输方式联合使用。当前无java实现。
(c)支持的服务模型
TSimpleServer – 简单的单线程服务模型,常用于测试
TThreadPoolServer – 多线程服务模型,使用标准的阻塞式IO。
TNonblockingServer – 多线程服务模型,使用非阻塞式IO(需使用TFramedTransport数据传输方式)
3) Thrift IDL
Thrift定义一套IDL(Interface Definition Language)用于描述接口,通常后缀名为.thrift,通过thrift程序把.thrift文件导出成各种不一样的代码的协议定义。IDL支持的类型可以参考这里: http://thrift.apache.org/docs/types
二、Thrift的官方网站在哪里?
http://thrift.apache.org/
三、在哪里下载?需要哪些组件的支持?
Thrift的官方下载地址在这里:http://www.apache.org/dyn/closer.cgi?path=/thrift/0.9.1/thrift-0.9.1.tar.gz
(
现在官网打包后的0.9.1版本在make的时候会出各种问题,后文会介绍不建议使用官网提供的0.9.1包)
Thrift的安装依赖,以及相关语言支持所需要的库,以下是来自官方文档的介绍:
Basic requirements
A relatively POSIX-compliant *NIX system
Cygwin or MinGW can be used on Windows
g++ 4.2
boost 1.53.0
Runtime libraries for lex and yacc might be needed for the compiler.
Requirements for building from source
GNU build tools:
autoconf 2.65
automake 1.9
libtool 1.5.24
pkg-config autoconf macros (pkg.m4)
lex and yacc (developed primarily with flex and bison)
libssl-dev
Language requirements
These are only required if you choose to build the libraries for the given language
C++
Boost 1.53.0
libevent (optional, to build the nonblocking server)
zlib (optional)
Java
Java 1.7
Apache Ant
C#: Mono 1.2.4 (and pkg-config to detect it) or Visual Studio 2005+
Python 2.6 (including header files for extension modules)
PHP 5.0 (optionally including header files for extension modules)
Ruby 1.8
bundler gem
Erlang R12 (R11 works but not recommended)
Perl 5
Bit::Vector
Class::Accessor
四、如何安装?
1) 安装依赖插件
1
|
root@m1:
/home/hadoop
#sudo apt-get install libboost-dev libboost-test-dev libboost-program-options-dev libevent-dev automake libtool flex bison pkg-config g++ libssl-dev
|
2) 安装最新版PHP5(因为后文会使用PHP来测试客户端与Golang服务端的交互)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#先添加phpkey
root@m2:
/home/hadoop/thrift-git
# add-apt-repository ppa:ondrej/php5
You are about to add the following PPA to your system:
This branch follows latest PHP packages as maintained by me & rest of the Debian pkg-php team.
You can get
more
information about the packages at https:
//sury
.org
If you need to stay with PHP 5.4 you can use the oldstable PHP repository:
ppa:ondrej
/php5-oldstable
BUGS&FEATURES: This PPA now has a issue tracker: https:
//deb
.sury.org
/pages/bugreporting
.html
PLEASE READ: If you like my work and want to give me a little motivation, please consider donating: https:
//deb
.sury.org
/pages/donate
.html
More info: https:
//launchpad
.net/~ondrej/+archive
/ubuntu/php5
Press [ENTER] to
continue
or ctrl-c to cancel adding it
gpg: 钥匙环‘
/tmp/tmpZ7PZIy/secring
.gpg’已建立
gpg: 钥匙环‘
/tmp/tmpZ7PZIy/pubring
.gpg’已建立
gpg: 下载密钥‘E5267A6C’,从 hkp 服务器 keyserver.ubuntu.com
gpg:
/tmp/tmpZ7PZIy/trustdb
.gpg:建立了信任度数据库
gpg: 密钥 E5267A6C:公钥“Launchpad PPA
for
Ondřej Surý”已导入
gpg: 合计被处理的数量:1
gpg: 已导入:1 (RSA: 1)
OK
root@m2:
/home/hadoop/thrift-git
# apt-get update
root@m1:
/home/hadoop/thrift-git
# apt-get install php5-dev php5-cli phpunit
|
3) 下载thirft0.9.1版本
1
2
3
4
5
6
7
8
9
10
11
|
root@m2:
/home/hadoop
# git clone https://github.com/apache/thrift.git thrift-git
Cloning into
'thrift-git'
...
remote: Counting objects: 37193,
done
.
remote: Compressing objects: 100% (216
/216
),
done
.
remote: Total 37193 (delta 319), reused 407 (delta 272)
Receiving objects: 100% (37193
/37193
), 9.62 MiB | 50 KiB
/s
,
done
.
Resolving deltas: 100% (25794
/25794
),
done
.
root@m1:
/home/hadoop
#cd thrift-git
root@m2:
/home/hadoop/thrift-git
# git checkout -b 0.9.1
Switched to a new branch
'0.9.1'
|
4) 编译安装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
root@m1:
/home/hadoop/thrift-git
#./bootstrap.sh
root@m1:
/home/hadoop/thrift-git
# ./configure --enable-thrift_protocol
#下面是截取部分运行成功后的信息
thrift 0.9.1
Building C++ Library ......... :
yes
Building C (GLib) Library .... :
yes
Building Java Library ........ : no
Building C
# Library .......... : no
Building Python Library ...... :
yes
Building Ruby Library ........ : no
Building Haskell Library ..... : no
Building Perl Library ........ : no
Building PHP Library ......... :
yes
Building Erlang Library ...... : no
Building Go Library .......... : no
Building D Library ........... : no
C++ Library:
Build TZlibTransport ...... :
yes
Build TNonblockingServer .. :
yes
Build TQTcpServer (Qt) .... : no
Python Library:
Using Python .............. :
/usr/bin/python
PHP Library:
Using php-config .......... :
/usr/bin/php-config
If something is missing that you think should be present,
please skim the output of configure to
find
the missing
component. Details are present
in
config.log.
|
如果在安装Thrift时,不需要支持的扩展,可以在使用./configure的时候带上以下参数
1
|
.
/configure
--without-php --without-ruby --without-haskell --without-python --without-perl
|
继续安装这个时间会长一点
1
2
|
root@m2:
/home/hadoop/thrift-git
# make
root@m2:
/home/hadoop/thrift-git
# make install
|
我们可以看到thrift已经安装完成,当前版本是0.9.1
1
2
|
root@m1:
/home/hadoop/thrift-git
# thrift -version
Thrift version 0.9.1
|
五、Golang、Java、Python、PHP之间通过Thrift实现跨语言调用
在写代码之前,我们先来配置Thrift的协议库IDL文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
root@m1:
/home/hadoop/thrift-git/tutorial
# vi idoall.org.thrift
namespace go idoall.org.demo
namespace java idoall.org.demo
namespace php idoall.org.demo
namespace py idoall.org.demo
struct Student{
1: i32 sid,
2: string sname,
3: bool ssex=0,
4: i16 sage,
}
const map
'hello'
:
'world'
,
'goodnight'
:
'moon'
}
service idoallThrift {
list
void put(1: Student s),
}
|
编译IDL文件,生成相关代码
1
2
3
4
|
root@m1:
/home/hadoop/thrift-git/tutorial
# thrift -r --gen go idoall.org.thrift
root@m1:
/home/hadoop/thrift-git/tutorial
# thrift -r --gen py idoall.org.thrift
root@m1:
/home/hadoop/thrift-git/tutorial
# thrift -r --gen php idoall.org.thrift
root@m1:
/home/hadoop/thrift-git/tutorial
# thrift -r --gen java idoall.org.thrift
|
如果编译IDL的PHP包要生成server端代码,和其他语言不太一样,可以使用thrift --help查看使用说明,需要加上server选项,如下:
1
|
root@m1:
/home/hadoop/thrift-git/tutorial
# thrift -r --gen php:server idoall.org.thrift
|
1) Golang 客户端和服务端的实现及交互
Golang1.3的安装,请参考这篇文章《 ubuntu12.04 64bit基于源码安装golang1.3》,默认使用apt-get安装不是最新版。
#安装golang的Thrift包:
1
|
root@m1:
/home/hadoop/thrift-git/tutorial
# go get git.apache.org/thrift.git/lib/go/thrift
|
#将Thrift生成的开发库也复制到GOPATH中
1
|
root@m1:
/home/hadoop/thrift-git/tutorial
# cp -r /home/hadoop/thrift-git/tutorial/gen-go/idoall $GOPATH/src
|
#编写go server端代码(后面的代码,我们都放在/home/hadoop/thrift_demo目录中进行演示)
1
2
3
|
root@m1:
/home/hadoop
# mkdir thrift_demo
root@m1:
/home/hadoop
# cd thrift_demo/
root@m1:
/home/hadoop/thrift_demo
# vi s.go
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
package main
import
(
"idoall/org/demo"
"fmt"
"git.apache.org/thrift.git/lib/go/thrift"
"os"
)
const (
NetworkAddr
=
"0.0.0.0:10086"
)
type
idoallThrift struct {
}
func (this
*
idoallThrift) CallBack(callTime int64, name string, paramMap
map
[string]string) (r []string, err error) {
fmt.Println(
"-->from client Call:"
, callTime, name, paramMap)
r
=
append(r,
"key:"
+
paramMap[
"a"
]
+
" value:"
+
paramMap[
"b"
])
return
}
func (this
*
idoallThrift) Put(s
*
demo.Student) (err error){
fmt.Printf(
"Stduent--->id: %d\tname:%s\tsex:%t\tage:%d\n"
, s.Sid, s.Sname, s.Ssex, s.Sage)
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 :
=
&idoallThrift{}
processor :
=
demo.NewIdoallThriftProcessor(handler)
server :
=
thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory)
fmt.Println(
"thrift server in"
, NetworkAddr)
server.Serve()
}
|
#编写go client端代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
root@m1:
/
home
/
hadoop
/
thrift_demo
# vi c.go
package main
import
(
"idoall/org/demo"
"fmt"
"git.apache.org/thrift.git/lib/go/thrift"
"net"
"os"
"time"
"strconv"
)
const (
HOST
=
"127.0.0.1"
PORT
=
"10086"
)
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.NewIdoallThriftClientFactory(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 <
5
; i
+
+
{
paramMap :
=
make(
map
[string]string)
paramMap[
"a"
]
=
"idoall"
paramMap[
"b"
]
=
"org"
+
strconv.Itoa(i
+
1
)
r1, _ :
=
client.CallBack(time.Now().UnixNano()
/
1000000
,
"go client"
, paramMap)
fmt.Println(
"GOClient Call->"
, r1)
}
model :
=
demo.Student{
11
,
"student-idoall-go"
,true,
20
}
client.Put(&model)
endTime :
=
currentTimeMillis()
fmt.Printf(
"本次调用用时:%d-%d=%d毫秒\n"
,endTime,startTime, (endTime
-
startTime))
}
func currentTimeMillis() int64 {
return
time.Now().UnixNano()
/
1000000
}
|
#运行go服务端(可以看到服务端已经在监听本机的10086端口)
1
2
|
root@m1:
/home/hadoop/thrift_demo
# go run s.go
thrift server
in
0.0.0.0:10086
|
#运行go客户端
1
2
3
4
5
6
7
8
|
root@m1:
/home/hadoop/thrift_demo
# go run c.go
GOClient Call-> [key:idoall value:org1]
GOClient Call-> [key:idoall value:org2]
GOClient Call-> [key:idoall value:org3]
GOClient Call-> [key:idoall value:org4]
GOClient Call-> [key:idoall value:org5]
本次调用用时:1408267333489-1408267333486=3毫秒
root@m1:
/home/hadoop/thrift_demo
#
|
#查看go服务端,可以看到数据的交互
1
2
3
4
5
6
7
8
|
root@m1:
/home/hadoop/thrift_demo
# go run s.go
thrift server
in
0.0.0.0:10086
-->from client Call: 1408267333487 go client map[a:idoall b:org1]
-->from client Call: 1408267333487 go client map[a:idoall b:org2]
-->from client Call: 1408267333488 go client map[b:org3 a:idoall]
-->from client Call: 1408267333488 go client map[a:idoall b:org4]
-->from client Call: 1408267333488 go client map[a:idoall b:org5]
Stduent--->
id
: 11 name:student-idoall-go sex:
true
age:20
|
2) python 客户端的实现与golang 服务端的交互
#将python用到的Thrift包复制到thrift_demo里面
1
2
|
root@m1:
/home/hadoop/thrift_demo
# cp -r /home/hadoop/thrift-git/lib/py/build /home/hadoop/thrift_demo/libpy
root@m1:
/home/hadoop/thrift_demo
# cp -r /home/hadoop/thrift-git/tutorial/gen-py /home/hadoop/thrift_demo/gen-py
|
#编写python client代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
root@m1:
/
home
/
hadoop
/
thrift_demo
# vi c.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import
sys, glob, time,datetime
sys.path.append(
'gen-py'
)
sys.path.insert(
0
, glob.glob(
'libpy/lib.*'
)[
0
])
from
idoall.org.demo
import
idoallThrift
from
idoall.org.demo.ttypes
import
*
from
thrift
import
Thrift
from
thrift.transport
import
TSocket
from
thrift.transport
import
TTransport
from
thrift.protocol
import
TBinaryProtocol
try
:
startTime
=
time.time()
*
1000
# Make socket
transport
=
TSocket.TSocket(
'127.0.0.1'
,
10086
)
# Framed is critical. Raw sockets are very slow
transport
=
TTransport.TFramedTransport(transport)
# Wrap in a protocol
protocol
=
TBinaryProtocol.TBinaryProtocol(transport)
# Create a client to use the protocol encoder
client
=
idoallThrift.Client(protocol)
# Connect!
transport.
open
()
for
i
in
range
(
1
,
6
):
r
=
client.CallBack(time.time()
*
1000
,
"python client"
,{
"a"
:
"idoall"
,
"b"
:
"org"
+
str
(i)})
print
"PythonClient Call->%s"
%
(r)
u1
=
Student()
u1.sid
=
111
u1.sname
=
'student-idoall-python'
u1.ssex
=
False
u1.sage
=
200
client.put(u1)
endTime
=
time.time()
*
1000
print
"本次调用用时:%d-%d=%d毫秒"
%
(endTime,startTime, (endTime
-
startTime))
# Close!
transport.close()
except
Thrift.TException, tx:
print
'ERROR:%s'
%
(tx.message)
|
#运行go服务端
1
2
|
root@m1:
/home/hadoop/thrift_demo
# go run s.go
thrift server
in
0.0.0.0:10086
|
#运行python客户端
1
2
3
4
5
6
7
8
|
root@m1:
/home/hadoop/thrift_demo
# python c.py
PythonClient Call->[
'key:idoall value:org1'
]
PythonClient Call->[
'key:idoall value:org2'
]
PythonClient Call->[
'key:idoall value:org3'
]
PythonClient Call->[
'key:idoall value:org4'
]
PythonClient Call->[
'key:idoall value:org5'
]
本次调用用时:1408268651648-1408268651646=2毫秒
root@m1:
/home/hadoop/thrift_demo
#
|
#查看go服务端,可以看到数据的交互
1
2
3
4
5
6
7
8
|
root@m1:
/home/hadoop/thrift_demo
# go run s.go
thrift server
in
0.0.0.0:10086
-->from client Call: 1408268651646 python client map[b:org1 a:idoall]
-->from client Call: 1408268651646 python client map[a:idoall b:org2]
-->from client Call: 1408268651647 python client map[a:idoall b:org3]
-->from client Call: 1408268651647 python client map[a:idoall b:org4]
-->from client Call: 1408268651647 python client map[a:idoall b:org5]
Stduent--->
id
: 111 name:student-idoall-python sex:
false
age:200
|
3) php 客户端的实现与golang 服务端的交互
#编译php的Thrift扩展
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
root@m1:
/home/hadoop/thrift_demo
# cd /home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol
root@m1:
/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol
# ls
acinclude.m4 build config.h.
in
config.
nice
configure include ltmain.sh Makefile.global mkinstalldirs php_thrift_protocol.h thrift_protocol.la
aclocal.m4 config.guess config.log config.status configure.
in
install
-sh Makefile Makefile.objects modules php_thrift_protocol.lo
autom4te.cache config.h config.m4 config.sub config.w32 libtool Makefile.fragments missing php_thrift_protocol.cpp run-tests.php
root@m1:
/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol
# phpize
Configuring
for
:
PHP Api Version: 20121113
Zend Module Api No: 20121212
Zend Extension Api No: 220121212
root@m1:
/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol
# ./configure
##以下只给出部分输出信息
checking
for
grep
that handles long lines and -e...
/bin/grep
checking
for
egrep
...
/bin/grep
-E
checking
for
a
sed
that does not truncate output...
/bin/sed
checking
for
cc… cc
…
…
config.status: creating config.h
config.status: config.h is unchanged
config.status: executing libtool commands
#执行make命令后,我们可以看到扩展文件放到了/usr/lib/php5/20121212/目录
root@m1:
/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol
# make && make install
Build complete.
Don
't forget to run '
make
test
'.
Installing shared extensions:
/usr/lib/php5/20121212/
|
#让PHP支持thrift,编辑php.ini文件,搜索extension_dir,然后在下面加上extension=thrift_protocol.so,保存退出。
1
2
3
4
5
6
7
|
root@m1:
/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol
# vi /etc/php5/fpm/php.ini
; Directory
in
which
the loadable extensions (modules) reside.
; http:
//php
.net
/extension-dir
; extension_dir =
"./"
; On windows:
; extension_dir =
"ext"
extension=thrift_protocol.so
|
#重启php5-fpm
1
2
3
4
|
root@m1:
/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol
# service php5-fpm restart
php5-fpm stop
/waiting
php5-fpm start
/running
, process 16522
root@m1:
/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol
#
|
#将php用到的Thrift包复制到thrift_demo里面
1
2
3
4
5
|
root@m1:
/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol
# mkdir -p /home/hadoop/thrift_demo/libphp/
root@m1:
/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol
# cp -r /home/hadoop/thrift-git/lib/php/src/* /home/hadoop/thrift_demo/libphp/
root@m1:
/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol
# cp -r /home/hadoop/thrift-git/lib/php/lib/Thrift /home/hadoop/thrift_demo/libphp
root@m1:
/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol
# cp -r /home/hadoop/thrift-git/tutorial/gen-php /home/hadoop/thrift_demo/gen-php
root@m1:
/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol
# cd /home/hadoop/thrift_demo
|
#编写php client端代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
root@m1:/home/hadoop/thrift_demo# vi c.php
$startTime
= getMillisecond();
$GLOBALS
[
'THRIFT_ROOT'
] =
'./libphp'
; # 指定库目录,可以是绝对路径或是相对路径
require_once
$GLOBALS
[
'THRIFT_ROOT'
].
'/Thrift/ClassLoader/ThriftClassLoader.php'
;
use
Thrift\ClassLoader\ThriftClassLoader;
use
Thrift\Protocol\TBinaryProtocol;
use
Thrift\Transport\TSocket;
use
Thrift\Transport\TSocketPool;
use
Thrift\Transport\TFramedTransport;
use
Thrift\Transport\TBufferedTransport;
$GEN_DIR
=
realpath
(dirname(
__FILE__
)).
'/gen-php'
;
$loader
=
new
ThriftClassLoader();
$loader
->registerNamespace(
'Thrift'
,
$GLOBALS
[
'THRIFT_ROOT'
]); # 加载thrift
$loader
->registerDefinition(
'idoall\org\demo'
,
$GEN_DIR
); # 加载自己写的thrift文件编译的类文件和数据定义
$loader
->register();
$socket
=
new
TSocket(
'127.0.0.1'
, 10086); # 建立socket
$socket
->setDebug(TRUE);
$framedSocket
=
new
TFramedTransport(
$socket
); #这个要和服务器使用的一致
$transport
=
$framedSocket
;
$protocol
=
new
TBinaryProtocol(
$transport
); # 这里也要和服务器使用的协议一致
$transport
->open();
$client
=
new
\idoall\org\demo\idoallThriftClient(
$protocol
); # 构造客户端
for
(
$i
=1;
$i
<6;
$i
++)
{
$item
=
array
();
$item
[
"a"
] =
"idoall"
;
$item
[
"b"
] =
"org"
+
$i
;
$result
=
$client
->CallBack(getMillisecond(),
"php client"
,
$item
); # 对服务器发起rpc调用
echo
"PHPClient Call->"
.implode(
''
,
$result
).
"\n"
;
}
$s
=
new
\idoall\org\demo\Student();
$s
->sid=1111;
$s
->sname=
"student-idoall-php"
;
$s
->ssex = false;
$s
->sage = 2000;
$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(); # 关闭链接
|
#运行go服务端
1
2
|
root@m1:
/home/hadoop/thrift_demo
# go run s.go
thrift server
in
0.0.0.0:10086
|
#运行php客户端
1
2
3
4
5
6
7
|
root@m1:
/home/hadoop/thrift_demo
# php c.php
PHPClient Call->key:idoall value:1
PHPClient Call->key:idoall value:2
PHPClient Call->key:idoall value:3
PHPClient Call->key:idoall value:4
PHPClient Call->key:idoall value:5
本次调用用时:1408268739277-1408268739269=8毫秒
|
#查看go服务端,可以看到数据的交互
1
2
3
4
5
6
7
8
|
root@m1:
/home/hadoop/thrift_demo
# go run s.go
thrift server
in
0.0.0.0:10086
-->from client Call: 1408268739272 php client map[a:idoall b:1]
-->from client Call: 1408268739273 php client map[a:idoall b:2]
-->from client Call: 1408268739274 php client map[a:idoall b:3]
-->from client Call: 1408268739275 php client map[a:idoall b:4]
-->from client Call: 1408268739275 php client map[a:idoall b:5]
Stduent--->
id
: 1111 name:student-idoall-php sex:
false
age:2000
|
4) java 客户端的实现与golang 服务端的交互
#安装maven项目管理工具
1
|
root@m1:
/home/hadoop/thrift_demo
# apt-get install maven
|
#将java用到的Thrift包复制到thrift_demo里面
1
2
3
4
5
6
|
root@m1:
/home/hadoop/thrift_demo
# cp -r /home/hadoop/thrift-git/tutorial/gen-java .
root@m1:
/home/hadoop/thrift_demo
# cd gen-java
root@m1:
/home/hadoop/thrift_demo/gen-java
# mkdir -p src/main/java
root@m1:
/home/hadoop/thrift_demo/gen-java
# mkdir META-INF
root@m1:
/home/hadoop/thrift_demo/gen-java
# mkdir lib
root@m1:
/home/hadoop/thrift_demo/gen-java
# cp -r /home/hadoop/thrift-git/lib/java/build/libthrift-0.9.1.jar ./lib/
|
#编写java client端代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
root
@m1
:/home/hadoop/thrift_demo/gen-java# vi idoall/org/demo/c.java
package
idoall.org.demo;
import
java.util.HashMap;
import
java.util.List;
import
java.util.Map;
import
org.apache.thrift.TException;
import
org.apache.thrift.protocol.TBinaryProtocol;
import
org.apache.thrift.protocol.TProtocol;
import
org.apache.thrift.transport.TFramedTransport;
import
org.apache.thrift.transport.TSocket;
import
org.apache.thrift.transport.TTransport;
import
org.apache.thrift.transport.TTransportException;
public
class
c {
public
static
final
String SERVER_IP =
"m1"
;
public
static
final
int
SERVER_PORT =
10086
;
public
static
final
int
TIMEOUT =
30000
;
/**
* @param args
*/
public
static
void
main(String[] args) {
long
startTime=System.currentTimeMillis();
//获取开始时间
TTransport transport =
null
;
try
{
transport =
new
TFramedTransport(
new
TSocket(SERVER_IP,
SERVER_PORT, TIMEOUT));
// 协议要和服务端一致
TProtocol protocol =
new
TBinaryProtocol(transport);
idoallThrift.Client client =
new
idoallThrift.Client(
protocol);
transport.open();
for
(
int
i=
1
;i<
6
;i++)
{
Map
new
HashMap
m.put(
"a"
,
"idoall"
);
m.put(
"b"
,
"org"
+i);
List
"java client"
,m);
System.out.println(
"JAVAClient Call->"
+ result);
}
Student s =
new
Student();
s.sid=
1111
;
s.sname=
"student-idoall-java"
;
s.ssex =
true
;
s.sage =
20000
;
client.put(s);
long
endTime = System.currentTimeMillis();
System.out.println(
"本次调用用时:"
+ endTime +
"-"
+ startTime +
"="
+ (endTime - startTime)+
"毫秒"
);
}
catch
(TTransportException e) {
e.printStackTrace();
}
catch
(TException e) {
e.printStackTrace();
}
finally
{
if
(
null
!= transport) {
transport.close();
}
}
}
}
|
#配置jar包的MANIFEST文件
1
2
3
4
|
root@m1:
/home/hadoop/thrift_demo/gen-java
# vi META-INF/MANIFEST.MF
Manifest-Version: 1.0
Main-Class: idoall.org.demo.c
Class-Path: lib/**.jar
|
#制作Maven的描述文件pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
root@m1:/home/hadoop/thrift_demo/gen-java# vi pom.xml
<
project
xmlns
=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation
=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<
modelVersion
>4.0.0
modelVersion
>
<
groupId
>idoall.org.demo
groupId
>
<
artifactId
>idoall.org.demo
artifactId
>
<
version
>0.0.1-SNAPSHOT
version
>
<
packaging
>jar
packaging
>
<
name
>idoall.org.demo
name
>
<
url
>http://maven.apache.org
url
>
<
properties
>
<
project.build.sourceEncoding
>UTF-8
project.build.sourceEncoding
>
properties
>
<
dependencies
>
<
dependency
>
<
groupId
>junit
groupId
>
<
artifactId
>junit
artifactId
>
<
version
>3.8.1
version
>
<
scope
>test
scope
>
dependency
>
<
dependency
>
<
groupId
>org.apache.thrift
groupId
>
<
artifactId
>libthrift
artifactId
>
<
version
>0.9.1
version
>
dependency
>
<
dependency
>
<
groupId
>org.slf4j
groupId
>
<
artifactId
>slf4j-log4j12
artifactId
>
<
version
>1.5.8
version
>
dependency
>
dependencies
>
<
build
>
<
plugins
>
<
plugin
>
<
artifactId
>maven-assembly-plugin
artifactId
>
<
configuration
>
<
archive
>
<
manifest
>
<
mainClass
>idoall.org.demo.c
mainClass
>
manifest
>
archive
>
<
descriptorRefs
>
<
descriptorRef
>jar-with-dependencies
descriptorRef
>
descriptorRefs
>
configuration
>
plugin
>
<
plugin
>
<
groupId
>org.apache.maven.plugins
groupId
>
<
artifactId
>maven-compiler-plugin
artifactId
>
<
configuration
>
<
source
>1.6
source
>
<
target
>1.6
target
>
configuration
>
plugin
>
plugins
>
build
>
project
>
|
#使用maven工具,将相关依赖打包到当前目录的target目录中,并生成idoall.org.demo-0.0.1-SNAPSHOT-jar-with-dependencies.jar
1
2
3
4
5
6
7
8
9
10
|
root@m1:
/home/hadoop/thrift_demo/gen-java
# mv idoall src/main/java/
root@m1:
/home/hadoop/thrift_demo/gen-java
# mvn assembly:assembly
#以下只给出部分提示信息
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total
time
: 7.618s
[INFO] Finished at: Sun Aug 17 09:36:48 CST 2014
[INFO] Final Memory: 12M
/29M
[INFO] ------------------------------------------------------------------------
|
#运行go服务端
1
2
|
root@m1:
/home/hadoop/thrift_demo
# go run s.go
thrift server
in
0.0.0.0:10086
|
#运行打包后的java客户端
1
2
3
4
5
6
7
|
root@m1:
/home/hadoop/thrift_demo/gen-java
# java -jar target/idoall.org.demo-0.0.1-SNAPSHOT-jar-with-dependencies.jar
JAVAClient Call->[key:idoall value:org1]
JAVAClient Call->[key:idoall value:org2]
JAVAClient Call->[key:idoall value:org3]
JAVAClient Call->[key:idoall value:org4]
JAVAClient Call->[key:idoall value:org5]
本次调用用时:1408268973582-1408268973477=105毫秒
|
#查看go服务端,可以看到数据的交互
1
2
3
4
5
6
7
8
|
root@m1:
/home/hadoop/thrift_demo
# go run s.go
thrift server
in
0.0.0.0:10086
-->from client Call: 1408268973547 java client map[a:idoall b:org1]
-->from client Call: 1408268973568 java client map[b:org2 a:idoall]
-->from client Call: 1408268973568 java client map[b:org3 a:idoall]
-->from client Call: 1408268973568 java client map[b:org4 a:idoall]
-->from client Call: 1408268973569 java client map[b:org5 a:idoall]
Stduent--->
id
: 1111 name:student-idoall-java sex:
true
age:20000
|
六、扩展阅读
Golang通过Thrift框架完美实现跨语言调用
maven-assembly-plugin
Our own "Hello World!"
文章中使用的代码提供下载,在这里: http://pan.baidu.com/s/1dDF1rRr
---------------------------------------
博文作者:迦壹
博客地址: Golang、Php、Python、Java基于Thrift0.9.1实现跨语言调用
转载声明:可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明,谢谢合作!
---------------------------------------