Golang、Php、Python、Java基於Thrift0.9.1實現跨語言呼叫

Lion發表於2014-08-17
目錄:
  一、什麼是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
 
---------------------------------------
博文作者:迦壹
轉載宣告:可以轉載, 但必須以超連結形式標明文章原始出處和作者資訊及版權宣告,謝謝合作!
---------------------------------------

相關文章