【转】Apache Thrift 学习 Apache Thrift 学习

Apache Thrift 学习

http://smallmin.iteye.com/blog/1121085

Apache Thrift 是跨语言服务访问的框架。最早由Facebook 开发,贡献给了Apache。
通过接口定义语言(IDL),定义和创建服务,Thrift生成特定语言的可供server和client 访问的代码。
Thrfit 有着非常优秀的效率,无论是内存还是 传输效率上。

Cassandra 支持多种语言的编程接口,正式由于使用了Thrift。

架构




以上是创建server和client的stack。最上面的是IDL,然后生成Client和Processor。红色的是发送的数据。protocol和transport 是Thrift运行库的一部分。
通过Thrift 你只需要关心服务的定义,而不需要关心protocol和transport。

Thrift允许你选择 protocol ,transport和server。因为Thrift 最早是有C++开发的,Thrift在C++实现中有最大的变化。

Thrift支持 text 和 binary protocols,binary protocols要比text protocols,但是有时候 text protocols比较有用(例如:调试的时候)。支持的协议有:
TBinaryProtocol  -直接的二进制格式
TCompactProtocol  效率和高压缩编码数据
TDenseProtocoal  和TCompactProtocol相似,但是省略了meta信息,从哪里发送的,增加了receiver。还在实验中,java实现还不可用。
TJSONProtocoal 使用JSON
TSImpleJSONProtocoal  只写的protocol使用JSON。适合被脚本语言转化
TDebugProtocoal  使用人类可读的text 格式 帮助调试

上面的protocol 说明了 什么被传送,Thrift  transports 说明了怎样传送。支持的transport:
TSocket  使用 blocking socket I/O
TFramedTransport   以帧的形式发送,每帧前面是一个长度。要求服务器来non-blocking server
TFileTransport   写到文件。没有包括在java实现中。
TMemoryTransport   使用内存 I/O 。java实现中在内部使用了ByteArrayOutputStream
TZlibTransport 压缩 使用zlib。在java实现中还不可用

最后,thrift 提供了servers:
TSimpleServer  单线程 server,使用标准的blocking IO。用于测试
TThreadPoolServer  多线程  使用标准的blocking IO
TNonblockingServer  多线程  使用 non-blocking IO (java实现中使用了NIO channels)。TFramedTransport必须使用在这个服务器。

一个server只允许定义一个接口服务。这样的话多个接口需要多个server。这样会带来资源的浪费。同意通过继承接口的方式。

创建服务 
1创建user.thrift

Java代码   收藏代码
  1. namespace java thrift.demo.gen  
  2. namespace py thrift.demo  
  3. struct User{  
  4.     1: i32 id,  
  5.     2: string username,  
  6.     3: string password  
  7. }  
  8.   
  9. exception UserNotFound{  
  10.     1:string message  
  11. }  
  12.   
  13. service UserService{  
  14.     list<User> getUsers(),  
  15.     User getUserByName(1:string username) throws(1:UserNotFound unf)  
  16. }  


定义了一个User ,一个UerNotFound异常,一个UserService服务接口

 

服务定义主要使用了 类C的语法

Types

Thrift 定义的类型

base type:bool,byte,i16,i32,i64,double,string(UTF-8 编码)

binary

structs

Contains:list<type>,set<type>,map<type>

exception

services:包含了一组接口方法

 

注意定义的时候 序号是不可省略的,使用序号可以提升序列化和反序列对象的速度。



2.生成代码
命令行下执行
生成java代码

Java代码   收藏代码
  1. thrift-0.6.1.exe --gen java  user.thrift  


生成python代码

Java代码   收藏代码
  1. thrift-0.6.1.exe --gen py user.thrift  


3.实现服务端
3.1接口服务实现

