Thrift的java和php數據交互

Thrift是一個軟件框架(遠程過程調用框架),用來進行可擴展且跨語言的服務的開發,封裝了數據傳輸格式(二進制、json)和網絡通訊的服務框架,提供多語言(C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml)的網絡服務器端和客戶端程序組件php

適用於搭建大型數據交換及存儲的通用工具,對於大型系統中的內部數據傳輸相對於JSON和xml不管在性能、傳輸大小上有明顯的優點。java

本文以註冊服務接口和登陸服務器接口爲教程,apache

Thrift開發的幾個概念:json

Server 服務模型api

Handler 數據處理接口服務器

Processor 數據處理對象網絡

Protocol 數據傳輸協議多線程

Transport 數據傳輸方式併發


(1)支持的傳輸格式框架

TBinaryProtocol – 二進制格式.

TCompactProtocol – 壓縮格式

TJSONProtocol – JSON格式

TSimpleJSONProtocol –提供JSON只寫協議, 生成的文件很容易經過腳本語言解析。

TDebugProtocol – 使用易懂的可讀的文本格式,以便於debug

 

(2) 支持的通訊方式(數據傳輸方式)(Transport)

TFileTransport:文件(日誌)傳輸類,容許client將文件傳給server,容許server將收到的數據寫到文件中。

THttpTransport:採用Http傳輸協議進行數據傳輸

TSocket:採用TCP Socket進行數據傳輸

TZlibTransport:壓縮後對數據進行傳輸,或者將收到的數據解壓

 

下面幾個類主要是對上面幾個類地裝飾(採用了裝飾模式),以提升傳輸效率。

TBufferedTransport:對某個Transport對象操做的數據進行buffer,即從buffer中讀取數據進行傳輸,或者將數據直接寫入buffer

TFramedTransport:以frame爲單位進行傳輸,非阻塞式服務中使用。同TBufferedTransport相似,也會對相關數據進行buffer,同時,它支持定長數據發送和接收。

TMemoryBuffer:從一個緩衝區中讀寫數據


(3)支持的服務模型

TSimpleServer – 簡單的單線程服務模型,經常使用於測試

TThreadedServer - 多線程服務模型,使用阻塞式IO,每一個請求建立一個線程。

TThreadPoolServer – 線程池服務模型,使用標準的阻塞式IO,預先建立一組線程處理請求。

TNonblockingServer – 多線程服務模型,使用非阻塞式IO(需使用TFramedTransport數據傳輸方式)

 

處理大量更新的話,主要是在TThreadedServer和TNonblockingServer中進行選擇。TNonblockingServer可以使用少許線程處理大量併發鏈接,可是延遲較高;TThreadedServer的延遲較低。實際中,TThreadedServer的吞吐量可能會比TNonblockingServer高,可是TThreadedServer的CPU佔用要比TNonblockingServer高不少。


服務端編寫的通常步驟:

1. 建立Handler

2. 基於Handler建立Processor

3. 建立Transport(通訊方式)

4. 建立Protocol方式(設定傳輸格式)

5. 基於Processor, Transport和Protocol建立Server

6. 運行Server

 

 

客戶端編寫的通常步驟:

1. 建立Transport

2. 建立Protocol方式

3. 基於Transport和Protocol建立Client

4. 運行Client的方法

上邊概述內容參考自:http://elf8848.iteye.com/blog/1960131

下面開始正式代碼教程

服務描述文件test.thrift,定義了login服務和register

/**
 * The first thing to know about are types. The available types in Thrift are:
 *
 *  bool        Boolean, one byte
 *  byte        Signed byte
 *  i16         Signed 16-bit integer
 *  i32         Signed 32-bit integer
 *  i64         Signed 64-bit integer
 *  double      64-bit floating point value
 *  string      String
 *  binary      Blob (byte array)
 *  map<t1,t2>  Map from one type to another
 *  list<t1>    Ordered list of one type
 *  set<t1>     Set of unique elements of one type
 *
 * Did you also notice that Thrift supports C style comments?
 */
namespace java com.penngo
namespace php com.penngo
struct User {
	1: i64 id,
	2: string name,
	3: string password
}

service LoginService{
    User login(1:string name, 2:string psw);
} 

service RegisterService{
    User createUser(1:string name, 2:string psw);
}

使用thrift生成對應平臺語言代碼

thrift -gen java test.thrift

thrift -gen php test.thrift

若是php須要生成服務器端,需求改成thrift -gen php:server test.thrift

java

實現LoginServiceImpl.java登陸接口業務

import org.apache.thrift.TException;
public class LoginServiceImpl implements LoginService.Iface{
	public LoginServiceImpl(){
	}
	public User login(String name, String psw) throws TException{
		User user = null;
		if(name.equals("penngo") && psw.equals("123")){
			user = new User();
			user.setId(1);
			user.setName("penngo");
		}
		return user;
	}
}

實現RegisterServiceImpl.java註冊接口業務

