公司的一些平臺服務框架底層封裝了thrift提供服務,最近項目不是很緊,因而研究了一下,剛剛入門,理解得不深,寫這篇博文來整理一下思路.html
簡單來講,是Facebook公佈的一款開源跨語言的RPC框架.java
那麼問題來了.c++
RPC全稱爲Remote Procedure Call,意爲遠程過程調用.git
假設有兩臺服務器A,B.A服務器上部署着一個應用a,B服務器上部署着一個應用b,如今a但願可以調用b應用的某個函數(方法),可是兩者不在同一個進程內,不能直接調用,就須要經過網絡傳輸,在AB服務器之間建一條網絡傳輸通道,a把參數傳過去,b接收到參數調用本身的方法,獲得結果,再經過網絡傳回給a,簡單講就是A經過網絡來調用B的過程.這個過程要涉及的東西不少,好比多線程,Socket,序列化反序列化,網絡I/O,很複雜,因而牛掰的程序員把這些封裝起來作成一套框架,供你們使用,就是RPC框架. 程序員
thrift經過一箇中間語言IDL(接口定義語言)來定義RPC的數據類型和接口,這些內容寫在以.thrift結尾的文件中,而後經過特殊的編譯器來生成不一樣語言的代碼,以知足不一樣須要的開發者,好比java開發者,就能夠生成java代碼,c++開發者能夠生成c++代碼,生成的代碼中不但包含目標語言的接口定義,方法,數據類型,還包含有RPC協議層和傳輸層的實現代碼.github
thrift是一種c/s的架構體系.在最上層是用戶自行實現的業務邏輯代碼.第二層是由thrift編譯器自動生成的代碼,主要用於結構化數據的解析,發送和接收。TServer主要任務是高效的接受客戶端請求,並將請求轉發給Processor處理。Processor負責對客戶端的請求作出響應,包括RPC請求轉發,調用參數解析和用戶邏輯調用,返回值寫回等處理。從TProtocol如下部分是thirft的傳輸協議和底層I/O通訊。TProtocol是用於數據類型解析的,將結構化數據轉化爲字節流給TTransport進行傳輸。TTransport是與底層數據傳輸密切相關的傳輸層,負責以字節流方式接收和發送消息體,不關注是什麼數據類型。底層IO負責實際的數據傳輸,包括socket、文件和壓縮數據流等。apache
個人電腦是mac,第一次安裝也碰到了一些問題,因此有必要記錄一下.ruby
首先,在官網下載安裝包http://thrift.apache.org/download 目前官網是0.10.0版本.下載完以後解壓到想要安裝的目錄.服務器
進入根目錄:網絡
step1:cd thrift-0.10.0 step2:./configure step3:make step4:make install
安裝的時候,第二步出現了問題,提示:
Bison version 2.5 or higher must be installed on the system!
緣由是Bison版本太低,mac默認安裝的版本是2.3,所以須要安裝最新版的Bison,命令行輸入:brew install bison安裝最新版bison,若是你的命令行反饋:Command not found,極可能是由於你沒裝homebrew,命令行輸入:
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
等待安裝完homebrew就能夠安裝bison了,最新版本3.0.4安裝完之後,執行第二步,發現依然提示上面那個警告,緣由是由於它讀取的仍然是默認的bison,因而找到系統安裝的bison目錄,個人mac是
/Library/Developer/CommandLineTools/usr/bin/bison,解決方法也比較簡單,能夠先將這個目錄下的bison名字改一下,再將最新版的bison複製進來,因而,在bin目錄下,執行命令:
sudo mv bison bison111
sudo cp /usr/local/opt/bison/bin/bison /Library/Developer/CommandLineTools/usr/bin/
如今,再按照上面的步驟進行下去,就能夠正確安裝thrift了.
1,建立一個服務Hello,建立文件Hello.thrift,代碼以下:
namespace java service.demo service Hello{ string helloString(1:string para) }
這裏定義了一個名爲helloString的方法,入參和返回值都是一個string類型的參數.
2,終端進入Hello.thrift所在目錄,執行命令:
thrift -r -gen java Hello.thrift
發如今當前目錄下多了一個gen-java的目錄,裏面的有一個Hello.java的文件.這個java文件包含Hello服務的接口定義Hello.Iface,以及服務調用的底層通訊細節,包括客戶端的調用邏輯Hello.Client以及服務端的處理邏輯Hello.Processor,
3,建立一個Maven管理的Java項目,pom.xml中添加相關的依賴,並將Hello.java文件複製到項目中:
<dependency> <groupId>org.apache.thrift</groupId> <artifactId>libthrift</artifactId> <version>0.10.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.5</version> </dependency>
4,建立HelloServiceImpl實現Hello.Iface接口:
package service.demo; import org.apache.thrift.TException; /** * @author yogo.wang * @date 2017/02/21-下午2:13. */ public class HelloServiceImpl implements Hello.Iface { public String helloString(String para) throws TException { return "result:"+para; } }
5,建立服務端實現代碼HelloServiceServer,把HelloServiceImpl做爲一個具體的處理器傳遞給Thrift服務器:
package service.demo; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.server.TServer; import org.apache.thrift.server.TSimpleServer; import org.apache.thrift.transport.TServerSocket; import org.apache.thrift.transport.TTransportException; /** * @author yogo.wang * @date 2017/02/21-下午2:15. */ public class HelloServiceServer { /** * 啓動thrift服務器 * @param args */ public static void main(String[] args) { try { System.out.println("服務端開啓...."); TProcessor tprocessor = new Hello.Processor<Hello.Iface>(new HelloServiceImpl()); // 簡單的單線程服務模型 TServerSocket serverTransport = new TServerSocket(9898); TServer.Args tArgs = new TServer.Args(serverTransport); tArgs.processor(tprocessor); tArgs.protocolFactory(new TBinaryProtocol.Factory()); TServer server = new TSimpleServer(tArgs); server.serve(); }catch (TTransportException e) { e.printStackTrace(); } } }
6,建立客戶端實現代碼HelloServiceClient,調用Hello.client訪問服務端的邏輯實現:
package service.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; /** * @author yogo.wang * @date 2017/02/21-下午2:35. */ public class HelloServiceClient { public static void main(String[] args) { System.out.println("客戶端啓動...."); TTransport transport = null; try { transport = new TSocket("localhost", 9898, 30000); // 協議要和服務端一致 TProtocol protocol = new TBinaryProtocol(transport); Hello.Client client = new Hello.Client(protocol); transport.open(); String result = client.helloString("哈哈"); System.out.println(result); } catch (TTransportException e) { e.printStackTrace(); } catch (TException e) { e.printStackTrace(); } finally { if (null != transport) { transport.close(); } } } }
所有工做完成後,下面來測試一下,先執行服務端main方法,在執行客戶端main方法,會在客戶端控制檯打印出:result:哈哈.