Java代码   收藏代码
  1. package thrift.demo.server;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import org.apache.thrift.TException;  
  7.   
  8. import thrift.demo.gen.User;  
  9. import thrift.demo.gen.UserNotFound;  
  10. import thrift.demo.gen.UserService.Iface;  
  11.   
  12. public class UserServiceHandler implements Iface {  
  13.   
  14.     @Override  
  15.     public List<User> getUsers() throws TException {  
  16.         List<User> list = new ArrayList<User>();  
  17.         User user = new User();  
  18.         user.setId(1);  
  19.         user.setUsername("user1");  
  20.         user.setPassword("pwd1");  
  21.         list.add(user);  
  22.         User user2 = new User();  
  23.         user2.setId(1);  
  24.         user2.setUsername("user2");  
  25.         user2.setPassword("pwd2");  
  26.         list.add(user2);  
  27.         return list;  
  28.     }  
  29.   
  30.     @Override  
  31.     public User getUserByName(String username) throws UserNotFound, TException {  
  32.         if ("user1".equals(username)) {  
  33.             User user = new User();  
  34.             user.setId(1);  
  35.             user.setUsername("user1");  
  36.             user.setPassword("pwd1");  
  37.             return user;  
  38.         } else {  
  39.             throw new UserNotFound();  
  40.         }  
  41.     }  
  42.   
  43. }  



3.2 Server启动类

Java代码   收藏代码
  1. package thrift.demo.server;  
  2.   
  3. import org.apache.thrift.TProcessorFactory;  
  4. import org.apache.thrift.protocol.TCompactProtocol;  
  5. import org.apache.thrift.server.THsHaServer;  
  6. import org.apache.thrift.server.TServer;  
  7. import org.apache.thrift.transport.TFramedTransport;  
  8. import org.apache.thrift.transport.TNonblockingServerSocket;  
  9. import org.apache.thrift.transport.TTransportException;  
  10.   
  11. import thrift.demo.gen.UserService;  
  12.   
  13. public class UserServer {  
  14.   
  15.     public final static int PORT = 8989;  
  16.     /** 
  17.      * @param args 
  18.      */  
  19.     public static void main(String[] args) {  
  20.         try {  
  21.             TNonblockingServerSocket socket = new TNonblockingServerSocket(PORT);  
  22.             final UserService.Processor processor = new UserService.Processor(  
  23.                     new UserServiceHandler());   
  24.             THsHaServer.Args arg = new THsHaServer.Args(socket);  
  25.             arg.protocolFactory(new TCompactProtocol.Factory());  
  26.             arg.transportFactory(new TFramedTransport.Factory());  
  27.             arg.processorFactory(new TProcessorFactory(processor));  
  28.             TServer server = new THsHaServer(arg);  
  29.             server.serve();  
  30.         } catch (TTransportException e) {  
  31.             e.printStackTrace();  
  32.         }  
  33.           
  34.   
  35.     }  
  36.   
  37. }  



4.实现客户端

Java代码   收藏代码
  1. package thrift.demo.client;  
  2.   
  3. import org.apache.thrift.TApplicationException;  
  4. import org.apache.thrift.TException;  
  5. import org.apache.thrift.protocol.TCompactProtocol;  
  6. import org.apache.thrift.protocol.TProtocol;  
  7. import org.apache.thrift.transport.TFramedTransport;  
  8. import org.apache.thrift.transport.TSocket;  
  9. import org.apache.thrift.transport.TTransport;  
  10. import org.apache.thrift.transport.TTransportException;  
  11.   
  12. import thrift.demo.gen.UserNotFound;  
  13. import thrift.demo.gen.UserService;  
  14.   
  15. public class UserClient {  
  16.     public static void main(String[] arsg) {  
  17.   
  18.         String address = "127.0.0.1";  
  19.         int port = 8989;  
  20.         int clientTimeout = 30000;  
  21.         TTransport transport = new TFramedTransport(new TSocket(address, port,  
  22.                 clientTimeout));  
  23.         TProtocol protocol = new TCompactProtocol(transport);  
  24.         UserService.Client client = new UserService.Client(protocol);  
  25.   
  26.         try {  
  27.             transport.open();  
  28.             System.out.println(client.getUserByName("user1"));  
  29.   
  30.         } catch (TApplicationException e) {  
  31.             System.out.println(e.getMessage() + " " + e.getType());  
  32.         } catch (TTransportException e) {  
  33.             e.printStackTrace();  
  34.         } catch (UserNotFound e) {  
  35.             e.printStackTrace();  
  36.         } catch (TException e) {  
  37.             e.printStackTrace();  
  38.         }  
  39.         transport.close();  
  40.     }  
  41. }  



注意 客户端和服务端要使用同一中 Protocol 和 Transport,否则会抛出异常

