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的官方网站在哪里?

  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

[email protected]:/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

[email protected]:/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

[email protected]:/home/hadoop/thrift-git# apt-get update

[email protected]:/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

[email protected]:/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.

[email protected]:/home/hadoop#cd thrift-git

[email protected]:/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

[email protected]:/home/hadoop/thrift-git#./bootstrap.sh

[email protected]:/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

[email protected]:/home/hadoop/thrift-git# make

[email protected]:/home/hadoop/thrift-git# make install

    我们可以看到thrift已经安装完成,当前版本是0.9.1

?


1

2

[email protected]:/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

[email protected]:/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

[email protected]:/home/hadoop/thrift-git/tutorial# thrift -r --gen go idoall.org.thrift

[email protected]:/home/hadoop/thrift-git/tutorial# thrift -r --gen py idoall.org.thrift  

[email protected]:/home/hadoop/thrift-git/tutorial# thrift -r --gen php idoall.org.thrift  

[email protected]:/home/hadoop/thrift-git/tutorial# thrift -r --gen java idoall.org.thrift

  如果编译IDL的PHP包要生成server端代码,和其他语言不太一样,可以使用thrift --help查看使用说明,需要加上server选项,如下:

?


1

[email protected]:/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

[email protected]:/home/hadoop/thrift-git/tutorial# go get git.apache.org/thrift.git/lib/go/thrift

#将Thrift生成的开发库也复制到GOPATH中

?


1

[email protected]:/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

[email protected]:/home/hadoop# mkdir thrift_demo

[email protected]:/home/hadoop# cd thrift_demo/

[email protected]:/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

[email protected]:/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

[email protected]:/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

[email protected]:/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毫秒

[email protected]:/home/hadoop/thrift_demo#

#查看go服务端,可以看到数据的交互

?


1

2

3

4

5

6

7

8

[email protected]:/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

[email protected]:/home/hadoop/thrift_demo# cp -r /home/hadoop/thrift-git/lib/py/build /home/hadoop/thrift_demo/libpy

[email protected]:/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

[email protected]:/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

[email protected]:/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

[email protected]:/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毫秒

[email protected]:/home/hadoop/thrift_demo#

#查看go服务端,可以看到数据的交互

?


1

2

3

4

5

6

7

8

[email protected]:/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

[email protected]:/home/hadoop/thrift_demo# cd /home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol  

[email protected]:/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

[email protected]:/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

[email protected]:/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/目录

[email protected]:/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

[email protected]:/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

[email protected]:/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol# service php5-fpm restart

php5-fpm stop/waiting

php5-fpm start/running, process 16522

[email protected]:/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol#

#将php用到的Thrift包复制到thrift_demo里面

?


1

2

3

4

5

[email protected]:/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol# mkdir -p /home/hadoop/thrift_demo/libphp/

[email protected]:/home/hadoop/thrift-git/lib/php/src/ext/thrift_protocol# cp -r /home/hadoop/thrift-git/lib/php/src/* /home/hadoop/thrift_demo/libphp/

[email protected]:/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

[email protected]:/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

[email protected]:/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

[email protected]:/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

[email protected]:/home/hadoop/thrift_demo# go run s.go

thrift server in 0.0.0.0:10086

#运行php客户端

?


1

2

3

4

5

6

7

[email protected]:/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

[email protected]:/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

[email protected]:/home/hadoop/thrift_demo# apt-get install maven

#将java用到的Thrift包复制到thrift_demo里面

?


1

2

3

4

5

6

[email protected]:/home/hadoop/thrift_demo# cp -r /home/hadoop/thrift-git/tutorial/gen-java .

[email protected]:/home/hadoop/thrift_demo# cd gen-java

[email protected]:/home/hadoop/thrift_demo/gen-java# mkdir -p src/main/java

[email protected]:/home/hadoop/thrift_demo/gen-java# mkdir META-INF

[email protected]:/home/hadoop/thrift_demo/gen-java# mkdir lib

[email protected]:/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

[email protected]:/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

[email protected]:/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

[email protected]:/home/hadoop/thrift_demo/gen-java# mv idoall src/main/java/

[email protected]:/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

[email protected]:/home/hadoop/thrift_demo# go run s.go

thrift server in 0.0.0.0:10086

#运行打包后的java客户端

?


1

2

3

4

5

6

7

[email protected]:/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

[email protected]:/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!"

---------------------------------------

博文作者:迦壹

博客地址:Golang、Php、Python、Java基于Thrift0.9.1实现跨语言调用

转载声明:可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明,谢谢合作!

---------------------------------------

Golang、Php、Python、Java基于Thrift0.9.1实现跨语言调用,布布扣,bubuko.com

时间: 2024-10-12 14:22:05

Golang、Php、Python、Java基于Thrift0.9.1实现跨语言调用的相关文章

