5月底的业余时间试用了一下thrift,效果不错,今天在博客小记一下。
thrift主要是用来进行跨语言层的rpc服务框架,基本原理是通过.thrift 文件以及dsl来生成相应的语言代码,目前支持的语言:c++,c#,java,php,服务器与客户端连接使用tcp/ip,数据协议支持二进制,json等。
我实验的平台是c#语言做客户端,java做服务端。
因为thrift是基于代码生成,所以首先要来编写用于代码生成的.thrift ,对于客户端和服务端而言,.thrift 只需要编写一次即可,通过thrift 的生成程序 可以分别生成用于客户端的c#以及服务端的java。(我这里用c#做客户端,java做服务端).
thrift 支持常见的数据类型如下:
1.基本类型(对应java类型)
bool 对应 boolean
byte 对应 byte 8位
i16 对应 short 16位
i32 对应 int 32位
i64 对应 long 64位
double 对应 double64位
string 对应 String utf-8
2.特殊类型 :
binary 对应 ByteBuffer
3.Structs(结构):
注意每个field前面需要加入序号,语句结尾要加","。
struct test{
1:i32 id,
2:string name,
}
4.容器类型:
list<t> 对应 List<t>
map<t1,t2> 对应 Map<t1,t2>
set<t> 对应 Set<t>
4.Include (包含):
include "product.thrift"
list<product> getProductList();
我建立的.thrift 如下
namespace java service.demo
struct Product{
1:i32 id,
2:string productName,
3:string productNumber,
}
service Hello{
//bean测试
i32 testInt(1:i32 para)
string testString(1:string para);
double testDouble(1:double para);
i64 testLong(1:i64 para);
bool testBoolean(1:bool para);
void testVoid();
void testMultiPara(1:i32 para1,2:double para2,3:bool para3);
//复杂实体测试
void addModel(1:Product para,2:i32 para2);
list<Product> getProductlList(1:i32 para);
set<Product> getProductSet(1:i32 para);
map<i32,Product> getProductMap(1:i32 para);
}
按照下面语句格式生成相应平台代码
生成c#
D:\杭州准备\thrift\thrift-0.9.0.exe -r -gen csharp D:\java\app\labs\src\thiftdemo\Test.thift
生成java
D:\杭州准备\thrift\thrift-0.9.0.exe -r -gen java D:\java\app\labs\src\thiftdemo\Test.thift
这里cshape 用来做客户端,java 做服务端
java 服务端 生成的文件为Hello.Iface ,建立一个类来继承并实现thrift加入的方法即可。
java 务端 : package thiftdemo; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TBinaryProtocol.Factory; 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 org.apache.thrift.transport.TTransportException; public class HelloServer { public void open() { try { TServerSocket serverSocket = new TServerSocket( 9091 ); /* 使用二进制 */ Factory factory = new TBinaryProtocol.Factory(); TProcessor processor = new Hello.Processor( new HelloImpl() ); Args args = new Args( serverSocket ); args.processor( processor ); args.protocolFactory( factory ); TServer server = new TThreadPoolServer( args ); System.out.println( "Start Thrift Port 9091" ); server.serve(); } catch ( TTransportException e ) { /* TODO: handle exception */ } } public static void main( String[] args ) { HelloServer server = new HelloServer(); server.open(); } }
java服务端业务:
package thiftdemo; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.thrift.TException; public class HelloImpl implements Hello.Iface { @Override public Product addProduct( Product para, int para2 ) throws TException { Product product = new Product(); product.setId( 1 ); product.setProductName( "test" ); product.setProductNumber( "20130529" ); return(product); } @Override public Map<Integer, Product> getProductMap( int para ) throws TException { Map<Integer, Product> map = new LinkedHashMap<Integer, Product>(); for ( int i = 0; i < 10; i++ ) { map.put( i, new Product( i, "test", "20130529" ) ); } return(map); } @Override public Set<Product> getProductSet( int para ) throws TException { Set<Product> set = new LinkedHashSet<Product>(); for ( int i = 0; i < 10; i++ ) { set.add( new Product( i, "test", "20130529" ) ); } return(set); } @Override public List<Product> getProductlList( int para ) throws TException { List<Product> productList = new ArrayList<Product>(); for ( int i = 0; i < 10; i++ ) { productList.add( new Product( i, "test", "20130529" ) ); } return(productList); } @Override public boolean testBoolean( boolean para ) throws TException { return(para); } @Override public double testDouble( double para ) throws TException { return(para); } @Override public int testInt( int para ) throws TException { return(para); } @Override public long testLong( long para ) throws TException { return(para); } @Override public void testMultiPara( int para1, double para2, boolean para3 ) throws TException { } @Override public String testString( String para ) throws TException { return(para); } @Override public void testVoid() throws TException { } }
c# 客户端:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Thrift.Transport; using Thrift.Protocol; using NUnit.Framework; namespace ThriftDemo { [TestFixture] public class Client { private Hello.Client client; private TTransport transport; public Client() { this.Connect(); } public void Connect() { this.transport = new TSocket( "127.0.0.1", 9091 ); TProtocol protocol = new TBinaryProtocol( transport ); this.client = new Hello.Client( protocol ); } private void Open() { if ( !this.transport.IsOpen ) this.transport.Open(); } private void Close() { if ( this.transport.IsOpen ) this.transport.Close(); } [Test] public void TestInt() { this.Open(); Assert.AreEqual( 3, this.client.testInt( 3 ) ); this.Close(); } [Test] public void TestString() { this.Open(); Assert.AreEqual( "test", this.client.testString( "test" ) ); this.Close(); } [Test] public void TestLong() { this.Open(); Assert.AreEqual( 3L, this.client.testLong( 3L ) ); this.Close(); } [Test] public void TestDouble() { this.Open(); Assert.AreEqual( 3.5d, this.client.testDouble( 3.5d ) ); this.Close(); } [Test] public void TestBoolean() { this.Open(); Assert.AreEqual( true, this.client.testBoolean( true ) ); this.Close(); } [Test] public void TestMultiPara() { this.Open(); this.client.testMultiPara( 1, 1D, true ); this.Close(); } [Test] public void TestAddProduct() { this.Open(); Product product = new Product(); product.Id = 1; product.ProductName = "test"; product.ProductNumber = "20130529"; Product productFromServer = this.client.addProduct( product, 1 ); Assert.AreEqual( product.Id, productFromServer.Id ); Assert.AreEqual( product.ProductName, productFromServer.ProductName ); Assert.AreEqual( product.ProductNumber, productFromServer.ProductNumber ); this.Close(); } [Test] public void TestGetProductlList() { this.Open(); List<Product> productList = this.client.getProductlList( 1 ); Assert.AreEqual( productList.Count, 10 ); this.Close(); } [Test] public void TestGetProductSet() { this.Open(); Thrift.Collections.THashSet<Product> productSet = this.client.getProductSet( 1 ); Assert.AreEqual( productSet.Count, 10 ); this.Close(); } [Test] public void TestGetProductMap() { this.Open(); Dictionary<int, Product> productHash = this.client.getProductMap( 1 ); Assert.AreEqual( productHash.Count, 10 ); Assert.AreEqual( productHash[0].Id, 0 ); Assert.AreEqual( productHash[1].ProductName, "test" ); Assert.AreEqual( productHash[2].ProductNumber, "20130529" ); this.Close(); } public static void Main( String[] args ) { Client client = new Client(); client.TestAddProduct(); } } }
客户端测试结果
![](https://images2015.cnblogs.com/blog/138935/201605/138935-20160503151714122-999377139.png)
下一篇想写写thrift的原理分析
郑州 2013年6月6日 晴