Apache Thrift 是跨语言服务访问的框架。最早由Facebook 开发,贡献给了Apache。
通过接口定义语言(IDL),定义和创建服务,Thrift生成特定语言的可供server和client 访问的代码。
Thrfit 有着非常优秀的效率,无论是内存还是 传输效率上。

Cassandra 支持多种语言的编程接口,正式由于使用了Thrift。

架构




以上是创建server和client的stack。最上面的是IDL,然后生成Client和Processor。红色的是发送的数据。protocol和transport 是Thrift运行库的一部分。
通过Thrift 你只需要关心服务的定义,而不需要关心protocol和transport。

Thrift允许你选择 protocol ,transport和server。因为Thrift 最早是有C++开发的,Thrift在C++实现中有最大的变化。

Thrift支持 text 和 binary protocols,binary protocols要比text protocols,但是有时候 text protocols比较有用(例如:调试的时候)。支持的协议有:
TBinaryProtocol  -直接的二进制格式
TCompactProtocol  效率和高压缩编码数据
TDenseProtocoal  和TCompactProtocol相似,但是省略了meta信息,从哪里发送的,增加了receiver。还在实验中,java实现还不可用。
TJSONProtocoal 使用JSON
TSImpleJSONProtocoal  只写的protocol使用JSON。适合被脚本语言转化
TDebugProtocoal  使用人类可读的text 格式 帮助调试

上面的protocol 说明了 什么被传送,Thrift  transports 说明了怎样传送。支持的transport:
TSocket  使用 blocking socket I/O
TFramedTransport   以帧的形式发送,每帧前面是一个长度。要求服务器来non-blocking server
TFileTransport   写到文件。没有包括在java实现中。
TMemoryTransport   使用内存 I/O 。java实现中在内部使用了ByteArrayOutputStream
TZlibTransport 压缩 使用zlib。在java实现中还不可用

最后,thrift 提供了servers:
TSimpleServer  单线程 server,使用标准的blocking IO。用于测试
TThreadPoolServer  多线程  使用标准的blocking IO
TNonblockingServer  多线程  使用 non-blocking IO (java实现中使用了NIO channels)。TFramedTransport必须使用在这个服务器。

一个server只允许定义一个接口服务。这样的话多个接口需要多个server。这样会带来资源的浪费。同意通过继承接口的方式。

创建服务 
1创建user.thrift

Java代码   收藏代码
  1. namespace java thrift.demo.gen  
  2. namespace py thrift.demo  
  3. struct User{  
  4.     1: i32 id,  
  5.     2: string username,  
  6.     3: string password  
  7. }  
  8.   
  9. exception UserNotFound{  
  10.     1:string message  
  11. }  
  12.   
  13. service UserService{  
  14.     list<User> getUsers(),  
  15.     User getUserByName(1:string username) throws(1:UserNotFound unf)  
  16. }  


定义了一个User ,一个UerNotFound异常,一个UserService服务接口

 

服务定义主要使用了 类C的语法

Types

Thrift 定义的类型

base type:bool,byte,i16,i32,i64,double,string(UTF-8 编码)

binary

structs

Contains:list<type>,set<type>,map<type>

exception

services:包含了一组接口方法

 

注意定义的时候 序号是不可省略的,使用序号可以提升序列化和反序列对象的速度。



2.生成代码
命令行下执行
生成java代码

Java代码   收藏代码
  1. thrift-0.6.1.exe --gen java  user.thrift  


生成python代码

Java代码   收藏代码
  1. thrift-0.6.1.exe --gen py user.thrift  


3.实现服务端
3.1接口服务实现

