vlambda博客
学习文章列表

Thrift介绍以及Java中使用Thrift实现RPC示例

场景

Thrift

Thrift最初由Facebook研发,主要用于各个服务之间的RPC通信,支持跨语言,常用的语言比如C++, Java, Python,PHP, Ruby, Erlang,Perl,Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml都支持。

Thrift是一个典型的CS(客户端/服务端)结构,客户端和服务端可以使用不同的语言开发。既然客户端和服务端能使用不同的语言开发,那么一定就要有一种中间语言来关联客户端和服务端的语言,这种语言就是IDL (Interface Description Language)。

RPC

RPC, 远程过程调用,直观说法就是A通过网络调用B的过程方法。

简单的说,RPC就是从一台机器(客户端)上通过参数传递的方式调用另一台机器(服务器)上的一个函数或方法(可以统称为服务)并得到返回的结果。

RPC 会隐藏底层的通讯细节(不需要直接处理Socket通讯或Http通讯) RPC 是一个请求响应模型。

客户端发起请求,服务器返回响应(类似于Http的工作方式) RPC 在使用形式上像调用本地函数(或方法)一样去调用远程的函数(或方法)。

注:

实现

Thrift数据类型

Thrift不支持无符号类型,因为很多编程语言不存在无符号类型,比如Java。

byte:有符号字节
i16:16位有符号整数
i32:32位有符号整数
i64:64位有符号整数
double:64位浮点数
string:字符串类型

Thrift容器类型

list:一系列由T类型的数据组成的有序列表,元素可以重复

set:一系列由T类型的数据组成的无序集合,元素不可重复

map:一个字典结构,key为K类型,value为V类型,相当于Java中的HashMap

Thrift工作原理

如何实现多语言之间的通信?

数据传输使用socket(多种语言均支持),数据再以特定的格式(String等)发送,接收方语言进行解析。

定义thrift的文件,由thrift文件(IDL)生成双方语言的接口、model,在生成的model以及接口中会有解码编码的代码。

Thrift结构体

就像C语言一样,Thrift支持struct类型,目的就是将
一些数据聚合在一起,方便传输管理。struct的定义
形式如下:

br

Thrift枚举

枚举的定义形式和Java的Enum定义类似


  
    
    
  
  1. enum Gender{

  2. MALE,

  3. FEMALE

  4. }

Thrift异常

Thrift支持自定义exception,规则与struct一样


  
    
    
  
  1. exception RequestException{

  2. 1:i32 code;

  3. 2: string reason:

  4. }

Thrift服务

Thrift定义服务相当于Java中创建Interface一样,创建的service经过代码生成命令之后就会生成客户端和服务端的框架代码。定义形式如下:、


  
    
    
  
  1. service HelloWordService {

  2. // service中定义的函数,相当于Java interface中定义的方法

  3. string doAction(1:string name,2: i32 age);

  4. }

Thrift类型定义

Thrift支持类似C++一样的typedef定义:


  
    
    
  
  1. typedef i32 int

  2. typedef i64 long

定义别名

Thrift常量

thrift也支持常量定义,使用const关键字:


  
    
    
  
  1. const i32 MAX_RETRIES_TIME=10

  2. const string MY_WEBSITE=

  3. "https://blog.csdn.net/BADAO_LIUMANG_QIZHI'

命名空间

Thrift的命名空间相当于Java中的package的意思,主要目的是组织代码。thrift使用关键字namespace 定义命名空间:

namespace java com.bdao.thrift

格式是: namespace 语言名 路径

文件包含

Thrift也支持文件包含,相当于C/C++中的include,Java中的import。使用关键字include定义:

include "global.thrift"

注释

Thrift注释方式支持shell风格的注释,支持C/C++风格的注释,即#和//开头的语句都当做注释,/**/包裹的语句也是注释。

可选与必选

Thrift提供两个关键字required, optional,分别用于表示对应的字段是必填的还是可选的


  
    
    
  
  1. struct People{

  2.   1:required string name;

  3.   2:optional i32 age;

  4. }

