一、About thrift 二、什么是thrift,怎么工作? 三、Thrift IDL 四、Thrift Demo 五、Thrift 协议栈 以及各层的使用(java 为例) 六、与protocolbuffer的区别 一、About thrift
thrift是一种可伸缩的跨语言服务的发展软件框架。它结合了功能强大的软件堆栈的代码生成引擎,以建设服务,工作效率和无缝地与C + +,C#,Java,Python和PHP和Ruby结合。thrift是facebook开发的,我们现在把它作为开源软件使用。thrift允许你定义一个简单的定义文件中的数据类型和服务接口。以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨编程语言(来自百度百科)。
>>>最初由facebook开发用做系统内个语言之间的RPC通信 。
>>>2007年由facebook贡献到apache基金 ,现在是apache下的opensource之一 。
>>>支持多种语言之间的RPC方式的通信:php语言client可以构造一个对象,调用相应的服务方法来调用java语言的服务 ,跨越语言的C/S rpc 调用 。
二、什么是thrift,怎么工作?
java rmi的例子,代码见附件,建立一个java rmi的流程 :
>>>定义一个服务调用接口 。
>>>server端:接口实现---impl的实例---注册该服务实现(端口)---启动服务。
>>>client端:通过ip、端口、服务名,得到服务,通过接口来调用 。
>>>rmi数据传输方式:java对象序列化 。
Thrift 服务
>>>例同rmi ,需要定义通信接口、实现、注册服务、绑定端口……
>>>如何多种语言之间通信 ?
>>>数据传输走socket(多种语言均支持),数据再以特定的格式(String ),发送,接收方语言解析 。
Object ---> String ---> Object 。
问题:编码、解析完全需要自己做 ,复杂的数据结构会编码困难 .
Thrift 服务 :thrift的中间编码层
>>>java Object ---> Thrift Object ---> php Object
>>> 定义thrift的文件 ,由thrift文件(IDL)生成 双方语言的接口、model ,在生成的model以及接口中会有解码编码的代码 。
>>>thrift 文件例子
thrift-0.7.0.exe -r -gen java TestThrift.thrift 生成java 代码
thrift-0.7.0.exe -r -gen php TestThrift.thrift 生成php代码
thrift-0.7.0.exe -r -gen py TestThrift.thrift 生成python代码
thrift-0.7.0.exe -r -gen as3 TestThrift.thrift 生成as3代码
thrift-0.7.0.exe -r -gen cpp TestThrift.thrift 生成C++代码
三、Thrift IDL
http://www.cnblogs.com/tianhuilove/archive/2011/09/05/2167669.html
http://wiki.apache.org/thrift/
http://wiki.apache.org/thrift/ThriftTypes
四、Thrift Demo
Thrift IDL 文件
Java代码
namespace java com.gemantic.analyse.thrift.index struct NewsModel{
1:i32 id ;
2:string title;
3:string content;
4:string media_from;
5:string author; } service IndexNewsOperatorServices { bool indexNews(
1:NewsModel indexNews), bool deleteArtificiallyNews(
1:i32 id ) }
java server
Java代码
package com.gemantic.analyse.thrift.index;
import java.net.InetSocketAddress;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.server.TThreadPoolServer.Args;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;
import org.apache.thrift.transport.TTransportFactory;
public class ThriftServerTest {
public static void main(String[] args) { IndexNewsOperatorServices.Processor processor =
new IndexNewsOperatorServices.Processor(
new IndexNewsOperatorServicesImpl());
try{ TServerTransport serverTransport =
new TServerSocket(
new InetSocketAddress(
"0.0.0.0",
9813)); Args trArgs=
new Args(serverTransport); trArgs.processor(processor); trArgs.protocolFactory(
new TBinaryProtocol.Factory(
true,
true)); trArgs.transportFactory(
new TTransportFactory()); TServer server =
new TThreadPoolServer(trArgs); System.out.println(
"server begin ......................"); server.serve(); System.out.println(
"---------------------------------------"); server.stop(); }
catch(Exception e){
throw new RuntimeException(
"index thrift server start failed!!"+
"/n"+e.getMessage()); } } }
java client
Java代码
package com.gemantic.analyse.thrift.index;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
public class ThriftClientTest {
public static void main(String[] args)
throws TException { TTransport transport =
new TSocket(
"10.0.0.41",
9813);
long start=System.currentTimeMillis(); TProtocol protocol =
new TBinaryProtocol(transport); IndexNewsOperatorServices.Client client=
new IndexNewsOperatorServices.Client(protocol); transport.open(); client.deleteArtificiallyNews(
123456); NewsModel newsModel=
new NewsModel(); newsModel.setId(
789456); newsModel.setTitle(
"this from java client"); newsModel.setContent(
" 世界杯比赛前,由于塞尔维亚和黑山突然宣布分裂,国际足联开会决定剔除塞黑,由世界上球迷最多的国家顶替,名额恰巧来到中国。举国上下一片欢腾,中国足协决定由“成世铎”(成龙+阎世铎)组队,进军世界杯。"); newsModel.setAuthor(
"ddc"); newsModel.setMedia_from(
"新华08"); client.indexNews(newsModel); transport.close(); System.out.println((System.currentTimeMillis()-start)); System.out.println(
"client sucess!"); } }
php client
Php代码
<?php
$GLOBALS[
'THRIFT_ROOT'] =
'/home/tjiang/demo/thrift/lib/php/src';
require_once $GLOBALS[
'THRIFT_ROOT'].
'/Thrift.php';
require_once $GLOBALS[
'THRIFT_ROOT'].
'/protocol/TBinaryProtocol.php';
require_once $GLOBALS[
'THRIFT_ROOT'].
'/transport/TSocket.php';
require_once $GLOBALS[
'THRIFT_ROOT'].
'/transport/THttpClient.php';
require_once $GLOBALS[
'THRIFT_ROOT'].
'/transport/TBufferedTransport.php';
include_once $GLOBALS[
'THRIFT_ROOT'].
'/packages/TestThrift/TestThrift_types.php';
include_once $GLOBALS[
'THRIFT_ROOT'].
'/packages/TestThrift/IndexNewsOperatorServices.php';
$data=
array(
'id'=>
'1',
'title'=>
'demo-标题',
'content'=>
'demo-内容',
'media_from'=>
'hexun',
'author'=>
'xiaodi667' );
$thrif_server_url =
'10.0.0.41';
$transport =
new TSocket(
$thrif_server_url, 9813);
$transport->open();
$protocol =
new TBinaryProtocol(
$transport);
$client=
new IndexNewsOperatorServicesClient(
$protocol,
$protocol);
$obj =
new NewsModel(
$data);
$result =
$client->indexNews(
$obj);
$transport->close(); ?>
python client
Python代码
import sys
from TestThrift.ttypes
import NewsModel
from TestThrift.IndexNewsOperatorServices
import Client
from thrift
import Thrift
from thrift.transport
import TSocket
from thrift.transport
import TTransport
from thrift.protocol
import TBinaryProtocol
try: transport = TSocket.TSocket(
'10.0.0.41',
9813) transport = TTransport.TBufferedTransport(transport) protocol = TBinaryProtocol.TBinaryProtocol(transport) client = Client(protocol) transport.open() client.deleteArtificiallyNews(
123) newsModel=NewsModel() newsModel.id=
123456 newsModel.title=
"python Test" newsModel.content=
"client test come from python"; newsModel.media_from=
"xinhua08" client.indexNews(newsModel) transport.close()
except Thrift.TException, tx:
print '%s' % (tx.message)
Csharp client
C#代码
TTransport transport =
new TSocket(
"10.0.0.41", 9813); TProtocol protocol =
new TBinaryProtocol(transport); IndexNewsOperatorServices.Client client =
new IndexNewsOperatorServices.Client(protocol); transport.Open(); NewsModel model =
new NewsModel(); model.Author =
"jww"; model.Title =
"title"; model.Content =
"client Come From CSharp"; model.Id = 1; client.deleteArtificiallyNews(123); Console.WriteLine(client.indexNews(model));
五、Thrift 协议栈 以及各层的使用(java 为例)
1、model interface
服务的调用接口以及接口参数model、返回值model
2、Tprotocol 协议层
将数据(model)编码 、解码 。
3、Ttramsport 传输层
编码后的数据传输(简单socket、http)
5、Tserver
服务的Tserver类型,实现了几种rpc调用(单线程、多线程、非阻塞IO)
六、与protocolbuffer的区别
http://liuchangit.com/development/346.html
http://stackoverflow.com/questions/69316/biggest-differences-of-thrift-vs-protocol-buffers
区别:
1、Another important difference are the languages supported by default. protobuf: Java, C++, Python Thrift: Java, C++, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, Ocaml
支持语言不同,thrift支持着更多的语言 。
2、Thrift supports ‘exceptions 。
thrift支持服务的异常 。
3、Protocol Buffers much easier to read 。Protobuf API looks cleaner, though the generated classes are all packed as an inner classes which is not so nice.
Protocol Buffers 在文档方面比thrift丰富,而且比thrift简单 。
4、Protobuf serialized objects are about 30% smaller then Thrift.
Protocol Buffers在序列化/反序列化、传输上性能更优 。
5、RPC is another key difference. Thrift generates code to implement RPC clients and servers wheres Protocol Buffers seems mostly designed as a data-interchange format alone.
thrift提供了一套完整的rpc服务实现(多线程socket、非阻塞的socket....)
6、And according to the wiki the Thrift runtime doesn't run on Windows.
thrift 对有些语言在windows上不支持:C++ .....
相关资源:intellij thrift插件