php는 서버 측 개발을 위해 thrift를 사용합니다.
thrift는 인터페이스 설명 언어를 사용하여 서비스를 정의하고 생성하며 바이너리 형식을 사용하여 데이터를 전송합니다. 높은 동시성, 대용량 데이터 및 더 효율적입니다. 다국어 환경을 지원합니다.
아파치 Thrift란 무엇인가요?
Apache Thrift는 FaceBook에서 개발한 확장 가능한 언어 간 서비스 호출 프레임워크입니다. 간단히 말하면 구성 파일을 먼저 정의해야 합니다. 클라이언트가 어떤 언어를 사용하든 상관없이 다양한 언어에서 Thrift를 사용하여 자체 언어로 서버를 생성할 수 있습니다. 즉, Thrift 프로토콜을 기반으로 Java는 PHP를 호출할 수 있습니다. 현재 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml, Delphi 및 기타 언어 간 상호 호출을 지원합니다.
xml 및 json과 같은 기존 데이터 전송 방법과 비교하여 thrift는 인터페이스 설명 언어를 사용하여 서비스를 정의하고 생성하며 높은 동시성, 대용량 데이터 및 다중 언어를 위해 데이터를 더 작고 효율적으로 전송합니다. 환경이 더 잘 지원됩니다.
중고 설치 환경 요구 사항
g++ 4.2
boost 1.53.0
lex 및 yacc(flex 및 bison 기반)
lex 및 yacc가 설치되지 않았습니다. 먼저 설치하세요 , 그렇지 않으면 make가 실패하고 lex 및 yacc 명령을 찾을 수 없음 오류가 표시됩니다(일반 시스템은 제거된 것 같습니다. Ubuntu의 경우 apt-get install flex bision을 사용하십시오). Thrift thrift thrift thrift의 최신 버전의 중고품 :
wget http://www.apache.org/dyn/closer.cgi?path=/thrift/0.9.3/thrift-0.9.3.tar.gz tar xvf thrift-0.9.3.tar.gz cd thrift-0.9.3
2. 특정 언어를 비활성화하려면 TBinaryProtocol 프로토콜이 pack() 및 unpack() 함수를 시퀀스로 변환하려면
APC 확장을 설치해야 합니다. 왜냐하면 TSocketPool 클래스는 apc 캐시 작업에 apc_fetch() 및 apc_store() 함수를 사용하기 때문입니다.
php에서 thrift를 사용하는 경우 thrift/lib/php/lib의 기본 파일을 프로젝트 디렉터리에 복사하는 것 외에도 구성 파일에 따라 생성된 php 파일을 packages 폴더에 복사하고 이를 import해야 합니다. 나중에 프로젝트에서 자세히 논의할 것입니다.
클래스 라이브러리 설명은 다음을 포함하여 Thrift 유형의 전송 콘텐츠, 패키징 및 언패킹을 정의합니다.
TBinaryProtocol, 바이너리 형식, TBinaryProtocolAccelerated는 thrift_protocol에 따라 달라집니다. 포장 풀기.
데이터 전송 방법(전송)
은 다음을 포함하여 데이터 전송(쓰기) 및 수신(읽기) 방법을 정의합니다.
TBufferedTransport, 캐시된 전송, 작성된 데이터는 캐시가 새로 고쳐질 때까지 즉시 전송을 시작하지 않습니다.
TSocket, 소켓 전송 사용
TFramedTransport, 전송에 블록 모드 사용, 특정 전송 구현은 서버와 상호 작용하기 위해 컬을 사용하는 TSocket
TCurlClient와 같은 다른 전송 방법에 따라 다름
THttpClient, 스트림 모드를 사용하여 HTTP 서버와 상호 작용
TMemoryBuffer, 메모리 모드를 사용하여 데이터 교환
TPhpStream, 전송을 위해 PHP 표준 입력 및 출력 스트림 사용
TNullTransport, 데이터 전송 끄기
TSocketPool은 TSocket 지원 다중 서버 관리(APC 지원 필요)를 기반으로 하며 잘못된 서버를 자동으로 제거합니다
1. IDL(인터페이스 설명 언어) 인터페이스 설명 파일, 접미사 .thrift
thrift 유형: http://thrift.apache.org/docs/types
3. 액세스 코드
// 创建./configure文件 ./bootstrap.sh // 配置并安装 ./configure make // 检测是否有问题,如果机子没有安装python和java等可能会报错,不过本文主要讲php,安了php环境就行 make check make install
include "shared.thrift" namespace php tutorial typedef i32 MyInteger const i32 INT32CONSTANT = 9853 const map<string,string> 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() }
php server
namespace php shared struct SharedStruct { 1: i32 key 2: string value } service SharedService { SharedStruct getStruct(1: i32 key) }
<?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 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"; }
위 내용은 서버 측 개발을 위해 Thrift를 사용하는 PHP에 관한 것들의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!