thrift示例及性能测试
来源:互联网 发布:封闭式小区 知乎 编辑:程序博客网 时间:2024/05/21 22:01
1 简介
Thrift是一个跨语言的服务部署框架,最初由facebook开发用做系统内各语言之间的RPC(Remote Procedure Call Protocol,远程过程调用协议通信),2007年由facebook贡献到apache基金,08年5月进入apache孵化器。Thrift通过一个中间语言IDL(interface description language, 接口定义语言)来定义RPC的接口和数据类型,然后通过一个编译器生成不同语言的代码,并由生成的代码负责RPC协议层和传输层的实现。支持的语言有C++, Java, Python, PHP,Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml,Delphi等。
2 原理
2.1 架构
Thrift通过代码生成工具将接口定义文件生成服务器端和客户端代码(可以为不同语言),从而实现服务端和客户端跨语言的支持。用户在Thirft描述文件中声明自己的服务,这些服务经过编译后会生成相应语言的代码文件,然后用户实现服务(客户端调用服务,服务器端提服务)便可以了。其中protocol(协议层, 定义数据传输格式,可以为二进制或者XML等)和transport(传输层,定义数据传输方式,可以为TCP/IP传输,内存共享或者文件共享等)被用作运行时库。
2.2 基本概念
- Thrift中的几个概念
Server 服务模型
Handler 数据处理接口
Processor 数据处理对象
Protocol 数据传输协议
Transport 数据传输方式
- 支持的服务模型[Server]
TSimpleServer – 简单的单线程服务模型,常用于测试
TThreadPoolServer – 多线程服务模型,使用标准的阻塞式IO。
TNonblockingServer – 多线程服务模型,使用非阻塞式IO(需使用TFramedTransport数据传输方式)
- 支持的传输格式[Protocol]
TBinaryProtocol – 二进制格式
TCompactProtocol – 压缩格式
TJSONProtocol – JSON格式
TSimpleJSONProtocol –提供JSON只写协议, 生成的文件很容易通过脚本语言解析。
TDebugProtocol – 使用易懂的可读的文本格式,以便于debug
- 支持的通信方式(数据传输方式)[Transport]
TFileTransport:文件(日志)传输类,允许client将文件传给server,允许server将收到的数据写到文件中。
THttpTransport:采用Http传输协议进行数据传输
TSocket:采用TCPSocket进行数据传输
TZlibTransport:压缩后对数据进行传输,或者将收到的数据解压
3 简单示例
3.1 下载安装
登录官网下载(http://thrift.apache.org/),windows下载thrift-0.9.3.exe
放到某一路径下,例如:D:\ProgramFiles\thirft\thrift.exe(为了方便执行命令,将文件名改为thrift.exe)
环境变量Path值追加"D:\ProgramFiles\thirft"
打开cmd.exe,输入thrift –help,并回车可以看到帮助信息说明已安装成功
3.2 编写thrift文件,并编译
创建hello.thrift文件:
namespace java com.tongyin.thrift.demo
service HelloWorldService {
string sayHello(1:string username)
}
将文件放到某路径下,例:D:\dev\hello.thrift
打开cmd.exe,并执行thrift -r --gen java hello.thrift
在D:\dev\gen-java目录下编译生成了java文件,文件所在的包com.tongyin.thrift.demo是hello.thrift文件定义的namespace,
再将生成的文件拷贝到项目中
3.3 服务端代码
3.3.1 HelloWorldService编译生成的thrift服务类
拷贝编译生成的HelloWorldService.java到服务端项目
3.3.2 HelloWorldImpl服务实现类
package com.tongyin.thrift.demo;
import org.apache.thrift.TException;
/**
* 服务接口实现类
* @authorliulin
*
*/
public class HelloWorldImpl implements HelloWorldService.Iface {
@Override
public String sayHello(Stringusername)throws TException {
return"Hi, " +username ;
}
}
3.3.3 HelloServerDemo服务入口类
package com.tongyin.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.transport.TServerSocket;
/**
* thrift服务端
* @authorliulin
*
*/
public class HelloServerDemo {
//thrift服务端口号
public static final int SERVER_PORT = 7911;
public void startServer() {
try {
System.out.println("Thrift TThreadPoolServer start ....");
TProcessor tprocessor =new HelloWorldService.Processor<HelloWorldService.Iface>(
new HelloWorldImpl());
TServerSocket serverTransport =new TServerSocket(SERVER_PORT);
TThreadPoolServer.Args ttpsArgs = new TThreadPoolServer.Args(
serverTransport);
ttpsArgs.processor(tprocessor);
ttpsArgs.protocolFactory(new TBinaryProtocol.Factory());
// 线程池服务模型,使用标准的阻塞式IO,预先创建一组线程处理请求。
TServer server =new TThreadPoolServer(ttpsArgs);
server.serve();
} catch (Exceptione) {
System.out.println("Server start error!!!");
e.printStackTrace();
}
}
/**
* @param args
*/
public static void main(String[] args) {
HelloServerDemo server =new HelloServerDemo();
server.startServer();
}
}
3.4 客户端代码
3.4.1 HelloWorldService编译生成的thrift服务类
拷贝编译生成的HelloWorldService.java到客户端项目
3.4.2 HelloClientDemo客户入口类
package com.tongyin.thrift.demo;
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;
import org.apache.thrift.transport.TTransportException;
/**
* thrift客户端
* @authorliulin
*
*/
public class HelloClientDemo {
public static final String SERVER_IP ="localhost";
public static final int SERVER_PORT = 7911;
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);
// 协议要和服务端一致
TProtocol protocol =new TBinaryProtocol(transport);
HelloWorldService.Client client = new HelloWorldService.Client(
protocol);
transport.open();
String result =client.sayHello(userName);
System.out.println("Thrify client result = " +result);
} catch (TTransportExceptione) {
e.printStackTrace();
} catch (TExceptione) {
e.printStackTrace();
} finally {
if (null !=transport) {
transport.close();
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
HelloClientDemo client =new HelloClientDemo();
client.startClient("Linda");
}
}
3.5 启动项目
运行HelloServerDemo,启动服务
执行HelloClientDemo,客户端获得服务端返回的数据
4 性能测试
4.1 测试准备
我采用基于httpclient的方式,将thrift与spring进行了集成,具体代码不再列出,只列出与测试相关的信息。
4.1.1 user.thrift配置文件
namespace java com.tongyin.thrift.demo
struct User {
1: required string uid;#注释:用户id
2: optional string name;#注释:用户名
3: optional string mobile;#注释:用户手机号
4: optional string email;#注释:用户邮箱
5: optional i32 partyId;#注释:用户微信分组id,无用
6: optional i32 sysId;#注释:用户关心系统,系统id
}
service UserService {
list<User> getAllUser();
}
4.1.2 服务实现类
返回包含10000个实例的list
package com.tongyin.thrift.demo;
import java.util.ArrayList;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.thrift.TException;
import org.springframework.stereotype.Service;
@Service(value="userService")
public class UserServiceImpl implements UserService.Iface{
@Override
public List<User> getAllUser()throws TException {
intuserNum = 10000;
List<User> users = new ArrayList<User>();
User tempuser;
for(inti=1;i<=userNum;i++){
tempuser = new User();
tempuser.setUid(String.valueOf(i));
tempuser.setName("name"+i);
tempuser.setMobile("10086"+i);
tempuser.setPartyId(i/10);
tempuser.setSysId(1);
users.add(tempuser);
}
returnusers;
}
}
4.2 thrift测试结果
耗时(毫秒)
并发量=1
并发量=50
并发量=200
第1次
615
1671
3273
第2次
68
918
3025
第3次
29
948
2973
第4次
31
1020
2875
第5次
32
1062
2938
第6次
61
915
3031
第7次
31
1001
2910
第8次
29
941
2958
第9次
28
915
2892
第10次
27
962
2893
平均值
95.1
1035.3
2976.8
2-10次平均
37.33
964.67
2943.89
5 与CXF性能对比
WebService是常用的远程调用技术,也是一种RPC(Remote Procedure CallProtocol,远程过程调用协议通信),下面以Apache CXF为例,进行性能对比。
5.1 测试准备
5.1.1 VO
采用与thrift相同的字段
5.1.2 CXF服务实现类
与thrift相同,返回包含10000个实例的list
package com.tongyin.weixin.webservice;
import java.util.ArrayList;
import java.util.List;
import javax.jws.WebService;
import org.springframework.stereotype.Service;
import com.tongyin.weixin.vo.UserVo;
@WebService(serviceName="helloWs", endpointInterface="com.tongyin.weixin.webservice.ITestService")
@Service("testService")
public class TestService implements ITestService {
public List<UserVo> getAllUser(){
intuserNum = 10000;
List<UserVo> vos = new ArrayList<UserVo>();
UserVo tempvo;
for(inti=1;i<=userNum;i++){
tempvo = new UserVo();
tempvo.setUid(String.valueOf(i));
tempvo.setName("name"+i);
tempvo.setMobile("10086"+i);
tempvo.setPartyId(i/10);
tempvo.setSysId(1);
vos.add(tempvo);
}
returnvos;
}
}
5.2 对比结果
耗时(毫秒)
并发量=1
CXF并发量=50
CXF并发量=200
Thrift
CXF
Thrift
CXF
Thrift
CXF
第1次
615
885
1671
2506
3273
8504
第2次
68
128
918
2831
3025
6758
第3次
29
46
948
2119
2973
8564
第4次
31
57
1020
2028
2875
6701
第5次
32
60
1062
2289
2938
6788
第6次
61
47
915
2234
3031
7959
第7次
31
53
1001
2178
2910
7757
第8次
29
48
941
2248
2958
8099
第9次
28
44
915
2205
2892
7266
第10次
27
46
962
1874
2893
8580
平均值
95.1
141.4
1035.3
2251.2
2976.8
7697.6
2-10次平均
37.33
58.78
964.67
2222.89
2943.89
7608
l 初次调用时,Thrift和CXF都需要进行一些初始化操作,耗时较长。Thrift耗时615毫秒,CXF耗时885毫秒,CXF比Thrift要多耗时270毫秒,是Thrift耗时的1.44倍;
l 在第一次调用完毕后,随后的调用中,性能都明显提升。Thrift在2-10次耗时的平均值为37.33,CXF在2-10次耗时的平均值为58.78,CXF平均耗时要比Thrift多21.5毫秒,是Thrift的1.57倍;
l 当有50个并发请求时,Thrift耗时1035.3毫秒,CXF耗时2251.2毫秒,CXF比Thrift多耗时1215.9,是Thrift耗时的2.17倍。
l 当有200个并发请求时,Thrift耗时2976.8毫秒,CXF耗时7697.6毫秒,CXF比Thrift多耗时4720.8,是Thrift耗时的2.58倍。
5.3 总结
l 从以上对比结果来看,Thrift的性能比Apache CXF要好很多;
l Thrift支持的语言很多,可以很方便的进行跨语言远程调用,甚至可以直接与JavaScript进行交互;
l Thrift想要与Spring进行整合还需要编写很多代码,Apache CXF能够很容易的与spring进行整合;
l Thrift的相关资料比较少,开发难度大,Apache CXF有丰富的资料。
参考资料:
1. http://blog.sina.com.cn/s/blog_72995dcc0101gn82.html
2. http://blog.csdn.net/taizhenba/article/details/49149589
3. http://baike.baidu.com/link?url=Kn_cU65EdYIupMDdBiYn_zuopJXx_r0-zPAtvvh6jL0ts6UsSyAKXo_YYFpwNwoGvhCIB7CBxtwqrofyYjWzCK
- thrift示例及性能测试
- thrift 安装及示例
- thrift性能测试并分析
- ice-dubbo-thrift-grpc性能测试对比
- Java 7:最新特性、代码示例及性能测试
- boost条件变量使用示例及性能测试
- Java中条件变量使用示例及性能测试
- 示例:性能测试工具GpProfile
- jmeter性能测试使用示例
- LoadRunner接口性能测试示例
- 数据库性能测试方案示例
- jmeter性能测试使用示例
- LoadRunner接口性能测试示例
- 数据库性能测试方案示例
- 跨语言序列化-protobuf/thrift/avro性能测试
- 跨语言序列化-protobuf/thrift/avro性能测试
- g++编译thrift及root程序(Makefile示例)
- 再探Java 7:最新特性更新、代码示例及性能测试
- 程序员修炼的三层境界,你属于哪一层?
- 自学java 答答租车系统
- 控件包含代码块(即 <% ... %>),因此无法修改控件集合。
- 打印九九乘法表
- 使用Json数据进行服务器与android端交互
- thrift示例及性能测试
- UVA 11388 GCD LCM
- 安卓数据保存,保存到文件(转自安卓官方培训中文版)
- linux下查看tcp连接的几种方式
- nyoj 420(快速幂)
- 简单的抽屉效果
- Android开发之启动页面Splash Screen
- 什么是 Landing Page?
- 如何优化cocos2d程序的内存使用和程序大小:第一部分