(轉)使用Thrift0.9.1實現跨語言調用Golang、Php、Python、Java

問題導讀:
什麼是Thrift?
Thrift的官方網站在哪裏?
Golang、Java、Python、PHP之間如何經過Thrift實現跨語言調用?





1、什麼是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

2、Thrift的官方網站在哪裏?
  http://thrift.apache.org/


3、在哪裏下載?須要哪些組件的支持?
  Thrift的官方下載地址在這裏:http://www.apache.org/dyn/closer ... 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

4、如何安裝?
1) 安裝依賴插件

php

  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服務端的交互)html

  1. #先添加phpkey
  2. root@m2:/home/hadoop/thrift-git# add-apt-repository ppa:ondrej/php5
  3. You are about to add the following PPA to your system:
  4. This branch follows latest PHP packages as maintained by me & rest of the Debian pkg-php team.
  5. You can get more information about the packages at https://sury.org
  6. If you need to stay with PHP 5.4 you can use the oldstable PHP repository:
  7.     ppa:ondrej/php5-oldstable
  8. BUGS&FEATURES: This PPA now has a issue tracker: https://deb.sury.org/pages/bugreporting.html
  9. 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
  10. More info: https://launchpad.net/~ondrej/+archive/ubuntu/php5
  11. Press [ENTER] to continue or ctrl-c to cancel adding it
  12. gpg: 鑰匙環‘/tmp/tmpZ7PZIy/secring.gpg’已創建
  13. gpg: 鑰匙環‘/tmp/tmpZ7PZIy/pubring.gpg’已創建
  14. gpg: 下載密鑰‘E5267A6C’,從 hkp 服務器 keyserver.ubuntu.com
  15. gpg: /tmp/tmpZ7PZIy/trustdb.gpg:創建了信任度數據庫
  16. gpg: 密鑰 E5267A6C:公鑰「Launchpad PPA for Ondřej Sury」已導入
  17. gpg: 合計被處理的數量:1
  18. gpg:               已導入:1  (RSA: 1)
  19. OK
  20. root@m2:/home/hadoop/thrift-git# apt-get update
  21. root@m1:/home/hadoop/thrift-git# apt-get install php5-dev php5-cli phpunit
複製代碼


3) 下載thirft0.9.1版本java

  1. root@m2:/home/hadoop# git clone https://github.com/apache/thrift.git thrift-git
  2. Cloning into 'thrift-git'...
  3. remote: Counting objects: 37193, done.
  4. remote: Compressing objects: 100% (216/216), done.
  5. remote: Total 37193 (delta 319), reused 407 (delta 272)
  6. Receiving objects: 100% (37193/37193), 9.62 MiB | 50 KiB/s, done.
  7. Resolving deltas: 100% (25794/25794), done.
  8. root@m1:/home/hadoop#cd thrift-git
  9. root@m2:/home/hadoop/thrift-git# git checkout -b 0.9.1
  10. Switched to a new branch '0.9.1'
複製代碼


4) 編譯安裝python

  1. root@m1:/home/hadoop/thrift-git#./bootstrap.sh
  2. root@m1:/home/hadoop/thrift-git# ./configure --enable-thrift_protocol
  3. #下面是截取部分運行成功後的信息
  4. thrift 0.9.1
  5. Building C++ Library ......... : yes
  6. Building C (GLib) Library .... : yes
  7. Building Java Library ........ : no
  8. Building C# Library .......... : no
  9. Building Python Library ...... : yes
  10. Building Ruby Library ........ : no
  11. Building Haskell Library ..... : no
  12. Building Perl Library ........ : no
  13. Building PHP Library ......... : yes
  14. Building Erlang Library ...... : no
  15. Building Go Library .......... : no
  16. Building D Library ........... : no
  17. C++ Library:
  18.    Build TZlibTransport ...... : yes
  19.    Build TNonblockingServer .. : yes
  20.    Build TQTcpServer (Qt) .... : no
  21. Python Library:
  22.    Using Python .............. : /usr/bin/python
  23. PHP Library:
  24.    Using php-config .......... : /usr/bin/php-config
  25. If something is missing that you think should be present,
  26. please skim the output of configure to find the missing
  27. component.  Details are present in config.log.
複製代碼