Thrift IDL示例文件


  
    
    
  
  1. namespace c_glib TTest

  2. namespace cpp thrift.test

  3. namespace delphi Thrift.Test

  4. namespace go thrifttest

  5. namespace java thrift.test

  6. namespace js ThriftTest

  7. namespace lua ThriftTest

  8. namespace netstd ThriftTest

  9. namespace perl ThriftTest

  10. namespace php ThriftTest

  11. namespace py ThriftTest

  12. namespace py.twisted ThriftTest

  13. namespace rb Thrift.Test

  14. namespace st ThriftTest

  15. namespace xsd test (uri = 'http://thrift.apache.org/ns/ThriftTest')

  16.  

  17. // Presence of namespaces and sub-namespaces for which there is

  18. // no generator should compile with warnings only

  19. namespace noexist ThriftTest

  20. namespace cpp.noexist ThriftTest

  21.  

  22. namespace * thrift.test

  23.  

  24. /**

  25.  * Docstring!

  26.  */

  27. enum Numberz

  28. {

  29.   ONE = 1,

  30.   TWO,

  31.   THREE,

  32.   FIVE = 5,

  33.   SIX,

  34.   EIGHT = 8

  35. }

  36.  

  37. const Numberz myNumberz = Numberz.ONE;

  38. // the following is expected to fail:

  39. // const Numberz urNumberz = ONE;

  40.  

  41. typedef i64 UserId

  42.  

  43. struct Bonk

  44. {

  45.   1: string message,

  46.   2: i32 type

  47. }

  48.  

  49. typedef map<string,Bonk> MapType

  50.  

  51. struct Bools {

  52.   1: bool im_true,

  53.   2: bool im_false,

  54. }

  55.  

  56. struct Xtruct

  57. {

  58.   1:  string string_thing,

  59.   4:  i8     byte_thing,

  60.   9:  i32    i32_thing,

  61.   11: i64    i64_thing

  62. }

  63.  

  64. struct Xtruct2

  65. {

  66.   1: i8     byte_thing,  // used to be byte, hence the name

  67.   2: Xtruct struct_thing,

  68.   3: i32    i32_thing

  69. }

  70.  

  71. struct Xtruct3

  72. {

  73.   1:  string string_thing,

  74.   4:  i32    changed,

  75.   9:  i32    i32_thing,

  76.   11: i64    i64_thing

  77. }

  78.  

  79.  

  80. struct Insanity

  81. {

  82.   1: map<Numberz, UserId> userMap,

  83.   2: list<Xtruct> xtructs

  84. } (python.immutable= "")

  85.  

  86. struct CrazyNesting {

  87.   1: string string_field,

  88.   2: optional set<Insanity> set_field,

  89.   // Do not insert line break as test/go/Makefile.am is removing this line with pattern match

  90.   3: required list<map<set<i32> (python.immutable = ""), map<i32,set<list<map<Insanity,string>(python.immutable = "")> (python.immutable = "")>>>> list_field,

  91.   4: binary binary_field

  92. }

  93.  

  94. union SomeUnion {

  95.   1: map<Numberz, UserId> map_thing,

  96.   2: string string_thing,

  97.   3: i32 i32_thing,

  98.   4: Xtruct3 xtruct_thing,

  99.   5: Insanity insanity_thing

  100. }

  101.  

  102. exception Xception {

  103.   1: i32 errorCode,

  104.   2: string message

  105. }

  106.  

  107. exception Xception2 {

  108.   1: i32 errorCode,

  109.   2: Xtruct struct_thing

  110. }

  111.  

  112. struct EmptyStruct {}

  113.  

  114. struct OneField {

  115.   1: EmptyStruct field

  116. }

  117.  

  118. service ThriftTest

  119. {

  120.   /**

  121.    * Prints "testVoid()" and returns nothing.

  122.    */

  123.   void         testVoid(),

  124.  

  125.   /**

  126.    * Prints 'testString("%s")' with thing as '%s'

  127.    * @param string thing - the string to print

  128.    * @return string - returns the string 'thing'

  129.    */

  130.   string       testString(1: string thing),

  131.  

  132.   /**

  133.    * Prints 'testBool("%s")' where '%s' with thing as 'true' or 'false'

  134.    * @param bool  thing - the bool data to print

  135.    * @return bool  - returns the bool 'thing'

  136.    */

  137.   bool         testBool(1: bool thing),

  138.  

  139.   /**

  140.    * Prints 'testByte("%d")' with thing as '%d'

  141.    * The types i8 and byte are synonyms, use of i8 is encouraged, byte still exists for the sake of compatibility.

  142.    * @param byte thing - the i8/byte to print

  143.    * @return i8 - returns the i8/byte 'thing'

  144.    */

  145.   i8           testByte(1: i8 thing),

  146.  

  147.   /**

  148.    * Prints 'testI32("%d")' with thing as '%d'

  149.    * @param i32 thing - the i32 to print

  150.    * @return i32 - returns the i32 'thing'

  151.    */

  152.   i32          testI32(1: i32 thing),

  153.  

  154.   /**

  155.    * Prints 'testI64("%d")' with thing as '%d'

  156.    * @param i64 thing - the i64 to print

  157.    * @return i64 - returns the i64 'thing'

  158.    */

  159.   i64          testI64(1: i64 thing),

  160.  

  161.   /**

  162.    * Prints 'testDouble("%f")' with thing as '%f'

  163.    * @param double thing - the double to print

  164.    * @return double - returns the double 'thing'

  165.    */

  166.   double       testDouble(1: double thing),

  167.  

  168.   /**

  169.    * Prints 'testBinary("%s")' where '%s' is a hex-formatted string of thing's data

  170.    * @param binary  thing - the binary data to print

  171.    * @return binary  - returns the binary 'thing'

  172.    */

  173.   binary       testBinary(1: binary thing),

  174.  

  175.   /**

  176.    * Prints 'testStruct("{%s}")' where thing has been formatted into a string of comma separated values

  177.    * @param Xtruct thing - the Xtruct to print

  178.    * @return Xtruct - returns the Xtruct 'thing'

  179.    */

  180.   Xtruct       testStruct(1: Xtruct thing),

  181.  

  182.   /**

  183.    * Prints 'testNest("{%s}")' where thing has been formatted into a string of the nested struct

  184.    * @param Xtruct2 thing - the Xtruct2 to print

  185.    * @return Xtruct2 - returns the Xtruct2 'thing'

  186.    */

  187.   Xtruct2      testNest(1: Xtruct2 thing),

  188.  

  189.   /**

  190.    * Prints 'testMap("{%s")' where thing has been formatted into a string of 'key => value' pairs

  191.    *  separated by commas and new lines

  192.    * @param map<i32,i32> thing - the map<i32,i32> to print

  193.    * @return map<i32,i32> - returns the map<i32,i32> 'thing'

  194.    */

  195.   map<i32,i32> testMap(1: map<i32,i32> thing),

  196.  

  197.   /**

  198.    * Prints 'testStringMap("{%s}")' where thing has been formatted into a string of 'key => value' pairs

  199.    *  separated by commas and new lines

  200.    * @param map<string,string> thing - the map<string,string> to print

  201.    * @return map<string,string> - returns the map<string,string> 'thing'

  202.    */

  203.   map<string,string> testStringMap(1: map<string,string> thing),

  204.  

  205.   /**

  206.    * Prints 'testSet("{%s}")' where thing has been formatted into a string of values

  207.    *  separated by commas and new lines

  208.    * @param set<i32> thing - the set<i32> to print

  209.    * @return set<i32> - returns the set<i32> 'thing'

  210.    */

  211.   set<i32>     testSet(1: set<i32> thing),

  212.  

  213.   /**

  214.    * Prints 'testList("{%s}")' where thing has been formatted into a string of values

  215.    *  separated by commas and new lines

  216.    * @param list<i32> thing - the list<i32> to print

  217.    * @return list<i32> - returns the list<i32> 'thing'

  218.    */

  219.   list<i32>    testList(1: list<i32> thing),

  220.  

  221.   /**

  222.    * Prints 'testEnum("%d")' where thing has been formatted into its numeric value

  223.    * @param Numberz thing - the Numberz to print

  224.    * @return Numberz - returns the Numberz 'thing'

  225.    */

  226.   Numberz      testEnum(1: Numberz thing),

  227.  

  228.   /**

  229.    * Prints 'testTypedef("%d")' with thing as '%d'

  230.    * @param UserId thing - the UserId to print

  231.    * @return UserId - returns the UserId 'thing'

  232.    */

  233.   UserId       testTypedef(1: UserId thing),

  234.  

  235.   /**

  236.    * Prints 'testMapMap("%d")' with hello as '%d'

  237.    * @param i32 hello - the i32 to print

  238.    * @return map<i32,map<i32,i32>> - returns a dictionary with these values:

  239.    *   {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 => 2, 3 => 3, 4 => 4, }, }

  240.    */

  241.   map<i32,map<i32,i32>> testMapMap(1: i32 hello),

  242.  

  243.   /**

  244.    * So you think you've got this all worked out, eh?

  245.    *

  246.    * Creates a map with these values and prints it out:

  247.    *   { 1 => { 2 => argument,

  248.    *            3 => argument,

  249.    *          },

  250.    *     2 => { 6 => <empty Insanity struct>, },

  251.    *   }

  252.    * @return map<UserId, map<Numberz,Insanity>> - a map with the above values

  253.    */

  254.   map<UserId, map<Numberz,Insanity>> testInsanity(1: Insanity argument),

  255.  

  256.   /**

  257.    * Prints 'testMulti()'

  258.    * @param i8 arg0 -

  259.    * @param i32 arg1 -

  260.    * @param i64 arg2 -

  261.    * @param map<i16, string> arg3 -

  262.    * @param Numberz arg4 -

  263.    * @param UserId arg5 -

  264.    * @return Xtruct - returns an Xtruct with string_thing = "Hello2, byte_thing = arg0, i32_thing = arg1

  265.    *    and i64_thing = arg2

  266.    */

  267.   Xtruct testMulti(1: i8 arg0, 2: i32 arg1, 3: i64 arg2, 4: map<i16, string> arg3, 5: Numberz arg4, 6: UserId arg5),

  268.  

  269.   /**

  270.    * Print 'testException(%s)' with arg as '%s'

  271.    * @param string arg - a string indication what type of exception to throw

  272.    * if arg == "Xception" throw Xception with errorCode = 1001 and message = arg

  273.    * else if arg == "TException" throw TException

  274.    * else do not throw anything

  275.    */

  276.   void testException(1: string arg) throws(1: Xception err1),

  277.  

  278.   /**

  279.    * Print 'testMultiException(%s, %s)' with arg0 as '%s' and arg1 as '%s'

  280.    * @param string arg - a string indicating what type of exception to throw

  281.    * if arg0 == "Xception" throw Xception with errorCode = 1001 and message = "This is an Xception"

  282.    * else if arg0 == "Xception2" throw Xception2 with errorCode = 2002 and struct_thing.string_thing = "This is an Xception2"

  283.    * else do not throw anything

  284.    * @return Xtruct - an Xtruct with string_thing = arg1

  285.    */

  286.   Xtruct testMultiException(1: string arg0, 2: string arg1) throws(1: Xception err1, 2: Xception2 err2)

  287.  

  288.   /**

  289.    * Print 'testOneway(%d): Sleeping...' with secondsToSleep as '%d'

  290.    * sleep 'secondsToSleep'

  291.    * Print 'testOneway(%d): done sleeping!' with secondsToSleep as '%d'

  292.    * @param i32 secondsToSleep - the number of seconds to sleep

  293.    */

  294.   oneway void testOneway(1:i32 secondsToSleep)

  295. }

  296.  

  297. service SecondService

  298. {

  299.   /**

  300.    * Prints 'testString("%s")' with thing as '%s'

  301.    * @param string thing - the string to print

  302.    * @return string - returns the string 'thing'

  303.    */

  304.   string secondtestString(1: string thing)

  305. }

  306.  

  307. struct VersioningTestV1 {

  308.        1: i32 begin_in_both,

  309.        3: string old_string,

  310.        12: i32 end_in_both

  311. }

  312.  

  313. struct VersioningTestV2 {

  314.        1: i32 begin_in_both,

  315.  

  316.        2: i32 newint,

  317.        3: i8 newbyte,

  318.        4: i16 newshort,

  319.        5: i64 newlong,

  320.        6: double newdouble

  321.        7: Bonk newstruct,

  322.        8: list<i32> newlist,

  323.        9: set<i32> newset,

  324.        10: map<i32, i32> newmap,

  325.        11: string newstring,

  326.        12: i32 end_in_both

  327. }

  328.  

  329. struct ListTypeVersioningV1 {

  330.        1: list<i32> myints;

  331.        2: string hello;

  332. }

  333.  

  334. struct ListTypeVersioningV2 {

  335.        1: list<string> strings;

  336.        2: string hello;

  337. }

  338.  

  339. struct GuessProtocolStruct {

  340.   7: map<string,string> map_field,

  341. }

  342.  

  343. struct LargeDeltas {

  344.   1: Bools b1,

  345.   10: Bools b10,

  346.   100: Bools b100,

  347.   500: bool check_true,

  348.   1000: Bools b1000,

  349.   1500: bool check_false,

  350.   2000: VersioningTestV2 vertwo2000,

  351.   2500: set<string> a_set2500,

  352.   3000: VersioningTestV2 vertwo3000,

  353.   4000: list<i32> big_numbers

  354. }

  355.  

  356. struct NestedListsI32x2 {

  357.   1: list<list<i32>> integerlist

  358. }

  359. struct NestedListsI32x3 {

  360.   1: list<list<list<i32>>> integerlist

  361. }

  362. struct NestedMixedx2 {

  363.   1: list<set<i32>> int_set_list

  364.   2: map<i32,set<string>> map_int_strset

  365.   3: list<map<i32,set<string>>> map_int_strset_list

  366. }

  367. struct ListBonks {

  368.   1: list<Bonk> bonk

  369. }

  370. struct NestedListsBonk {

  371.   1: list<list<list<Bonk>>> bonk

  372. }

  373.  

  374. struct BoolTest {

  375.   1: optional bool b = true;

  376.   2: optional string s = "true";

  377. }

  378.  

  379. struct StructA {

  380.   1: required string s;

  381. }

  382.  

  383. struct StructB {

  384.   1: optional StructA aa;

  385.   2: required StructA ab;

  386. }

  387.  

  388. struct OptionalSetDefaultTest {

  389.   1: optional set<string> with_default = [ "test" ]

  390. }

