Thrift入门及Java实例

一、概述

Thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 等等编程语言间无缝结合的、高效的服务。

Thrift最初由facebook开发,07年四月开放源码,08年5月进入apache孵化器。thrift允许你定义一个简单的定义文件中的数据类型和服务接口。以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨编程语言。【来自百度百科】

官网地址:thrift.apache.org


二、下载依赖(Maven)

1、在pom.xml 中添加如下内容:

<span style="white-space:pre">		</span><dependency>
			<groupId>org.apache.thrift</groupId>
			<artifactId>libthrift</artifactId>
			<version>0.9.3</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.12</version>
		</dependency>

三、基本概念以及实现步骤

几张图片说明thrift整个流程:

架构图:


服务端


客户端


部署图


注意:图片来源互联网

1、数据传输协议

TBinaryProtocol : 二进制格式.
TCompactProtocol : 压缩格式
TJSONProtocol : JSON格式
TSimpleJSONProtocol : 提供JSON只写协议, 生成的文件很容易通过脚本语言解析

注意: 客户端和服务端的协议要一致。

2、服务端

实现服务处理接口impl
创建TProcessor
创建TServerTransport
创建TProtocol
创建TServer
启动Server

3、客户端

创建Transport
创建TProtocol
基于TTransport和TProtocol创建 Client
调用Client的相应方法


四、实例

1、thrift文件创建,并在文件中定义需要的接口方法

namespace java com.jmust.thrift.demo

service  HelloWorldService {
  string sayHello(1:string username)
}

2、执行thrift-0.9.3.exe生成代码

thrift-0.9.3.exe -r -gen java ./demoHello.thrift
3、创建一个服务maven项目(shrift-service),将生成的 HelloWorldService.java文件复制到自己的项目中,利用maven打包成为bundle作为一个服务包,里面代码具体是什么样子的,我们不需要关心,到时候需要用到的地方,只需要把这个服务包引进去即可使用,下面看看我的pom.xml文件(把该开放出去的package开放出去,该引进来的package引进来)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.jmust.thrift</groupId>
	<artifactId>thrift-service</artifactId>
	<version>1.0.0</version>
	<packaging>jar</packaging>

	<name>thrift-service</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.thrift</groupId>
			<artifactId>libthrift</artifactId>
			<version>0.9.3</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.12</version>
		</dependency>
	</dependencies>
	
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.2</version>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
					<encoding>${project.build.sourceEncoding}</encoding>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<version>2.4.3</version>
				<executions>
					<execution>
						<phase>compile</phase>
					</execution>
				</executions>
				<configuration>
					<encoding>${project.build.sourceEncoding}</encoding>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-source-plugin</artifactId>
				<version>2.4</version>
				<executions>
					<execution>
						<phase>deploy</phase>
						<goals>
							<goal>jar</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-deploy-plugin</artifactId>
				<version>2.8.2</version>
				<configuration>
					<skip>false</skip>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-javadoc-plugin</artifactId>
				<version>2.10.3</version>
				<configuration>
					<aggregate>true</aggregate>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>2.7.2</version>
				<configuration>
					<skip>false</skip>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>cobertura-maven-plugin</artifactId>
				<version>2.7</version>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<version>2.3.1</version>
				<configuration>
					<archive>
						<manifest>
							<addClasspath>true</addClasspath>
							<classpathPrefix>lib/</classpathPrefix>
						</manifest>
						<manifestEntries>
							<Class-Path>.</Class-Path>
							<Built-By>JMUST</Built-By>
							<Bundle-ManifestVersion>2</Bundle-ManifestVersion>
							<Bundle-Name>${project.groupId}.${project.ArtifactId}</Bundle-Name>
							<Bundle-SymbolicName>${project.groupId}.${project.ArtifactId}</Bundle-SymbolicName>
							<Bundle-Version>${project.version}</Bundle-Version>
							<Bundle-Vendor>${project.groupId}</Bundle-Vendor>
							<Export-Package>com.jmust.thrift.service;version=${project.version}
							</Export-Package>
							<Import-Package>
								javax.annotation,org.slf4j,org.apache.thrift,org.apache.thrift.async,org.apache.thrift.scheme,org.apache.thrift.protocol,org.apache.thrift.server.AbstractNonblockingServer
							</Import-Package>
						</manifestEntries>
					</archive>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>


4、再创建一个实现以上服务maven项目(thrift-demo),pom.xml文件只需要引入

<span style="white-space:pre">		</span><dependency>
			<groupId>org.apache.thrift</groupId>
			<artifactId>libthrift</artifactId>
			<version>0.9.3</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.12</version>
		</dependency>
		<dependency>
			<groupId>com.jmust.thrift</groupId>
			<artifactId>thrift-service</artifactId>
			<version>1.0.0</version>
		</dependency>

4.1、实现接口Iface

package com.jmust.thrift.impl;

import org.apache.thrift.TException;

import com.jmust.thrift.service.HelloWorldService.Iface;

/**
 * 
 * @author LK
 *
 */
public class HelloWorldImpl implements Iface
{