若是在安裝Thrift時,不須要支持的擴展,能夠在使用./configure的時候帶上如下參數git

  1. ./configure --without-php --without-ruby --without-haskell --without-python --without-perl
複製代碼


繼續安裝這個時間會長一點github

  1. root@m2:/home/hadoop/thrift-git# make
  2. root@m2:/home/hadoop/thrift-git# make install
複製代碼


咱們能夠看到thrift已經安裝完成,當前版本是0.9.1golang

  1. root@m1:/home/hadoop/thrift-git# thrift -version
  2. Thrift version 0.9.1
複製代碼



5、Golang、Java、Python、PHP之間經過Thrift實現跨語言調用
  在寫代碼以前,咱們先來配置Thrift的協議庫IDL文件:數據庫

  1. root@m1:/home/hadoop/thrift-git/tutorial# vi idoall.org.thrift 
  2. namespace go idoall.org.demo
  3. namespace java idoall.org.demo
  4. namespace php idoall.org.demo
  5. namespace  py idoall.org.demo
  6. struct Student{
  7. 1: i32 sid, 
  8. 2: string sname,
  9. 3: bool ssex=0,
  10. 4: i16 sage,
  11. }
  12. const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'}
  13. service idoallThrift {        
  14.         list<string> CallBack(1:i64 callTime, 2:string name, 3:map<string, string> paramMap),
  15.         void put(1: Student s),
  16. }
複製代碼


編譯IDL文件,生成相關代碼apache

  1. root@m1:/home/hadoop/thrift-git/tutorial# thrift -r --gen go idoall.org.thrift 
  2. root@m1:/home/hadoop/thrift-git/tutorial# thrift -r --gen py idoall.org.thrift   
  3. root@m1:/home/hadoop/thrift-git/tutorial# thrift -r --gen php idoall.org.thrift   
  4. 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. root@m1:/home/hadoop# mkdir thrift_demo
  2. root@m1:/home/hadoop# cd thrift_demo/
  3. root@m1:/home/hadoop/thrift_demo# vi s.go
複製代碼
  1. package main
  2. import (
  3.     "idoall/org/demo"
  4.     "fmt"
  5.     "git.apache.org/thrift.git/lib/go/thrift"
  6.     "os"
  7. )
  8. const (
  9.     NetworkAddr = "0.0.0.0:10086"
  10. )
  11. type idoallThrift struct {
  12. }
  13. func (this *idoallThrift) CallBack(callTime int64, name string, paramMap map[string]string) (r []string, err error) {
  14.     fmt.Println("-->from client Call:", callTime, name, paramMap)
  15.     r = append(r, "key:"+paramMap["a"]+"    value:"+paramMap["b"])
  16.     return
  17. }
  18. func (this *idoallThrift) Put(s *demo.Student) (err error){
  19.     fmt.Printf("Stduent--->id: %d\tname:%s\tsex:%t\tage:%d\n", s.Sid, s.Sname, s.Ssex, s.Sage)
  20.     return nil
  21. }
  22. func main() {
  23.     transportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory())
  24.     protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
  25.     //protocolFactory := thrift.NewTCompactProtocolFactory()
  26.     serverTransport, err := thrift.NewTServerSocket(NetworkAddr)
  27.     if err != nil {
  28.         fmt.Println("Error!", err)
  29.         os.Exit(1)
  30.     }
  31.     handler := &idoallThrift{}
  32.     processor := demo.NewIdoallThriftProcessor(handler)
  33.     server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory)
  34.     fmt.Println("thrift server in", NetworkAddr)
  35.     server.Serve()
  36. }
複製代碼


