thrift使用介紹

原文出處:http://gemantic.iteye.com/blog/1199214

一、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 {  
  
    /** 
     * @param args 
     */  
    public static void main(String[] args) {  
        // TODO Auto-generated method stub  
        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));  
            //使用普通的socket來傳輸數據  
            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 {  
  
    /** 
     * @param args 
     * @throws TException  
     */  
    public static void main(String[] args) throws TException {  
        // TODO Auto-generated method stub  
        TTransport transport = new TSocket("10.0.0.41", 9813);  
        long start=System.currentTimeMillis();  
//      TTransport transport = new TSocket("218.11.178.110",9090);  
        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代碼  

#!/usr/bin/env python  
  
#  
# Licensed to the Apache Software Foundation (ASF) under one  
# or more contributor license agreements. See the NOTICE file  
# distributed with this work for additional information  
# regarding copyright ownership. The ASF licenses this file  
# to you under the Apache License, Version 2.0 (the  
# "License"); you may not use this file except in compliance  
# with the License. You may obtain a copy of the License at  
#  
#   http://www.apache.org/licenses/LICENSE-2.0  
#  
# Unless required by applicable law or agreed to in writing,  
# software distributed under the License is distributed on an  
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY  
# KIND, either express or implied. See the License for the  
# specific language governing permissions and limitations  
# under the License.  
#  
  
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:  
  
  # Make socket  
  transport = TSocket.TSocket('10.0.0.41', 9813)  
  
  # Buffering is critical. Raw sockets are very slow  
  transport = TTransport.TBufferedTransport(transport)  
  
  # Wrap in a protocol  
  protocol = TBinaryProtocol.TBinaryProtocol(transport)  
  
  # Create a client to use the protocol encoder  
  client = Client(protocol)  
  
  # Connect!  
  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)  
    
  #close  
  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 爲例) 
4e271cc2-1589-3480-b556-3067ea04479e.png 
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++   ..... 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章