Thrift传输

 

thrift通过一个中间语言IDL(接口定义语言)来定义RPC的数据类型和接口,这些内容写在以.thrift结尾的文件中,然后通过特殊的编译器来生成不同语言的代码

,以满足不同需要的开发者,比如java开发者,就可以生成java代码,c++开发者可以生成c++代码,生成的代码中不但包含目标语言的接口定义,方法,数据类型,

还包含有RPC协议层和传输层的实现代码。

图中,TProtocol(协议层),定义数据传输格式,例如:

TBinaryProtocol:二进制格式;
TCompactProtocol:压缩格式;
TJSONProtocol:JSON格式;
TSimpleJSONProtocol:提供JSON只写协议, 生成的文件很容易通过脚本语言解析;
TDebugProtocol:使用易懂的可读的文本格式,以便于debug
TTransport(传输层),定义数据传输方式,可以为TCP/IP传输,内存共享或者文件共享等)被用作运行时库。

TSocket:阻塞式socker;
TFramedTransport:以frame为单位进行传输,非阻塞式服务中使用;
TFileTransport:以文件形式进行传输;
TMemoryTransport:将内存用于I/O,java实现时内部实际使用了简单的ByteArrayOutputStream;
TZlibTransport:使用zlib进行压缩, 与其他传输方式联合使用,当前无java实现;
 

