好久沒有寫文章了,由於換工作了,所以一直沒有時間來寫博。今天抽個空練練手下~最近接觸了下Thrift,網上也有很多文章對於Thrift做了說明:
Thrift是一種可伸縮的跨語言服務架構,它結合了功能強大的軟體堆棧的代碼產生引擎,以建設服務,工作效率和無縫地與C++,C#,Java,Python和PHP和Ruby結合。thrift允許你定義一個簡單的定義檔案中的資料類型和服務介面。以作為輸入檔案,編譯器產生代碼用來方便地產生RPC用戶端和伺服器通訊的無縫跨程式設計語言。
它的好處是什嗎?當然是它支援大多數時下流行的語言。通過Thrift命令自動產生相應的語言指令碼。而進行一些效能對比中,它的好處顯而易見。
以上是傳輸相同的內容時內容大小的對比。
以上是運行開銷比較結果。
TCompactProtocol和TBinaryProtocol是Thrift支援的兩種協議,其中TCompactProtocol使用Variable-Length Quantity (VLQ) 編碼對資料進行壓縮。
詳細可以查看:http://www.javabloger.com/article/apache-thrift-architecture.html
接下來,我想講述一下如何使用Thrift搭建C#版的用戶端以及服務端通訊的程式。
1. 先從官網下載Thrift安裝包以及簽出SVN源碼:
官網:http://thrift.apache.org/download/
這裡我下載了一個Thrift compiler for Windows版本的EXE檔案(thrift-0.7.0.exe)
簽出SVN源碼地址:http://svn.apache.org/repos/asf/thrift/trunk
2. 這裡我利用文章(http://www.javabloger.com/article/thrift-java-code-example.html)的例子(該例子產生Java源碼的),完成一個C#版本的樣本。
3. 首先建立指令碼,命名為textCsharp.thrift,指令碼內容如下:
namespace java com.javabloger.gen.code # 注釋1
struct Blog { # 注釋2
1: string topic
2: binary content
3: i64 createdTime
4: string id
5: string ipAddress
6: map<string,string> props
}
service ThriftCase { # 注釋3
i32 testCase1(1:i32 num1, 2:i32 num2, 3:string num3) # 注釋4
list<string> testCase2(1:map<string,string> num1)
void testCase3()
void testCase4(1:list<Blog> blog)
}
4. 執行thrift命令:thrift -gen csharp testCsharp.thrift,這裡說明一下:參數"csharp”意味著這裡將自動產生C#代碼,如果這裡寫java,python等等,可以用"java"或者"py”代替。
於是得到gen-csharp的目錄,這個目錄裡面就包含支援Thrift的Blog以及ThriftCase的原始碼,具體裡面都產生什麼代碼,後面會做出介紹。
5. 然後,我現在開啟SVN源碼中的 trunk\lib\csharp\ 路徑,我用項目開啟
編譯後,得到Thrift.dll檔案,為了後面使用Thrift做準備。
6.建立工程,添加Server以及Client項目,把剛才產生的程式碼檔案放入Common項目中。讓Client和Server項目引用Thrift.dll類庫。
7. 編寫服務端程式:
public class Server
{
public void Start()
{
TServerSocket serverTransport = new TServerSocket(7911, 0, false);
ThriftCase.Processor processor = new ThriftCase.Processor(new BusinessImpl());
TServer server = new TSimpleServer(processor, serverTransport);
Console.WriteLine("Starting server on port 7911 ...");
server.Serve();
}
}
其中BusinessImpl具體提供商務邏輯的實現:
public class BusinessImpl : ThriftCase.Iface
{
public int testCase1(int num1, int num2, String num3)
{
int i = num1 + num2;
Console.Write( "testCase1 num1+num2 is :"+ i);
Console.WriteLine( " num3 is :"+ num3);
return i;
}
public List<String> testCase2(Dictionary<String, String> num1)
{
Console.WriteLine("testCase2 num1 :" + num1);
List<String> list = new List<String>();
list.Add("num1");
return list;
}
public void testCase3()
{
Console.WriteLine("testCase3 ..........." + DateTime.Now);
}
public void testCase4(List<Blog> blogs)
{
Console.WriteLine("testCase4 ...........");
for (int i = 0; i < blogs.Count; i++)
{
Blog blog = blogs[i];
Console.Write("id:" + blog.Id);
Console.Write(",IpAddress:" + blog.IpAddress);
//Console.Write (",Content:" + new String(blog.Content));
Console.Write(",topic:" + blog.Topic);
Console.Write(",time:" + blog.CreatedTime);
}
Console.WriteLine("\n");
}
}
讓它繼承ThriftCase.Iface介面。
8. 編寫用戶端程式:
class Client
{
static Dictionary<String, String> map = new Dictionary<String, String>();
static List<Blog> blogs = new List<Blog>();
static void Main(string[] args)
{
TTransport transport = new TSocket("localhost", 7911);
TProtocol protocol = new TBinaryProtocol(transport);
ThriftCase.Client client = new ThriftCase.Client(protocol);
transport.Open();
Console.WriteLine("Client calls .....");
map.Add("blog", "http://www.javabloger.com%22);/
client.testCase1(10, 21, "3");
client.testCase2(map);
client.testCase3();
Blog blog = new Blog();
//blog.setContent("this is blog content".getBytes());
blog.CreatedTime = DateTime.Now.Ticks;
blog.Id = "123456";
blog.IpAddress = "127.0.0.1";
blog.Topic = "this is blog topic";
blogs.Add(blog);
client.testCase4(blogs);
transport.Close();
Console.ReadKey();
}
}
9. 運行Server以及Client:
從用戶端調用的方法,服務端已經接收到了資料。
原始碼下載:ThriftCSharp.rar
後面的文章,我會具體介紹下Thrift的工作機制和原理。