#編寫go client端代碼

  1. root@m1:/home/hadoop/thrift_demo# vi c.go
  2. package main
  3. import (
  4.     "idoall/org/demo"
  5.     "fmt"
  6.     "git.apache.org/thrift.git/lib/go/thrift"
  7.     "net"
  8.     "os"
  9.     "time"
  10.     "strconv"
  11. )
  12. const (
  13.     HOST = "127.0.0.1"
  14.     PORT = "10086"
  15. )
  16. func main() {
  17.     startTime := currentTimeMillis()
  18.     transportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory())
  19.     protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
  20.     transport, err := thrift.NewTSocket(net.JoinHostPort(HOST, PORT))
  21.     if err != nil {
  22.         fmt.Fprintln(os.Stderr, "error resolving address:", err)
  23.         os.Exit(1)
  24.     }
  25.     useTransport := transportFactory.GetTransport(transport)
  26.     client := demo.NewIdoallThriftClientFactory(useTransport, protocolFactory)
  27.     if err := transport.Open(); err != nil {
  28.         fmt.Fprintln(os.Stderr, "Error opening socket to "+HOST+":"+PORT, " ", err)
  29.         os.Exit(1)
  30.     }
  31.     defer transport.Close()
  32.     for i := 0; i < 5; i++ {
  33.         paramMap := make(map[string]string)
  34.         paramMap["a"] = "idoall"
  35.         paramMap["b"] = "org"+strconv.Itoa(i+1)
  36.         r1, _ := client.CallBack(time.Now().UnixNano() / 1000000, "go client", paramMap)
  37.         fmt.Println("GOClient Call->", r1)
  38.     }
  39.     model := demo.Student{11,"student-idoall-go",true,20}
  40.     client.Put(&model)
  41.     endTime := currentTimeMillis()
  42.     fmt.Printf( "本次調用用時:%d-%d=%d毫秒\n",endTime,startTime, (endTime - startTime))
  43. }
  44. func currentTimeMillis() int64 {
  45.     return time.Now().UnixNano() / 1000000
  46. }
複製代碼


#運行go服務端(能夠看到服務端已經在監聽本機的10086端口)

  1. root@m1:/home/hadoop/thrift_demo# go run s.go
  2. thrift server in 0.0.0.0:10086
複製代碼


#運行go客戶端

  1. root@m1:/home/hadoop/thrift_demo# go run c.go
  2. GOClient Call-> [key:idoall    value:org1]
  3. GOClient Call-> [key:idoall    value:org2]
  4. GOClient Call-> [key:idoall    value:org3]
  5. GOClient Call-> [key:idoall    value:org4]
  6. GOClient Call-> [key:idoall    value:org5]
  7. 本次調用用時:1408267333489-1408267333486=3毫秒
  8. root@m1:/home/hadoop/thrift_demo#
複製代碼


#查看go服務端,能夠看到數據的交互

  1. root@m1:/home/hadoop/thrift_demo# go run s.go
  2. thrift server in 0.0.0.0:10086
  3. -->from client Call: 1408267333487 go client map[a:idoall b:org1]
  4. -->from client Call: 1408267333487 go client map[a:idoall b:org2]
  5. -->from client Call: 1408267333488 go client map[b:org3 a:idoall]
  6. -->from client Call: 1408267333488 go client map[a:idoall b:org4]
  7. -->from client Call: 1408267333488 go client map[a:idoall b:org5]
  8. Stduent--->id: 11       name:student-idoall-go  sex:true        age:20
複製代碼


2) python 客戶端的實現與golang 服務端的交互
        #將python用到的Thrift包複製到thrift_demo裏面

  1. root@m1:/home/hadoop/thrift_demo# cp -r /home/hadoop/thrift-git/lib/py/build /home/hadoop/thrift_demo/libpy
  2. root@m1:/home/hadoop/thrift_demo# cp -r /home/hadoop/thrift-git/tutorial/gen-py /home/hadoop/thrift_demo/gen-py
複製代碼