	public HelloWorldImpl(){
		
	}
	
	public String sayHello(String username) throws TException {
		return "Hi," + username + " welcome to my blog www.jmust.com";
	}
   
}


5、根据协议去实现服务端

5.1、TSimpleServer服务端-----简单的单线程服务模型,一般用于测试

package com.jmust.thrift.demo;


import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TServer.Args;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;

import com.jmust.thrift.impl.HelloWorldImpl;
import com.jmust.thrift.service.HelloWorldService.Iface;
import com.jmust.thrift.service.HelloWorldService.Processor;

/**
 * 单线程服务模型,一般用于测试  TSimpleServer服务端
 * @author LK
 *
 */
public class HelloTSimpleServerDemo {

	public static final int SERVER_PORT = 8090;

	public void startServer() {
		try {
			System.out.println("HelloWorld TSimpleServer start ....");
 
			TProcessor tprocessor = new Processor<Iface>(
					new HelloWorldImpl());
			// 简单的单线程服务模型,一般用于测试  
			TServerSocket serverTransport = new TServerSocket(SERVER_PORT);
			Args tArgs = new Args(serverTransport);
			tArgs.processor(tprocessor);
			tArgs.protocolFactory(new TBinaryProtocol.Factory());
			TServer server = new TSimpleServer(tArgs);
			server.serve();
 
		} catch (Exception e) {
			System.out.println("Server start error!!!");
			e.printStackTrace();
		}
	}
 
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		HelloTSimpleServerDemo server = new HelloTSimpleServerDemo();
		server.startServer();
	}
}

5.2、TThreadPoolServer 服务模型 ------线程池服务模型, 使用标准的阻塞式IO,预先创建一组线程处理请求

package com.jmust.thrift.demo;


import org.apache.thrift.TProcessor;
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 com.jmust.thrift.impl.HelloWorldImpl;
import com.jmust.thrift.service.HelloWorldService.Iface;
import com.jmust.thrift.service.HelloWorldService.Processor;

/**
 * 线程池服务模型,使用标准的阻塞式IO,预先创建一组线程处理请求    TThreadPoolServer 服务模型
 * @author LK
 *
 */
public class HelloTThreadPoolServerDemo {

	public static final int SERVER_PORT = 8090;
	
	public void startServer() {
		try {
			System.out.println("HelloWorld TThreadPoolServer start ....");
 
			TProcessor tprocessor = new Processor<Iface>(
					new HelloWorldImpl());
			TServerSocket serverTransport = new TServerSocket(SERVER_PORT);
			//TThreadPoolServer 线程池服务模型
			Args ttpsArgs = new Args(
					 serverTransport);
			ttpsArgs.processor(tprocessor);
			ttpsArgs.protocolFactory(new TBinaryProtocol.Factory());
			//线程池服务模型,使用标准的阻塞式IO,预先创建一组线程处理请求。
			TServer server = new TThreadPoolServer(ttpsArgs);
			server.serve();
		} catch (Exception e) {
			System.out.println("Server start error!!!");
			e.printStackTrace();
		}
	}
 
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		HelloTThreadPoolServerDemo server = new HelloTThreadPoolServerDemo();
		server.startServer();
	}
}


5.3、TNonblockingServer 服务模型  -------使用 非阻塞式IO,服务端和客户端需要指定  TFramedTransport 数据传输的方式

package com.jmust.thrift.demo;


import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.server.TNonblockingServer;
import org.apache.thrift.server.TNonblockingServer.Args;
import org.apache.thrift.server.TServer;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TNonblockingServerSocket;

import com.jmust.thrift.impl.HelloWorldImpl;
import com.jmust.thrift.service.HelloWorldService.Iface;
import com.jmust.thrift.service.HelloWorldService.Processor;

/**
 * 使用非阻塞式IO,服务端和客户端需要指定 TFramedTransport 数据传输的方式    TNonblockingServer 服务模型
 * @author LK
 *
 */
public class HelloTNonblockingServerDemo {

	public static final int SERVER_PORT = 8090;
	public void startServer() {
		try {
			System.out.println("HelloWorld TNonblockingServer start ....");
 
			TProcessor tprocessor = new Processor<Iface>(
					new HelloWorldImpl());
			TNonblockingServerSocket tnbSocketTransport = new TNonblockingServerSocket(SERVER_PORT);
			Args tnbArgs = new Args(tnbSocketTransport);
			tnbArgs.processor(tprocessor);
			tnbArgs.transportFactory(new TFramedTransport.Factory());
			tnbArgs.protocolFactory(new TCompactProtocol.Factory());
			TServer server = new TNonblockingServer(tnbArgs);
			server.serve();
			
		} catch (Exception e) {
			System.out.println("Server start error!!!");
			e.printStackTrace();
		}
	}
 
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		HelloTNonblockingServerDemo server = new HelloTNonblockingServerDemo();
		server.startServer();
	}
}

5.4、THsHaServer服务模型  -------半同步半异步的服务端模型,需要指定为:  TFramedTransport 数据传输的方式

package com.jmust.thrift.demo;