Thrift支持的服务模型

TSimpleServer:简单的单线程服务模型,常用于测试;
TThreadPoolServer:多线程服务模型,使用标准的阻塞式IO;
TNonblockingServer:多线程服务模型,使用非阻塞式IO(需使用TFramedTransport数据传输方式);

Java中使用Thrift实现RPC示例

http://thrift.apache.org/download

这里下载Windows版本为例

 

Thrift介绍以及Java中使用Thrift实现RPC示例

下载thrift的exe文件

 

Thrift介绍以及Java中使用Thrift实现RPC示例

将其下载到磁盘中某目录,然后在环境变量的的系统变量的Path中将exe所在的路径添加。

 

Thrift介绍以及Java中使用Thrift实现RPC示例

这样就能在任何地方使用thrift-0.13.0.exe了,为了使用命令方便,将此exe命名为thrift.exe

然后打开cmd ,输入

thrift -version

 

Thrift介绍以及Java中使用Thrift实现RPC示例

出现如上则配置成功。

这里使用Gradle作为依赖管理,当然也可以使用Maven,只是管理方式不同而已。

Gradle在Windows下的下载安装与配置以及在IDEA中配置以及修改jar包位置:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108578033

参照上面在IDEA中进行搭建Gradle项目

然后在build.gradle中引入thrift的相关依赖,在Maven中央仓库中搜搜thrift

 

