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