#編寫python client代碼

  1. root@m1:/home/hadoop/thrift_demo# vi c.py
  2. #!/usr/bin/env python
  3. # -*- coding: utf-8 -*-
  4. import sys, glob, time,datetime
  5. sys.path.append('gen-py')
  6. sys.path.insert(0, glob.glob('libpy/lib.*')[0])
  7. from idoall.org.demo import idoallThrift
  8. from idoall.org.demo.ttypes import *
  9. from thrift import Thrift
  10. from thrift.transport import TSocket
  11. from thrift.transport import TTransport
  12. from thrift.protocol import TBinaryProtocol
  13. try:
  14.   startTime = time.time()*1000
  15.   # Make socket
  16.   transport = TSocket.TSocket('127.0.0.1', 10086)
  17.   # Framed is critical. Raw sockets are very slow
  18.   transport = TTransport.TFramedTransport(transport)
  19.   # Wrap in a protocol
  20.   protocol = TBinaryProtocol.TBinaryProtocol(transport)
  21.   # Create a client to use the protocol encoder
  22.   client = idoallThrift.Client(protocol)
  23.   # Connect!
  24.   transport.open()
  25.   for i in range(1,6):
  26.     r = client.CallBack(time.time()*1000,"python client",{"a":"idoall","b":"org"+str(i)})
  27.     print "PythonClient Call->%s" %(r)
  28.   u1 = Student()  
  29.   u1.sid=111 
  30.   u1.sname='student-idoall-python' 
  31.   u1.ssex=False
  32.   u1.sage=200
  33.   client.put(u1)
  34.   endTime = time.time()*1000
  35.   print "本次調用用時:%d-%d=%d毫秒" %(endTime,startTime, (endTime - startTime))
  36.   # Close!
  37.   transport.close()
  38. except Thrift.TException, tx:
  39.   print 'ERROR:%s' % (tx.message)
複製代碼


#運行go服務端

  1. root@m1:/home/hadoop/thrift_demo# go run s.go
  2. thrift server in 0.0.0.0:10086
複製代碼


#運行python客戶端

  1. root@m1:/home/hadoop/thrift_demo# python c.py 
  2. PythonClient Call->['key:idoall    value:org1']
  3. PythonClient Call->['key:idoall    value:org2']
  4. PythonClient Call->['key:idoall    value:org3']
  5. PythonClient Call->['key:idoall    value:org4']
  6. PythonClient Call->['key:idoall    value:org5']
  7. 本次調用用時:1408268651648-1408268651646=2毫秒
  8. root@m1:/home/hadoop/thrift_demo#
複製代碼


#查看go服務端,能夠看到數據的交互

  1. root@m1:/home/hadoop/thrift_demo# go run s.go
  2. thrift server in 0.0.0.0:10086
  3. -->from client Call: 1408268651646 python client map[b:org1 a:idoall]
  4. -->from client Call: 1408268651646 python client map[a:idoall b:org2]
  5. -->from client Call: 1408268651647 python client map[a:idoall b:org3]
  6. -->from client Call: 1408268651647 python client map[a:idoall b:org4]
  7. -->from client Call: 1408268651647 python client map[a:idoall b:org5]
  8. Stduent--->id: 111      name:student-idoall-python      sex:false       age:200
複製代碼


3) php 客戶端的實現與golang 服務端的交互
        #編譯php的Thrift擴展

  1. root@m1:/home/hadoop/thrift_demo# cd /home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol   
  2. root@m1:/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol# ls
  3. acinclude.m4    build         config.h.in  config.nice    configure     include     ltmain.sh           Makefile.global   mkinstalldirs            php_thrift_protocol.h   thrift_protocol.la
  4. aclocal.m4      config.guess  config.log   config.status  configure.in  install-sh  Makefile            Makefile.objects  modules                  php_thrift_protocol.lo
  5. autom4te.cache  config.h      config.m4    config.sub     config.w32    libtool     Makefile.fragments  missing           php_thrift_protocol.cpp  run-tests.php
  6. root@m1:/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol# phpize
  7. Configuring for:
  8. PHP Api Version:         20121113
  9. Zend Module Api No:      20121212
  10. Zend Extension Api No:   220121212
  11. root@m1:/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol# ./configure
  12. ##如下只給出部分輸出信息
  13. checking for grep that handles long lines and -e... /bin/grep
  14. checking for egrep... /bin/grep -E
  15. checking for a sed that does not truncate output... /bin/sed
  16. checking for cc… cc
  17. config.status: creating config.h
  18. config.status: config.h is unchanged
  19. config.status: executing libtool commands
  20. #執行make命令後,咱們能夠看到擴展文件放到了/usr/lib/php5/20121212/目錄
  21. root@m1:/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol# make && make install
  22. Build complete.
  23. Don't forget to run 'make test'.
  24. Installing shared extensions:     /usr/lib/php5/20121212/
複製代碼