Thrift介绍以及Java中使用Thrift实现RPC示例

选择与编译器对应的版本这里是0.13.0

 

Thrift介绍以及Java中使用Thrift实现RPC示例

选择gradle的依赖配置进行复制

然后复制到build.gradle中


  
    
    
  
  1. dependencies {

  2.     compile (

  3.             [group:'org.apache.thrift', name: 'libthrift', version: '0.13.0']

  4.     )

  5. }

因为设置了自动导入,所以会在项目中自动引入thrift相关的依赖

 

Thrift介绍以及Java中使用Thrift实现RPC示例

然后在src下新建thrift目录,在此目录下新建MyData.thrift文件


  
    
    
  
  1. namespace java thrift.generated

  2.  

  3. typedef i16 short

  4. typedef i32 int

  5. typedef i64 long

  6. typedef bool boolean

  7. typedef string String

  8.  

  9. struct Person {

  10.     1:optional String username,

  11.     2:optional int age,

  12.     3:optional boolean married

  13. }

  14.  

  15. exception DataException {

  16.     1:optional String message,

  17.     2:optional String callback,

  18.     3:optional String date

  19. }

  20.  

  21. service PersonService {

  22.     Person getPersonByUsername(1:required String username) throws (1:DataException dataException),

  23.     void savePerson(1:required Person person) throws(1:DataException dataException)

  24. }