Java代码   收藏代码
  1. package thrift.demo.server;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import org.apache.thrift.TException;  
  7.   
  8. import thrift.demo.gen.User;  
  9. import thrift.demo.gen.UserNotFound;  
  10. import thrift.demo.gen.UserService.Iface;  
  11.   
  12. public class UserServiceHandler implements Iface {  
  13.   
  14.     @Override  
  15.     public List<User> getUsers() throws TException {  
  16.         List<User> list = new ArrayList<User>();  
  17.         User user = new User();  
  18.         user.setId(1);  
  19.         user.setUsername("user1");  
  20.         user.setPassword("pwd1");  
  21.         list.add(user);  
  22.         User user2 = new User();  
  23.         user2.setId(1);  
  24.         user2.setUsername("user2");  
  25.         user2.setPassword("pwd2");  
  26.         list.add(user2);  
  27.         return list;  
  28.     }  
  29.   
  30.     @Override  
  31.     public User getUserByName(String username) throws UserNotFound, TException {  
  32.         if ("user1".equals(username)) {  
  33.             User user = new User();  
  34.             user.setId(1);  
  35.             user.setUsername("user1");  
  36.             user.setPassword("pwd1");  
  37.             return user;  
  38.         } else {  
  39.             throw new UserNotFound();  
  40.         }  
  41.     }  
  42.   
  43. }  



3.2 Server启动类

Java代码   收藏代码
  1. package thrift.demo.server;  
  2.   
  3. import org.apache.thrift.TProcessorFactory;  
  4. import org.apache.thrift.protocol.TCompactProtocol;  
  5. import org.apache.thrift.server.THsHaServer;  
  6. import org.apache.thrift.server.TServer;  
  7. import org.apache.thrift.transport.TFramedTransport;  
  8. import org.apache.thrift.transport.TNonblockingServerSocket;  
  9. import org.apache.thrift.transport.TTransportException;  
  10.   
  11. import thrift.demo.gen.UserService;  
  12.   
  13. public class UserServer {  
  14.   
  15.     public final static int PORT = 8989;  
  16.     /** 
  17.      * @param args 
  18.      */  
  19.     public static void main(String[] args) {  
  20.         try {  
  21.             TNonblockingServerSocket socket = new TNonblockingServerSocket(PORT);  
  22.             final UserService.Processor processor = new UserService.Processor(  
  23.                     new UserServiceHandler());   
  24.             THsHaServer.Args arg = new THsHaServer.Args(socket);  
  25.             arg.protocolFactory(new TCompactProtocol.Factory());  
  26.             arg.transportFactory(new TFramedTransport.Factory());  
  27.             arg.processorFactory(new TProcessorFactory(processor));  
  28.             TServer server = new THsHaServer(arg);  
  29.             server.serve();  
  30.         } catch (TTransportException e) {  
  31.             e.printStackTrace();  
  32.         }  
  33.           
  34.   
  35.     }  
  36.   
  37. }  



4.实现客户端

Java代码   收藏代码
  1. package thrift.demo.client;  
  2.   
  3. import org.apache.thrift.TApplicationException;  
  4. import org.apache.thrift.TException;  
  5. import org.apache.thrift.protocol.TCompactProtocol;  
  6. import org.apache.thrift.protocol.TProtocol;  
  7. import org.apache.thrift.transport.TFramedTransport;  
  8. import org.apache.thrift.transport.TSocket;  
  9. import org.apache.thrift.transport.TTransport;  
  10. import org.apache.thrift.transport.TTransportException;  
  11.   
  12. import thrift.demo.gen.UserNotFound;  
  13. import thrift.demo.gen.UserService;  
  14.   
  15. public class UserClient {  
  16.     public static void main(String[] arsg) {  
  17.   
  18.         String address = "127.0.0.1";  
  19.         int port = 8989;  
  20.         int clientTimeout = 30000;  
  21.         TTransport transport = new TFramedTransport(new TSocket(address, port,  
  22.                 clientTimeout));  
  23.         TProtocol protocol = new TCompactProtocol(transport);  
  24.         UserService.Client client = new UserService.Client(protocol);  
  25.   
  26.         try {  
  27.             transport.open();  
  28.             System.out.println(client.getUserByName("user1"));  
  29.   
  30.         } catch (TApplicationException e) {  
  31.             System.out.println(e.getMessage() + " " + e.getType());  
  32.         } catch (TTransportException e) {  
  33.             e.printStackTrace();  
  34.         } catch (UserNotFound e) {  
  35.             e.printStackTrace();  
  36.         } catch (TException e) {  
  37.             e.printStackTrace();  
  38.         }  
  39.         transport.close();  
  40.     }  
  41. }  



注意 客户端和服务端要使用同一中 Protocol 和 Transport,否则会抛出异常

猜你喜欢

转载自wolfdream.iteye.com/blog/1210706