#讓PHP支持thrift,編輯php.ini文件,搜索extension_dir,而後在下面加上extension=thrift_protocol.so,保存退出。

  1. root@m1:/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol# vi /etc/php5/fpm/php.ini
  2. ; Directory in which the loadable extensions (modules) reside.
  3. ; http://php.net/extension-dir
  4. ; extension_dir = "./"
  5. ; On windows:
  6. ; extension_dir = "ext"
  7. extension=thrift_protocol.so
複製代碼


#重啓php5-fpm

  1. root@m1:/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol# service php5-fpm restart
  2. php5-fpm stop/waiting
  3. php5-fpm start/running, process 16522
  4. root@m1:/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol#
複製代碼


#將php用到的Thrift包複製到thrift_demo裏面

  1. root@m1:/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol# mkdir -p /home/hadoop/thrift_demo/libphp/
  2. 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/
  3. 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
  4. 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
  5. root@m1:/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol# cd /home/hadoop/thrift_demo
複製代碼


#編寫php client端代碼

  1. root@m1:/home/hadoop/thrift_demo# vi c.php
  2. <?php 
  3. $startTime = getMillisecond();
  4. $GLOBALS['THRIFT_ROOT'] = './libphp';   # 指定庫目錄,能夠是絕對路徑或是相對路徑 
  5. require_once $GLOBALS['THRIFT_ROOT'].'/Thrift/ClassLoader/ThriftClassLoader.php';
  6. use Thrift\ClassLoader\ThriftClassLoader; 
  7. use Thrift\Protocol\TBinaryProtocol; 
  8. use Thrift\Transport\TSocket; 
  9. use Thrift\Transport\TSocketPool; 
  10. use Thrift\Transport\TFramedTransport; 
  11. use Thrift\Transport\TBufferedTransport;
  12. $GEN_DIR = realpath(dirname(__FILE__)).'/gen-php';
  13. $loader = new ThriftClassLoader(); 
  14. $loader->registerNamespace('Thrift', $GLOBALS['THRIFT_ROOT']); # 加載thrift 
  15. $loader->registerDefinition('idoall\org\demo', $GEN_DIR); # 加載本身寫的thrift文件編譯的類文件和數據定義 
  16. $loader->register();
  17. $socket = new TSocket('127.0.0.1', 10086);     # 創建socket 
  18. $socket->setDebug(TRUE); 
  19. $framedSocket = new TFramedTransport($socket); #這個要和服務器使用的一致 
  20. $transport = $framedSocket; 
  21. $protocol = new TBinaryProtocol($transport);   # 這裏也要和服務器使用的協議一致 
  22. $transport->open();
  23. $client= new \idoall\org\demo\idoallThriftClient($protocol);  # 構造客戶端
  24. for($i=1;$i<6;$i++)
  25. {
  26.     $item = array();
  27.     $item["a"] = "idoall";
  28.     $item["b"] = "org"+$i;
  29.     $result = $client->CallBack(getMillisecond(),"php client",$item); # 對服務器發起rpc調用 
  30.     echo "PHPClient Call->".implode('',$result)."\n";
  31. }
  32. $s = new \idoall\org\demo\Student();
  33. $s->sid=1111;
  34. $s->sname="student-idoall-php";
  35. $s->ssex = false;
  36. $s->sage = 2000;
  37. $client->put($s);
  38. $endTime = getMillisecond();
  39. echo "本次調用用時:".$endTime."-".$startTime."=".($endTime-$startTime)."毫秒\n";
  40. function getMillisecond() {
  41. list($t1, $t2) = explode(' ', microtime());     
  42. return (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000);  
  43. }
  44. $transport->close();                       # 關閉連接
複製代碼


#運行go服務端

  1. root@m1:/home/hadoop/thrift_demo# go run s.go
  2. thrift server in 0.0.0.0:10086
複製代碼


#運行php客戶端

  1. root@m1:/home/hadoop/thrift_demo# php c.php   
  2. PHPClient Call->key:idoall    value:1
  3. PHPClient Call->key:idoall    value:2
  4. PHPClient Call->key:idoall    value:3
  5. PHPClient Call->key:idoall    value:4
  6. PHPClient Call->key:idoall    value:5
  7. 本次調用用時:1408268739277-1408268739269=8毫秒
複製代碼