(转)使用Thrift0.9.1实现跨语言调用Golang、Php、Python、Java

问题导读:什么是Thrift?Thrift的官方网站在哪里?Golang.Java.Python.PHP之间如何通过Thrift实现跨语言调用? 一.什么是Thrift Thrift是一种可伸缩的跨语言服务的发展软件框架.它结合了功能强大的软件堆栈的代码生成引擎,以建设服务. Thrift是facebook开发的,07年4月开放源代码,08年5月进入apache孵化器.创造Thrift是为了解决facebook系统中各系统间大数据量的传 输通信以及系统之间语言环境不同需要跨平台的特性.所以thr

Java跨语言调用,使用JNA访问Java外部接口

1. JNA简单介绍 先说JNI(Java Native Interface)吧,有过不同语言间通信经历的一般都知道,它允许Java代码和其他语言(尤其C/C++)写的代码进行交互,只要遵守调用约定即可.首先看下JNI调用C/C++的过程,注意写程序时自下而上,调用时自上而下. 可 见步骤非常的多,很麻烦,使用JNI调用.dll/.so共享库都能体会到这个痛苦的过程.如果已有一个编译好的.dll/.so文件,如果使用JNI技 术调用,我们首先需要使用C语言另外写一个.dll/.so共享库,使用S

C++ 跨语言调用 Java

C++ 跨语言调用 Java Java JDK 提供了 JNI 接口供 C/C++ 程序调用 Java 编译后的类与方法,主要依赖于头文件(jni.h) 和 动态库(jvm.so/jvm.dll),由于 JNI 包含了丰富的接口映射和跨语言的数据通信,非常复杂(坑 深不见底),所以这里只对一个测试程序进行简单的描述. 最开始测试的时候选择了 Window7 64 的环境,安装的 Java JDK 也是64位的,但是我们都知道 VS 编译的程序默认情况下都是32位程序,所以我在 LoadLibra

#python+java#同样功能的代码两种语言实现

概述:设置两个数组/列表,列表a是[1,2,3],列表b是['a','b','c'],把他们一对一对打印出来,但不打印"3:c"这对. python版: ''' Created on 2014-11-2 @author: Administrator ''' class MyArray:     def __init__(self):         self.a = range(1,4)         self.b = ['a','b','c']     def getValue(s

Atitit java c# php c++ js跨语言调用matlab实现边缘检测等功能attilax总结

1.1. 边缘检测的基本方法Canny最常用了1 1.2. 编写matlab边缘检测代码,保存为m文件1 1.3. 通过cli接口调用Matlab执行m文件1 1.4. 效果如图1 1.1. 边缘检测的基本方法Canny最常用了 1.2. 编写matlab边缘检测代码,保存为m文件 fprintf('Hello World'); imag = imread('C:\00edge\a.jpg');  %读取 imag = rgb2gray(imag);        %转化为灰度图 %imag_f

2017年的golang、python、php、c++、c、java、Nodejs性能对比[续]

2017年的golang.python.php.c++.c.java.Nodejs性能对比[续] 最近忙,这个话题放了几天,今天来个续集.   上篇传送门: 2017年的golang.python.php.c++.c.java.Nodejs性能对比(golang python php c++ java Nodejs Performance)   好了,上回的某些事有些人有异议,今天也回应下. 1.有人说python性能没那么Low? 这个我用pypy 2.7确认了下,确实没那么差, 如果用num

2017年的golang、python、php、c++、c、java、Nodejs性能对比(golang python php c++ java Nodejs Performance)

2017年的golang.python.php.c++.c.java.Nodejs性能对比 本人在PHP/C++/Go/Py时,突发奇想,想把最近主流的编程语言性能作个简单的比较, 至于怎么比,还是不得不用神奇的斐波那契算法.可能是比较常用或好玩吧. 好了,talk is cheap, show me your code!  打开Mac,点开Clion开始Coding吧! 1.怎么第一是Go呢,因为我个人最近正在用,感觉很不错 package main import "fmt" fun

Python/Java程序员面试必备常用问题解析与答案

转自AI算法联盟,理解python技术问题,以及一些常见的java面试中经常遇到的问题,这些面试问题分为四类: 是什么(what) 如何做(how) 说区别/谈优势(difference) 实践操作(practice) 1. 什么是Python? Python是一种编程语言,它有对象.模块.线程.异常处理和自动内存管理.可以加入与其他语言的对比.下面是回答这一问题的几个关键点: a. Python是一种解释型语言,python代码在运行之前不需要编译. b. Python是动态类型语言,在声明变

十大经典排序算法(Python,Java实现)

参照:https://www.cnblogs.com/wuxinyan/p/8615127.html https://www.cnblogs.com/onepixel/articles/7674659.html 一.排序算法分类: 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序. 非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排 二.算法复杂度 注(