设为首页 收藏本站
查看: 1655|回复: 0

[经验分享] thrift实现php调用C++接口

[复制链接]

尚未签到

发表于 2017-4-1 10:12:24 | 显示全部楼层 |阅读模式
一、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代码 DSC0000.gif   DSC0001.png DSC0002.gif





  • 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 )  
  • }  



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());  
  •         }  
  •     }  
  •   
  • }  



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!");  
  •     }  
  •   
  • }  



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();  
  • ?>  



<?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)  



#!/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));  



                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 为例)
DSC0003.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++   .....

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-358511-1-1.html 上篇帖子: php文件类型MIME对照表 下篇帖子: PHP MVC、模板引擎及权限设计
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表