#查看go服務端,能夠看到數據的交互

  1. root@m1:/home/hadoop/thrift_demo# go run s.go
  2. thrift server in 0.0.0.0:10086
  3. -->from client Call: 1408268739272 php client map[a:idoall b:1]
  4. -->from client Call: 1408268739273 php client map[a:idoall b:2]
  5. -->from client Call: 1408268739274 php client map[a:idoall b:3]
  6. -->from client Call: 1408268739275 php client map[a:idoall b:4]
  7. -->from client Call: 1408268739275 php client map[a:idoall b:5]
  8. 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. root@m1:/home/hadoop/thrift_demo# cp -r /home/hadoop/thrift-git/tutorial/gen-java .
  2. root@m1:/home/hadoop/thrift_demo# cd gen-java
  3. root@m1:/home/hadoop/thrift_demo/gen-java# mkdir -p src/main/java
  4. root@m1:/home/hadoop/thrift_demo/gen-java# mkdir META-INF
  5. root@m1:/home/hadoop/thrift_demo/gen-java# mkdir lib
  6. 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. root@m1:/home/hadoop/thrift_demo/gen-java# vi idoall/org/demo/c.java
  2. package idoall.org.demo;
  3. import java.util.HashMap;
  4. import java.util.List;
  5. import java.util.Map;
  6. import org.apache.thrift.TException;
  7. import org.apache.thrift.protocol.TBinaryProtocol;
  8. import org.apache.thrift.protocol.TProtocol;
  9. import org.apache.thrift.transport.TFramedTransport;
  10. import org.apache.thrift.transport.TSocket;
  11. import org.apache.thrift.transport.TTransport;
  12. import org.apache.thrift.transport.TTransportException;
  13. public class c {
  14.      
  15.     public static final String SERVER_IP = "m1";
  16.     public static final int SERVER_PORT = 10086;
  17.     public static final int TIMEOUT = 30000;
  18.     /**
  19.      * @param args
  20.      */
  21.     public static void main(String[] args) {
  22.          
  23.         long startTime=System.currentTimeMillis();   //獲取開始時間
  24.         TTransport transport = null;
  25.         try {
  26.             transport = new TFramedTransport(new TSocket(SERVER_IP,
  27.                     SERVER_PORT, TIMEOUT));
  28.             // 協議要和服務端一致
  29.             TProtocol protocol = new TBinaryProtocol(transport);
  30.             idoallThrift.Client client = new idoallThrift.Client(
  31.                     protocol);
  32.             transport.open();
  33.              
  34.             for(int i=1;i<6;i++)
  35.             {
  36.                 Map<String,String> m = new HashMap<String,String>();
  37.                 m.put("a", "idoall");
  38.                 m.put("b", "org"+i);
  39.                  
  40.                 List<String> result = client.CallBack(System.currentTimeMillis(),"java client",m);
  41.                 System.out.println("JAVAClient Call->" + result);
  42.             }
  43.              
  44.             Student s = new Student();
  45.             s.sid=1111;
  46.             s.sname="student-idoall-java";
  47.             s.ssex = true;
  48.             s.sage = 20000;
  49.             client.put(s);
  50.             long endTime = System.currentTimeMillis();
  51.             System.out.println("本次調用用時:" + endTime + "-" + startTime + "=" + (endTime - startTime)+"毫秒");
  52.              
  53.         } catch (TTransportException e) {
  54.             e.printStackTrace();
  55.         } catch (TException e) {
  56.             e.printStackTrace();
  57.         } finally {
  58.             if (null != transport) {
  59.                 transport.close();
  60.             }
  61.         }
  62.     }
  63. }
複製代碼


