簡易RPC框架:序列化機制

概述

在上一篇文章《簡易RPC框架:基於 netty 的協議編解碼》中談到對於協議的 decode 和 encode,在談 decode 之前,必須先要知道 encode 的過程是什麼,它把什麼東西轉化成了二進制協議。
由於我們還未談到具體的 RPC 調用機制,因此暫且認爲 encode 就是把一個包含了調用信息的 Java 對象,從 client 經過序列化,變成一串二進制流,發送到了 server 端。
這裏需要明確的是,encode 的職責是拼協議,它不負責序列化,同樣,decode 只是把整個二進制報文分割,哪部分是報文頭,哪部分是報文體,誠然,報文體就是被序列化成二進制流的一個 Java 對象。
對於調用方來說,先將調用信息封裝成一個 Java 對象,經過序列化後形成二進制流,再經過 encode 階段,拼接成一個完整的遵守我們定好的協議的報文。
對於被調用方來說,則是收取完整的報文,在 decode 階段將報文中的報文頭,報文體分割出來,在序列化階段將報文體反序列化爲一個 Java 對象,從而獲得調用信息。
本文探討序列化機制。

基於 netty handler

由於這個 RPC 框架基於 netty 實現,因此序列化機制其實體現在了 netty 的 pipeline 上的 handler 上。
例如對於調用方,它需要在 pipeline 上加上一個 序列化 encode handler,用來序列化發出去的請求,同時需要加上一個反序列化的 decode handler, 以便反序列化調用結果。如下所示:

                    protected void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline pipeline = ch.pipeline();
                        pipeline.addLast(new ProtocolEncoder())
                                .addLast(new ProtocolDecoder())
                                .addLast(new SerializationHandler(serialization))
                                .addLast(new DeserializationHandler(serialization));

                    }

其中的 SerializationHandler 和 DeserializationHandler 就是上文提到的序列化 encode handler 和反序列化 decode handler。
同樣,對於被調用方來說,它也需要這兩個handler,與調用方的 handler 編排順序一致。

其中,serialization 這個參數的對象代表具體的序列化機制策略。

序列化機制

上文中,SerializationHandler 和 DeserializationHandler 這兩個對象都需要一個 serialization 對象作爲參數,它是這麼定義的:

private ISerialization serialization = SerializationFactory.getSerialization(ServerDefaults.DEFAULT_SERIALIZATION_TYPE);

採用工廠模式來創建具體的序列化機制:

/**
 * 序列化工廠
 *
 * @author beanlam
 * @version 1.0
 */
public class SerializationFactory {

    private SerializationFactory() {
    }

    public static ISerialization getSerialization(SerializationType type) {
        if (type == SerializationType.JDK) {
            return new JdkSerialization();
        }
        return new HessianSerialization();
    }
}

這裏暫時只支持 JDK 原生序列化 和 基於 Hessian 的序列化機制,日後若有其他效率更高更適合的序列化機制,則可以在工廠類中進行添加。

這裏的 hessian 序列化是從 dubbo 中剝離出來的一塊代碼,感興趣可以從 dubbo 的源碼中的 com.caucho.hessian 包中獲得。

以 HessianSerialization 爲例:

/**
 * @author beanlam
 * @version 1.0
 */
public class HessianSerialization implements ISerialization {

    private ISerializer serializer = new HessianSerializer();
    private IDeserializer deserializer = new HessianDeserializer();

    @Override
    public ISerializer getSerializer() {
        return serializer;
    }

    @Override
    public IDeserializer getDeserializer() {
        return deserializer;
    }

    @Override
    public boolean accept(Class<?> clazz) {
        return Serializable.class.isAssignableFrom(clazz);
    }
}

根據 Hessian 的 API, 分別返回一個 hessian 的序列化器和反序列化器即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章