Golang、Php、Python、Java基于Thrift0.9.1实现跨语言调用

目录:
  一、什么是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的官方网站在哪里?
 
  三、在哪里下载?需要哪些组件的支持?
  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<string,string> MAPCONSTANT = { 'hello' : 'world' , 'goodnight' : 'moon' }
 
service idoallThrift {       
         list<string> CallBack(1:i64 callTime, 2:string name, 3:map<string, string> paramMap),
         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
<?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<String,String> m = new HashMap<String,String>();
                 m.put( "a" , "idoall" );
                 m.put( "b" , "org" +i);
                 
                 List<String> result = client.CallBack(System.currentTimeMillis(), "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
 
  六、扩展阅读
 
  文章中使用的代码提供下载,在这里: http://pan.baidu.com/s/1dDF1rRr
 
---------------------------------------
博文作者:迦壹
转载声明:可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明,谢谢合作!
---------------------------------------

转载于:https://www.cnblogs.com/lion.net/p/3918386.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值