import org.apache.thrift.TException;
public class RegisterServiceImpl implements RegisterService.Iface{
	public RegisterServiceImpl(){
	}
	public User createUser(String name, String psw) throws TException{
		User user = new User();
		user.setId(2);
		user.setName(name);
		user.setPassword(psw);
		return user;
	}
}

服務器端java代碼

package com.penngo.main;

import org.apache.thrift.TMultiplexedProcessor;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TTransportException;
import com.penngo.LoginService;
import com.penngo.LoginServiceImpl;
import com.penngo.RegisterService;
import com.penngo.RegisterServiceImpl;

public class Server {
	private void start() {
		try {
			TServerSocket serverTransport = new TServerSocket(7911);
			// 用戶登陸
			LoginService.Processor loginProcessor = new LoginService.Processor(
					new LoginServiceImpl());
			// 用戶註冊
			RegisterService.Processor registerProcessor = new RegisterService.Processor(
					new RegisterServiceImpl());
			// Factory protFactory = new TBinaryProtocol.Factory(true, true);
			// TServer server = new TThreadPoolServer(new
			// TThreadPoolServer.Args(serverTransport)
			// .processor(loginProcessor));
			TMultiplexedProcessor processor = new TMultiplexedProcessor();
			processor.registerProcessor("LoginService", loginProcessor);
			processor.registerProcessor("RegisterService", registerProcessor);
			TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(
					serverTransport).processor(processor));
			System.out.println("Starting server on port 7911 ...");
			server.serve();
		} catch (TTransportException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String args[]) {
		Server srv = new Server();
		srv.start();
	}
}

客戶端java

package com.penngo.main;

import org.apache.thrift.*;
import org.apache.thrift.protocol.*;
import org.apache.thrift.transport.*;
import com.penngo.LoginService;
import com.penngo.RegisterService;
import com.penngo.User;

public class Client {
	public static void main(String[] args) {
		try {
			TTransport transport = new TSocket("localhost", 7911);
			TProtocol protocol = new TBinaryProtocol(transport);
			TMultiplexedProtocol mp1 = new TMultiplexedProtocol(protocol,
					"LoginService");
			// TProtocol protocol = new TBinaryProtocol(transport);
			// LoginService.Client client = new LoginService.Client(protocol);
			LoginService.Client loginClient = new LoginService.Client(mp1);
			TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol,
					"RegisterService");
			RegisterService.Client registerClient = new RegisterService.Client(
					mp2);
			transport.open();

			User user = loginClient.login("penngo", "123");
			if (user != null) {
				System.out.println("登陸成功:" + user.getId() + " "
						+ user.getName());
			} else {
				System.out.println("登陸失敗");
			}
			User user2 = registerClient.createUser("test", "123");
			if (user2 != null) {
				System.out.println("建立用戶成功:" + user2.getId() + " "
						+ user2.getName());
			} else {
				System.out.println("建立用戶失敗");
			}
			transport.close();
		} catch (TException x) {
			x.printStackTrace();
		}
	}
}

客戶端php

<?php
namespace com\penngo;

require_once __DIR__.'/../../lib/Thrift/ClassLoader/ThriftClassLoader.php';
//echo __DIR__.'/../../lib/Thrift/ClassLoader/ThriftClassLoader.php';
use Thrift\ClassLoader\ThriftClassLoader;

$GEN_DIR = realpath(dirname(__FILE__)).'/../../gen-php';

$loader = new ThriftClassLoader();
$loader->registerNamespace('Thrift', __DIR__ . '/../../lib');
//$loader->registerDefinition('shared', $GEN_DIR);
$loader->registerDefinition('com', $GEN_DIR);
$loader->register();

if (php_sapi_name() == 'cli') {
    ini_set("display_errors", "stderr");
}

use Thrift\Protocol\TBinaryProtocol;
use Thrift\Protocol\TMultiplexedProtocol;
use Thrift\Transport\TSocket;
use Thrift\Transport\THttpClient;
use Thrift\Transport\TBufferedTransport;
use Thrift\Exception\TException;
use com\penngo\RegisterServiceClient;
use com\penngo\LoginServiceClient;

try {
    if (array_search('--http', $argv)) {
        //$socket = new THttpClient('localhost', 8080, '/php/PhpServer.php');
    } else {
        $socket = new TSocket('localhost', 7911);
    }
    $transport = new TBufferedTransport($socket, 1024, 1024);
    $protocol = new TBinaryProtocol($transport);
    $loginProtocol = new TMultiplexedProtocol($protocol, "LoginService");
    $registerProtocol = new TMultiplexedProtocol($protocol, "RegisterService");
    $loginClient = new LoginServiceClient($loginProtocol);
    $registerClient = new RegisterServiceClient($registerProtocol);
    $transport->open();
    $user = $loginClient->login('penngo', '123');
    print "user===={$user->id} {$user->name} \n";
    
    $user = $registerClient->createUser('test', '123456');
    print "user===={$user->id} {$user->name} \n";
    $transport->close();
} catch (TException $tx) {
    print 'TException: '.$tx->getMessage()."\n";
    print 'TException: '.$tx->getTraceAsString()."\n";
}

?>
相關文章
相關標籤/搜索