然后在IDEA中新建Terminal

 thrift --gen java src/thrift/MyData.thrift

后面跟的目录就是thrift文件所在的路径

 

Thrift介绍以及Java中使用Thrift实现RPC示例

此时会在项目的根目录下生成代码,然后在src/main/java/com.badao下新建一个目录Thrift,然后将上面生成的代码复制到此路径下。

此时代码就已经生成好,

在此目录下新建PersonServiceImpl并实现生成的PersonService接口


  
    
    
  
  1. package com.badao.Thrift;

  2.  

  3. import org.apache.thrift.TException;

  4.  

  5. public class PersonServiceImpl implements PersonService.Iface {

  6.     @Override

  7.     public Person getPersonByUsername(String username) throws DataException, TException {

  8.         System.out.println("getPersonByUsername被调用并收到参数:" + username);

  9.         Person person = new Person();

  10.         person.setAge(100);

  11.         person.setMarried(true);

  12.  

  13.         return person;

  14.     }

  15.  

  16.     @Override

  17.     public void savePerson(Person person) throws DataException, TException {

  18.         System.out.println("savePerson方法被调用,接收到的参数为:");

  19.         System.out.println(person.getUsername());

  20.         System.out.println(person.getAge());

  21.         System.out.println(person.isMarried());

  22.     }

  23. }

