Hessian 原理分析--转
原文地址:http://blog.csdn.net/zhtang0526/article/details/4788879
一.??????遠程通訊協(xié)議的基本原理
網(wǎng)絡通信需要做的就是將流從一臺計算機傳輸?shù)搅硗庖慌_計算機,基于傳輸協(xié)議和網(wǎng)絡?IO?來實現(xiàn),其中傳輸協(xié)議比較出名的有?http?、?tcp?、?udp?等等,?http?、?tcp?、?udp?都是在基于?Socket?概念上為某類應用場景而擴展出的傳輸協(xié)議,網(wǎng)絡?IO?,主要有?bio?、?nio?、?aio?三種方式,所有的分布式應用通訊都基于這個原理而實現(xiàn),只是為了應用的易用,各種語言通常都會提供一些更為貼近應用易用的應用層協(xié)議。
二.??????應用級協(xié)議?Binary-RPC
Binary-RPC?是一種和?RMI?類似的遠程調(diào)用的協(xié)議,它和?RMI?的不同之處在于它以標準的二進制格式來定義請求的信息?(?請求的對象、方法、參數(shù)等?)?,這樣的好處是什么呢,就是在跨語言通訊的時候也可以使用。
來看下?Binary -RPC?協(xié)議的一次遠程通信過程:
?
1?、客戶端發(fā)起請求,按照?Binary -RPC?協(xié)議將請求信息進行填充;
2?、填充完畢后將二進制格式文件轉(zhuǎn)化為流,通過傳輸協(xié)議進行傳輸;
3?、接收到在接收到流后轉(zhuǎn)換為二進制格式文件,按照?Binary -RPC?協(xié)議獲取請求的信息并進行處理;
4?、處理完畢后將結(jié)果按照?Binary -RPC?協(xié)議寫入二進制格式文件中并返回。
?????????問題總結(jié):
1?、傳輸?shù)臉藴矢袷绞?#xff1f;
????標準格式的二進制文件。
2?、怎么樣將請求轉(zhuǎn)化為傳輸?shù)牧?#xff1f;
????將二進制格式文件轉(zhuǎn)化為流。
3?、怎么接收和處理流?
????通過監(jiān)聽的端口獲取到請求的流,轉(zhuǎn)化為二進制文件,根據(jù)協(xié)議獲取請求的信息,進行處理并將結(jié)果寫入?XML?中返回。
4?、傳輸協(xié)議是?
Http?。
三.??????Hessian?——一種實現(xiàn)遠程通訊的?library
Hessian?是由?caucho?提供的一個基于?binary-RPC?實現(xiàn)的遠程通訊?library?。
1?、是基于什么協(xié)議實現(xiàn)的?
基于?Binary-RPC?協(xié)議實現(xiàn)。
2?、怎么發(fā)起請求?
需通過?Hessian?本身提供的?API?來發(fā)起請求。
3?、怎么將請求轉(zhuǎn)化為符合協(xié)議的格式的?
Hessian?通過其自定義的串行化機制將請求信息進行序列化,產(chǎn)生二進制流。
4?、使用什么傳輸協(xié)議傳輸?
Hessian?基于?Http?協(xié)議進行傳輸。
5?、響應端基于什么機制來接收請求?
響應端根據(jù)?Hessian?提供的?API?來接收請求。
6?、怎么將流還原為傳輸格式的?
Hessian?根據(jù)其私有的串行化機制來將請求信息進行反序列化,傳遞給使用者時已是相應的請求信息對象了。
7?、處理完畢后怎么回應?
?????????????處理完畢后直接返回,?hessian?將結(jié)果對象進行序列化,傳輸至調(diào)用端。
四.??????Hessian?源碼分析
以?hessian?和?spring?dm server?整合環(huán)境為例。
Hessian?的這個遠程過程調(diào)用,完全使用動態(tài)代理來實現(xiàn)的。有客戶端可以看出。
除去?spring?對其的封裝,客戶端主要是通過?HessianProxyFactory?的?create?方法就是創(chuàng)建接口的代理類,該類實現(xiàn)了接口,?JDK?的?proxy?類會自動用?InvocationHandler?的實現(xiàn)類(該類在?Hessian?中表現(xiàn)為HessianProxy?)的?invoke?方法體來填充所生成代理類的方法體。
客戶端系統(tǒng)啟動時:
?????????根據(jù)?serviceUrl?和?serviceInterface?創(chuàng)建代理。
?????????HessianProxyFactoryBean?類
????????
HessianClientInterceptor?類
??????????????????createHessianProxy(HessianProxyFactory proxyFactory)
?
HessianProxyFactory?類
??????????????????public Object create(Class api, String urlName)
?
客戶端調(diào)用?hessian?服務時:
???????????????????HessianProxy?類的?invoke(Object proxy, Method method, Object []args)?方法
????????????????????????????String methodName = method.getName();//?取得方法名
????????????????????????????Object value = args[0]; //?取得傳入?yún)?shù)
????????????????????????????conn =?sendRequest(mangleName, args)?;??????//?通過該方法和服務器端取得連接
?
????????????????????????????httpConn = (HttpURLConnection) conn;
????????????????????????????code = httpConn.getResponseCode();????//?發(fā)出請求
?
//?等待服務器端返回相應…………
?
????????????????????????????is = conn.getInputStream();
????????????????????????????Object value = in.readObject(method.getReturnType()); //?取得返回值
?
HessianProxy?類的?URLConnection sendRequest(String methodName, Object []args)?方法:
??????????????????????URLConnection??conn = _factory.openConnection(_url);??????//?創(chuàng)建?URLConnection?
????????????????????????????OutputStream os = conn.getOutputStream();
?
????????????????????????????AbstractHessianOutput out = _factory.getHessianOutput(os); //?封裝為?hessian?自己的輸入輸出API
????????????????????????????out.call(methodName, args);
????????????????????????????return conn;
????????
?
服務器端截獲相應請求交給:
org.springframework.remoting.caucho.HessianServiceExporter
具體處理步驟如下:
a)???????HessianServiceExporter?類
(HessianExporter)?invoke(request.getInputStream(), response.getOutputStream());
?
b)???????HessianExporter?類
(Hessian2SkeletonInvoker)?this.skeletonInvoker.invoke(inputStream, outputStream);
c)???????Hessian2SkeletonInvoker?類
將輸入輸出封轉(zhuǎn)化為轉(zhuǎn)化為?Hessian?特有的?Hessian2Input?和?Hessian2Output
??????Hessian2Input in = new Hessian2Input(isToUse);
??????in.setSerializerFactory(this.serializerFactory);
?
??????AbstractHessianOutput out = null;
??????int major = in.read();
??????int minor = in.read();
??????out = new Hessian2Output(osToUse);
??????out = new HessianOutput(osToUse);
??????out.setSerializerFactory(this.serializerFactory);
??????(HessianSkeleton) this.skeleton.invoke(in, out);
?
d)???????HessianSkeleton?類
???????????讀取方法名
?????????String methodName = in.readMethod();
????Method method = getMethod(methodName);
?
???????????讀取方法參數(shù)
?????????Class []args = method.getParameterTypes();
????Object []values = new Object[args.length];
?
???????????執(zhí)行相應方法并取得結(jié)果
?????????result = method.invoke(service, values);
?
???????????結(jié)果寫入到輸出流
?????????out.writeObject(result);
????????
總結(jié):?由上面源碼分析可知,客戶端發(fā)起請求和服務器端接收處理請求都是通過?hessian?自己的?API?。輸入輸出流都要封裝為?hessian?自己的?Hessian2Input?和?Hessian2Output?,接下來一節(jié)我們將去了解?hessian?自己封裝的輸入輸出到底做了些什么!
五.??????Hessian?的序列化和反序列化實現(xiàn)
hessian?源碼中?com.caucho.hessian.io?這個包是?hessian?實現(xiàn)序列化與反序列化的核心包。其中AbstractSerializerFactory?,?AbstractHessianOutput?,?AbstractSerializer?,?AbstractHessianInput?,AbstractDeserializer?是?hessian?實現(xiàn)序列化和反序列化的核心結(jié)構(gòu)代碼。
?
根據(jù)類來決定用哪種序列化工具類
abstract public Serializer getSerializer(Class cl)??throws HessianProtocolException;?
根據(jù)類來決定用哪種反序列化工具類
abstract public Deserializer getDeserializer(Class cl)??throws HessianProtocolException;
在?SerializerFactory?有很多靜態(tài)?map?用來存放類與序列化和反序列化工具類的映射,這樣如果已經(jīng)用過的序列化工具就可以直接拿出來用,不必再重新實例化工具類。
在?SerializerFactory?中,實現(xiàn)了抽象類的?getSerializer?方法,根據(jù)不同的需要被序列化的類來獲得不同的序列化工具,一共有?17?種序列化工具,?hessian?為不同的類型的?Java?對象實現(xiàn)了不同的序列化工具,默認的序列化工具是?JavaSerializer?。
在?SerializerFactory?中,也實現(xiàn)了抽象類的?getDeserializer?方法,根據(jù)不同的需要被反序列化的類來獲得不同的反序列化工具,默認的反序列化工具類是?JavaDeserializer?。
它會實現(xiàn)很多方法,用來做流輸出。
需要注意的是方法,它會先調(diào)用?serializerFactory?根據(jù)類來獲得?serializer?序列化工具類
public void writeObject(Object object)
throws IOException?
{?
if (object == null) {?
writeNull();?
return;?
}?
?
Serializer serializer;?
?
serializer =?_serializerFactory.getSerializer(object.getClass());??
?
serializer.writeObject(object, this);?
}?
其?writeObject?是必須在子類實現(xiàn)的方法,?AbstractSerializer?有?17?種子類實現(xiàn),?hessian?根據(jù)不同的java?對象類型來實現(xiàn)了不同的序列化工具類,其中默認的是?JavaSerializer?。
而?JavaSerializer?的?writeObject?方法的實現(xiàn),遍歷?java?對象的數(shù)據(jù)成員,根據(jù)數(shù)據(jù)成員的類型來獲得各自的?FieldSerializer?,一共有?6?中默認的?FieldSerializer?。
拿默認的?FieldSerializer?舉例,還是調(diào)用?AbstractHessianOutput?的子類來?writeObject?,這個時候,肯定能找到相應的?Serializer?來做序列化
?
同理可以反推出?hessian?的反序列化機制。?SerializerFactory?可以根據(jù)需要被反序列化的類來獲得反序列化工具類來做反序列化操作。
?
總結(jié):得益于?hessian?序列號和反序列化的實現(xiàn)機制,?hessian?序列化的速度很快,而且序列化后的字節(jié)數(shù)也較其他技術少。
?
?
參考文獻:
http://blog.csdn.net/xpspace/archive/2007/10/05/1811603.aspx
轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/p/5488309.html
總結(jié)
以上是生活随笔為你收集整理的Hessian 原理分析--转的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用实例讲解Spark Sreaming-
- 下一篇: 好技术领导和差技术领导区别在哪里--转