import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.THsHaServer;
import org.apache.thrift.server.THsHaServer.Args;
import org.apache.thrift.server.TServer;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TNonblockingServerSocket;

import com.jmust.thrift.impl.HelloWorldImpl;
import com.jmust.thrift.service.HelloWorldService.Iface;
import com.jmust.thrift.service.HelloWorldService.Processor;

/**
 * 半同步半异步的服务端模型,需要指定为: TFramedTransport 数据传输的方式  THsHaServer服务模型
 * @author LK
 *
 */
public class HelloTHsHaServerDemo {

	public static final int SERVER_PORT = 8090;
	public void startServer() {
		try {
			System.out.println("HelloWorld THsHaServer start ....");
 
			TProcessor tprocessor = new Processor<Iface>(
					new HelloWorldImpl());
			TNonblockingServerSocket tnbSocketTransport = new TNonblockingServerSocket(SERVER_PORT);
			Args args = new Args(tnbSocketTransport);
			args.processor(tprocessor);
			args.transportFactory(new TFramedTransport.Factory());
			args.protocolFactory(new TBinaryProtocol.Factory());
			TServer server = new THsHaServer(args);
			server.serve();
			
		} catch (Exception e) {
			System.out.println("Server start error!!!");
			e.printStackTrace();
		}
	}
 
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		HelloTHsHaServerDemo server = new HelloTHsHaServerDemo();
		server.startServer();
	}
}

6、客户端实现

6.1、同步

package com.jmust.thrift.demo;

import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;

import com.jmust.thrift.service.HelloWorldService.Client;

/**
 * 
 * @author LK
 *
 */
public class HelloClientDemo {
	public static final String SERVER_IP = "localhost";
	public static final int SERVER_PORT = 8090;
	public static final int TIMEOUT = 30000;

	/**
	 *
	 * @param userName
	 */
	public void startClient(String userName) {
		TTransport transport = null;
		try {
			//transport = new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT);
			transport = new TFramedTransport(new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT));
			// 协议要和服务端一致
			TProtocol protocol = new TBinaryProtocol(transport);
			//TProtocol protocol = new TCompactProtocol(transport);
			// TProtocol protocol = new TJSONProtocol(transport);
			Client client = new Client(protocol);
			transport.open();
			String result = client.sayHello(userName);
			System.out.println("Thrify client result =: " + result);
		} catch (TTransportException e) {
			e.printStackTrace();
		} catch (TException e) {
			e.printStackTrace();
		} finally {
			if (null != transport) {
				transport.close();
			}
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		HelloClientDemo client = new HelloClientDemo();
		client.startClient("lvk");

	}
}

6.2、异步

package com.jmust.thrift.demo;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.apache.thrift.TException;
import org.apache.thrift.async.AsyncMethodCallback;
import org.apache.thrift.async.TAsyncClientManager;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocolFactory;
import org.apache.thrift.transport.TNonblockingSocket;
import org.apache.thrift.transport.TNonblockingTransport;

import com.jmust.thrift.service.HelloWorldService.AsyncClient;
import com.jmust.thrift.service.HelloWorldService.AsyncClient.sayHello_call;

/**
 * 异步客户端
 * @author LK
 *
 */
public class HelloAsynClientDemo {
	public static final String SERVER_IP = "localhost";
	public static final int SERVER_PORT = 8090;
	public static final int TIMEOUT = 30000;

	/**
	 *
	 * @param userName
	 */
	public void startClient(String userName) {
		try {
			TAsyncClientManager clientManager = new TAsyncClientManager();
			TNonblockingTransport transport = new TNonblockingSocket(SERVER_IP, SERVER_PORT, TIMEOUT);
			TProtocolFactory tprotocol = new TCompactProtocol.Factory();
			AsyncClient asyncClient = new AsyncClient(tprotocol, clientManager, transport);
			System.out.println("Client start .....");
		
			CountDownLatch latch = new CountDownLatch(1);
			AsynCallback callBack = new AsynCallback(latch);
			System.out.println("call method sayHello start ...");
			asyncClient.sayHello(userName, callBack);
			System.out.println("call method sayHello .... end");
			boolean wait = latch.await(30, TimeUnit.SECONDS);
			System.out.println("latch.await =:" + wait);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("startClient end.");
	}

	public class AsynCallback implements AsyncMethodCallback<sayHello_call>{
		private CountDownLatch latch;

		public AsynCallback(CountDownLatch latch) {
			this.latch = latch;
		}
		public void onComplete(sayHello_call response) {
			System.out.println("onComplete");
			try {
				// Thread.sleep(1000L * 1);
				System.out.println("AsynCall result =:"
						+ response.getResult().toString());
			} catch (TException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				latch.countDown();
			}
		}
		public void onError(Exception exception) {
			System.out.println("onError :" + exception.getMessage());
			latch.countDown();
		}
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		HelloAsynClientDemo client = new HelloAsynClientDemo();
		client.startClient("lvk");
	}
}

7.、测试步骤

先运行服务端,让后再运行客户端,看看是否输出预计结果。


完毕!

  • 8
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值