并且实现其两个方法,在根据用户名获取Person实体的方法中

输出接收到的username参数并将一个Person对象返回。

在保存Person的方法中将接收到的Person对象进行输出。

然后在此目录下新建服务端类ThriftServer


  
    
    
  
  1. package com.badao.Thrift;

  2.  

  3. import org.apache.thrift.TProcessorFactory;

  4. import org.apache.thrift.protocol.TCompactProtocol;

  5. import org.apache.thrift.server.THsHaServer;

  6. import org.apache.thrift.server.TServer;

  7. import org.apache.thrift.transport.TFramedTransport;

  8. import org.apache.thrift.transport.TNonblockingServerSocket;

  9.  

  10.  

  11. public class ThriftServer {

  12.     public static void main(String[] args) throws Exception

  13.     {

  14.         //设置服务器端口  TNonblockingServerSocket-非堵塞服务模型

  15.         TNonblockingServerSocket serverSocket = new TNonblockingServerSocket(8899);

  16.         //参数设置

  17.         THsHaServer.Args arg = new THsHaServer.Args(serverSocket).minWorkerThreads(2).maxWorkerThreads(4);

  18.         //处理器

  19.         PersonService.Processor<PersonServiceImpl> processor = new PersonService.Processor<>(new PersonServiceImpl());

  20.         arg.protocolFactory(new TCompactProtocol.Factory());

  21.         arg.transportFactory(new TFramedTransport.Factory());

  22.         arg.processorFactory(new TProcessorFactory(processor));

  23.  

  24.         TServer server = new THsHaServer(arg);

  25.         System.out.println("Thrift 服务端启动成功");

  26.         server.serve();

  27.     }

  28.  

  29.  

  30. }

绑定端口并启动服务端。

然后在此路径下新建客户端ThriftClient


  
    
    
  
  1. package com.badao.Thrift;

  2.  

  3. import org.apache.thrift.protocol.TCompactProtocol;

  4. import org.apache.thrift.protocol.TProtocol;

  5. import org.apache.thrift.transport.TFramedTransport;

  6. import org.apache.thrift.transport.TSocket;

  7. import org.apache.thrift.transport.TTransport;

  8.  

  9. public class ThriftClient {

  10.     public static void main(String[] args) {

  11.         TTransport transport = new TFramedTransport(new TSocket("localhost", 8899), 600);

  12.         TProtocol protocol = new TCompactProtocol(transport);

  13.         PersonService.Client client = new PersonService.Client(protocol);

  14.  

  15.         try {

  16.             transport.open();

  17.  

  18.             System.out.println(person.getUsername());

  19.             System.out.println(person.getAge());

  20.             System.out.println(person.isMarried());

  21.  

  22.             System.out.println("------------------------");

  23.  

  24.             Person person1 = new Person();

  25.             person1.setAge(50);

  26.             person1.setMarried(true);

  27.  

  28.             client.savePerson(person1);

  29.  

  30.         }catch (Exception ex){

  31.             throw new RuntimeException(ex.getMessage(),ex);

  32.         }finally {

  33.             transport.close();

  34.         }

  35.     }

  36. }

与服务端建立连接并调用服务端的两个方法,然后运行服务端

 

Thrift介绍以及Java中使用Thrift实现RPC示例

然后再运行客户端

 

此时客户端已经调用getPersonByUsername并输出数据并且调用了服务端的savePerson方法

 

示例代码下载

https://download.csdn.net/download/BADAO_LIUMANG_QIZHI/12864856

博客原文:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108689413