#配置jar包的MANIFEST文件

  1. root@m1:/home/hadoop/thrift_demo/gen-java# vi META-INF/MANIFEST.MF
  2. Manifest-Version: 1.0
  3. Main-Class: idoall.org.demo.c
  4. Class-Path: lib/**.jar
複製代碼


#製做Maven的描述文件pom.xml

  1. root@m1:/home/hadoop/thrift_demo/gen-java# vi pom.xml
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4.     <modelVersion>4.0.0</modelVersion>
  5.     <groupId>idoall.org.demo</groupId>
  6.     <artifactId>idoall.org.demo</artifactId>
  7.     <version>0.0.1-SNAPSHOT</version>
  8.     <packaging>jar</packaging>
  9.     <name>idoall.org.demo</name>
  10.     <url>http://maven.apache.org</url>
  11.     <properties>
  12.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  13.     </properties>
  14.     <dependencies>
  15.         <dependency>
  16.             <groupId>junit</groupId>
  17.             <artifactId>junit</artifactId>
  18.             <version>3.8.1</version>
  19.             <scope>test</scope>
  20.         </dependency>
  21.         <dependency>
  22.             <groupId>org.apache.thrift</groupId>
  23.             <artifactId>libthrift</artifactId>
  24.             <version>0.9.1</version>
  25.         </dependency>
  26.         <dependency>
  27.             <groupId>org.slf4j</groupId>
  28.             <artifactId>slf4j-log4j12</artifactId>
  29.             <version>1.5.8</version>
  30.         </dependency>
  31.     </dependencies>
  32.     <build>
  33.         <plugins>
  34.             <plugin>
  35.                 <artifactId>maven-assembly-plugin</artifactId>
  36.                 <configuration>
  37.                     <archive>
  38.                         <manifest>
  39.                             <mainClass>idoall.org.demo.c</mainClass>
  40.                         </manifest>
  41.                     </archive>
  42.                     <descriptorRefs>
  43.                         <descriptorRef>jar-with-dependencies</descriptorRef>
  44.                     </descriptorRefs>
  45.                 </configuration>
  46.             </plugin>
  47.             <plugin>
  48.                 <groupId>org.apache.maven.plugins</groupId>
  49.                 <artifactId>maven-compiler-plugin</artifactId>
  50.                 <configuration>
  51.                     <source>1.6</source>
  52.                     <target>1.6</target>
  53.                 </configuration>
  54.             </plugin>
  55.         </plugins>
  56.     </build>
  57. </project>
複製代碼


#使用maven工具,將相關依賴打包到當前目錄的target目錄中,並生成idoall.org.demo-0.0.1-SNAPSHOT-jar-with-dependencies.jar

  1. root@m1:/home/hadoop/thrift_demo/gen-java# mv idoall src/main/java/
  2. root@m1:/home/hadoop/thrift_demo/gen-java# mvn assembly:assembly
  3. #如下只給出部分提示信息
  4. [INFO] ------------------------------------------------------------------------
  5. [INFO] BUILD SUCCESS
  6. [INFO] ------------------------------------------------------------------------
  7. [INFO] Total time: 7.618s
  8. [INFO] Finished at: Sun Aug 17 09:36:48 CST 2014
  9. [INFO] Final Memory: 12M/29M
  10. [INFO] ------------------------------------------------------------------------
複製代碼


#運行go服務端

  1. root@m1:/home/hadoop/thrift_demo# go run s.go
  2. thrift server in 0.0.0.0:10086
複製代碼


#運行打包後的java客戶端

  1. root@m1:/home/hadoop/thrift_demo/gen-java# java -jar target/idoall.org.demo-0.0.1-SNAPSHOT-jar-with-dependencies.jar 
  2. JAVAClient Call->[key:idoall    value:org1]
  3. JAVAClient Call->[key:idoall    value:org2]
  4. JAVAClient Call->[key:idoall    value:org3]
  5. JAVAClient Call->[key:idoall    value:org4]
  6. JAVAClient Call->[key:idoall    value:org5]
  7. 本次調用用時:1408268973582-1408268973477=105毫秒
複製代碼


#查看go服務端,能夠看到數據的交互

  1. root@m1:/home/hadoop/thrift_demo# go run s.go
  2. thrift server in 0.0.0.0:10086
  3. -->from client Call: 1408268973547 java client map[a:idoall b:org1]
  4. -->from client Call: 1408268973568 java client map[b:org2 a:idoall]
  5. -->from client Call: 1408268973568 java client map[b:org3 a:idoall]
  6. -->from client Call: 1408268973568 java client map[b:org4 a:idoall]
  7. -->from client Call: 1408268973569 java client map[b:org5 a:idoall]
  8. Stduent--->id: 1111     name:student-idoall-java        sex:true        age:20000
複製代碼




<ignore_js_op> thrift_demo.tar.gz (1.18 MB, 下載次數: 1) 

相關文章
相關標籤/搜索