java服务端开发 php_PHP使用thrift做服务端开发
php中文网最新课程
每日17点准时技术干货分享
php使用thrift做服务端开发
thrift采用接口描述语言定义和创建服务,用二进制格式传输数据,体积更小、效率更高,对于高并发、数据量大和多语言的环境有更好的支持。
Apache Thrift是啥?
Apache Thrift是FaceBook开发的一套可扩展的、跨语言的服务调用框架。简单的说就是先定义一个配置文件,不同的语言可以利用thrift基于这个配置文件生成各自语言的服务端,不管客户端用什么语言,都可以调用,也就是说基于thrift协议用java可以调用php的服务。目前支持C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi等语言之间相互调用。
相对于传统的xml和json等数据传输方式来说,thrift采用接口描述语言定义和创建服务,用二进制格式传输数据,体积更小、效率更高,对于高并发、数据量大和多语言的环境有更好的支持。
thrift安装环境要求
g++ 4.2
boost 1.53.0
lex and yacc(基于flex和bison)
如果没安装lex和yacc的话要先安装,否则会make失败,提示lex和yacc command not found错误(一般的机器貌似都没安,Ubuntu用apt-get install flex bision即可)。
安装thrift
1.下载最新版thrift:
wget http://www.apache.org/dyn/closer.cgi?path=/thrift/0.9.3/thrift-0.9.3.tar.gztar xvf thrift-0.9.3.tar.gzcd thrift-0.9.3
2.创建configure文件
// 创建./configure文件./bootstrap.sh// 配置并安装./configuremake// 检测是否有问题,如果机子没有安装python和java等可能会报错,不过本文主要讲php,安了php环境就行make checkmake install
编译选项
使用./configure --help可以查看选项
如果想禁用某个语言,可以用./configure --without-java
thrift for php安装环境要求
php版本>5.0,因为TBinaryProtocol协议用到了pack()和unpack()函数来序列化数据
需要安装APC扩展,因为TSocketPool这个类用到了apc_fetch()和apc_store()函数进行apc缓存操作。
php使用thrift的时候,除了要将thrift/lib/php/lib里的基础文件copy到项目目录下,还需要将根据配置文件生成的php文件也copy到packages文件夹下,并引入到项目中,这个后续会详细讲。
类库说明
数据传输格式(protocol)
定义的了传输内容,对Thrift Type的打包解包,包括:
TBinaryProtocol,二进制格式,TBinaryProtocolAccelerated则是依赖于thrift_protocol扩展的快速打包解包。
TCompactProtocol,压缩格式
TJSONProtocol,JSON格式
TMultiplexedProtocol,利用前三种数据格式与支持多路复用协议的服务端(同时提供多个服务,TMultiplexedProcessor)交互
数据传输方式(transport)
定义了如何发送(write)和接收(read)数据,包括:
TBufferedTransport,缓存传输,写入数据并不立即开始传输,直到刷新缓存。
TSocket,使用socket传输
TFramedTransport,采用分块方式进行传输,具体传输实现依赖其他传输方式,比如TSocket
TCurlClient,使用curl与服务端交互
THttpClient,采用stream方式与HTTP服务端交互
TMemoryBuffer,使用内存方式交换数据
TPhpStream,使用PHP标准输入输出流进行传输
TNullTransport,关闭数据传输
TSocketPool在TSocket基础支持多个服务端管理(需要APC支持),自动剔除无效的服务器
开发流程
1、定义IDL(Interface description language)接口描述文件,后缀.thrift
IDL规范:http://thrift.apache.org/docs/idl
thrift types:http://thrift.apache.org/docs/types
2、服务端代码开发
3、客户端编写接入代码
IDL:
1.tutorial.thrift
include "shared.thrift"namespace php tutorialtypedef i32 MyIntegerconst i32 INT32CONSTANT = 9853const map MAPCONSTANT = {'hello':'world', 'goodnight':'moon'}enum Operation { ADD = 1, SUBTRACT = 2, MULTIPLY = 3, DIVIDE = 4}struct Work { 1: i32 num1 = 0, 2: i32 num2, 3: Operation op, 4: optional string comment,}exception InvalidOperation { 1: i32 whatOp, 2: string why}service Calculator extends shared.SharedService { void ping(), i32 add(1:i32 num1, 2:i32 num2), i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch), oneway void zip()}
2.shared.thrift
namespace php sharedstruct SharedStruct { 1: i32 key 2: string value}service SharedService { SharedStruct getStruct(1: i32 key)}
php服务端
<?php namespace tutorial\php;ini_set('display_errors',1);error_reporting(E_ALL);// 引入类自动加载文件require_once __DIR__.'/../../lib/php/lib/Thrift/ClassLoader/ThriftClassLoader.php';// 载入自动加载类use Thrift\ClassLoader\ThriftClassLoader;// 定义根据.thrift文件生成的php文件$GEN_DIR = realpath(dirname(__FILE__).'/..').'/gen-php';// 注册thrift服务$loader = new ThriftClassLoader();$loader->registerNamespace('Thrift', __DIR__ . '/../../lib/php/lib');$loader->registerDefinition('shared', $GEN_DIR);$loader->registerDefinition('tutorial', $GEN_DIR);$loader->register();if (php_sapi_name() == 'cli') { ini_set("display_errors", "stderr");}use Thrift\Protocol\TBinaryProtocol; // 二进制格式打包解包use Thrift\Transport\TPhpStream; // php流输入输出use Thrift\Transport\TBufferedTransport; // 使用缓存// 开始服务端逻辑class CalculatorHandler implements \tutorial\CalculatorIf { protected $log = array(); public function ping() { error_log("ping()"); } // 相加 public function add($num1, $num2) { error_log("add({$num1}, {$num2})"); return $num1 + $num2; } // 枚举计算类型 public function calculate($logid, \tutorial\Work $w) { error_log("calculate({$logid}, {{$w->op}, {$w->num1}, {$w->num2}})"); switch ($w->op) { case \tutorial\Operation::ADD: $val = $w->num1 + $w->num2; break; case \tutorial\Operation::SUBTRACT: $val = $w->num1 - $w->num2; break; case \tutorial\Operation::MULTIPLY: $val = $w->num1 * $w->num2; break; case \tutorial\Operation::DIVIDE: if ($w->num2 == 0) { $io = new \tutorial\InvalidOperation(); $io->whatOp = $w->op; $io->why = "Cannot divide by 0"; throw $io; } $val = $w->num1 / $w->num2; break; default: $io = new \tutorial\InvalidOperation(); $io->whatOp = $w->op; $io->why = "Invalid Operation"; throw $io; } $log = new \shared\SharedStruct(); $log->key = $logid; $log->value = (string)$val; $this->log[$logid] = $log; return $val; } public function getStruct($key) { error_log("getStruct({$key})"); // This actually doesn't work because the PHP interpreter is // restarted for every request. //return $this->log[$key]; return new \shared\SharedStruct(array("key" => $key, "value" => "PHP is stateless!")); } public function zip() { error_log("zip()"); }};header('Content-Type', 'application/x-thrift');if (php_sapi_name() == 'cli') { echo "\r\n";}$handler = new CalculatorHandler();$processor = new \tutorial\CalculatorProcessor($handler);// 客户端和服务端在同一个输入输出流上//1) cli 方式:php Client.php | php Server.php //2) cgi 方式:利用Apache或nginx监听http请求,调用php-fpm处理,将请求转换为PHP标准输入输出流$transport = new TBufferedTransport(new TPhpStream(TPhpStream::MODE_R | TPhpStream::MODE_W));$protocol = new TBinaryProtocol($transport, true, true);$transport->open();$processor->process($protocol, $protocol);$transport->close();//作为cli方式运行,非阻塞方式监听,基于libevent实现,非官方实现//$transportFactory = new TBufferedTransportFactory();//$protocolFactory = new TBinaryProtocolFactory(true, true);//$transport = new TNonblockingServerSocket('localhost', 9090);//$server = new TNonblockingServer($processor, $transport, $transportFactory, $transportFactory, $protocolFactory, $protocolFactory);//$server->serve();//作为cli方式运行,监听端口,官方实现//$transportFactory = new TBufferedTransportFactory();//$protocolFactory = new TBinaryProtocolFactory(true, true);//$transport = new TServerSocket('localhost', 9090);//$server = new TSimpleServer($processor, $transport, $transportFactory, $transportFactory, $protocolFactory, $protocolFactory);//$server->serve();
php客户端
<?php namespace tutorial\php;error_reporting(E_ALL);require_once __DIR__.'/../../lib/php/lib/Thrift/ClassLoader/ThriftClassLoader.php';use Thrift\ClassLoader\ThriftClassLoader;$GEN_DIR = realpath(dirname(__FILE__).'/..').'/gen-php';$loader = new ThriftClassLoader();$loader->registerNamespace('Thrift', __DIR__ . '/../../lib/php/lib');$loader->registerDefinition('shared', $GEN_DIR);$loader->registerDefinition('tutorial', $GEN_DIR);$loader->register();use Thrift\Protocol\TBinaryProtocol;use Thrift\Transport\TSocket;use Thrift\Transport\THttpClient;use Thrift\Transport\TBufferedTransport;use Thrift\Exception\TException;// 以上配置跟服务端类似try { if (array_search('--http', $argv)) { // 使用http方式连接 $socket = new THttpClient('localhost', 8080, '/php/PhpServer.php'); } else { // 使用socket连接 $socket = new TSocket('localhost', 9090); } $transport = new TBufferedTransport($socket, 1024, 1024); $protocol = new TBinaryProtocol($transport); $client = new \tutorial\CalculatorClient($protocol); $transport->open(); $client->ping(); print "ping()\n"; $sum = $client->add(1,1); print "1+1=$sum\n"; // 调试异常情况 $work = new \tutorial\Work(); $work->op = \tutorial\Operation::DIVIDE; $work->num1 = 1; $work->num2 = 0; try { $client->calculate(1, $work); print "Whoa! We can divide by zero?\n"; } catch (\tutorial\InvalidOperation $io) { print "InvalidOperation: $io->why\n"; } $work->op = \tutorial\Operation::SUBTRACT; $work->num1 = 15; $work->num2 = 10; $diff = $client->calculate(1, $work); print "15-10=$diff\n"; $log = $client->getStruct(1); print "Log: $log->value\n"; $transport->close();} catch (TException $tx) { print 'TException: '.$tx->getMessage()."\n";}
输出:
// php client.php --httpping()1+1=2InvalidOperation: Cannot divide by 015-10=5Log: PHP is stateless!
▼
java服务端开发 php_PHP使用thrift做服务端开发相关推荐
- 做B端产品经理好还是做C端产品经理好?
做B端产品经理好还是做C端产品经理好?这个问题也是一些小白和刚转行进入产品经理的新人的一个疑问,做哪种产品经理好.本文从三个层面为大家进行剖析. B端产品经理 1.定义层面:B端产品经理和C端产品经理 ...
- 本文写给广大正在做软件开发的、曾经做过软件开发的以及即将做软件开发的女同胞们。同时也希望男同胞们能够给女同胞多一些理解和包容,多一些关心和帮助,让女同胞能在软件开发的路上走的更远一点,走的更好一
本文写给广大正在做软件开发的.曾经做过软件开发的以及即将做软件开发的女同胞们.同时也希望男同胞们能够给女同胞多一些理解和包容,多一些关心和帮助,让女同胞能在软件开发的路上走的更远一点,走的更好一些. ...
- 前端开发怎么用php,做web前端开发怎么样?
前端工程师是互联网时代软件产品研发中不可缺少的一种专业研发角色.从狭义上讲,前端工程师使用 HTML.CSS.JavaScript 等专业技能和工具将产品UI设计稿实现成网站产品,涵盖用户PC端.移动 ...
- Web测试要点 做移动端的测试,也做web端的测试,甚至后面桌面端的测试和后台的测试也做了,基本上把我们产品各个端都玩了一轮...
Web测试要点 一.功能测试 1.链接测试 (1).测试所有链接是否按指示的那样确实链接到了该链接的页面: (2).测试所链接的页面是否存在: (3).保证Web应用系统上没有孤立的页面(所谓 ...
- 看看高手做的ARM开发板
放假前,我写了一篇文章,里面有提到我放假的时候会接触一个开发板,这个开发板就是标题提到的这个ARM处理器,这篇文章会对这个处理器和开发板做个简单的介绍. 说这个开发板前,先介绍下我的一个朋友zzy. ...
- java开发的微信公众号服务端生产环境中的两个大坑
摘要: 我们开发的公众号,由于将功能开发完毕后,未对服务进行压力测试,因此用到的组件中的参数值全是默认的,服务上线后一段时间运行得倒没什么问题,随着服务得访问量增加,一些多线程并发的问题就逐步暴露出来 ...
- java sslsocket程序_JAVA与C++进行sslsocket通信,JAVA做服务端或客户端
前几天有位网友问我关于Unity3D里面使用Protobuf的方法,一时有事拖到现在才写这篇文章,不好意思哈. 本文测试环境: 系统:WINDOWS 7(第3.6步).OS X 10.9(第4步) 软 ...
- 我问你这篇保熟不?! -- 做服务端开发,不懂网络层,真的可以吗?
文章目录 唠嗑两句·网络层 网络层简介 网际协议IP 常见的三类IP地址 A类 B类.C类 IP地址与硬件地址 地址解析协议ARP IP层转发分组 子网划分 子网划分的背景意义 什么是子网划分? 子网 ...
- python mobile-hi.codemao.cn_使用thrift做c++,java和python的相互调用
linux上安装thrift见 http://jinghong.iteye.com/blog/1102535 thrift做为跨语言调用的方案有高效,支持语言较多,成熟等优点:代码侵入较强是其弱点. ...
最新文章
- NSLog不打印设置
- (转)Symbian启动J2ME程序
- php的cookie的函数,php setcookie()函数的使用简介
- oracle中minus
- 怎么把word里面虚线变成实线_弱电不会制作cad图,花3分钟看完,只要会用WORD保证你能画出来...
- UVa 11044 - Searching for Nessy
- 欧盟无线产品RED认证
- codeblocks13.12汉化
- 如何使用pyodbc
- 传奇攻城期间禁止玩家下地图打怪的脚本写法
- macbook卡在进度条开不了机_Mac 开机停在进度条解决方法
- mysql latch_MySQL中的latch(闩锁)详解——易产生的问题以及原因分析
- LPC解算的burg算法
- 抖音矩阵系统。抖音矩阵系统。抖音矩阵系统。抖音矩阵系统。抖音矩阵系统。
- 【应用多元统计分析】——第三章(1)
- GO+ 教程总览(二)
- Android实现手机静音
- vivado设计之解读复杂性报告(Complexity Characteristics)
- 大班科学计算机的发明应用教案,大班科学教案:《中国古代四大发明》
- Python:Flask自动刷新页面livereload
热门文章
- 一个Portal处理流程
- 前端每日实战:60# 视频演示如何用纯 CSS 创作一块乐高积木
- 第二章:SpringBoot与JSP间不可描述的秘密
- linux正则表达式BRE
- ubuntu14.04配置java jdk
- xCode自定义快捷键
- java整理软件--- Java OCR 图像智能字符识别技术,可识别中文,但是验证码不可以识别...已测识别中文效果很好...
- IT巨擎为何迷失互联网大潮
- python paramiko模块 远程上传目录文件
- java 反序列化 ysoserial exploit/JRMPClient 原理剖析