序列化
Dynamic typing
Custom serialization
Java serialization
Component-specific serialization registrations
本文闡述了 Storm 0.6.0 以上版本的序列化機制。在低於 0.6.0 版本的 Storm 中使用了另外一種序列化系統,詳細信息能夠參考 Serialization (prior to 0.6.0) 一文。
Storm 中的 tuple 能夠包含任何類型的對象。因爲 Storm 是一個分佈式系統,因此在不一樣的任務之間傳遞消息時 Storm 必須知道怎樣序列化、反序列化消息對象。
Storm 使用 Kryo庫 對對象進行序列化。Kryo 是一個靈活、快速的序列化庫。Storm 默認支持基礎類型、string、byte arrays、ArrayList、HashMap、HashSet 以及 Clojure 的集合類型的序列化。若是你須要在 tuple 中使用其餘的對象類型,你就須要註冊一個自定義的序列化器。html
在 tuple 中沒有對各個域(field)的直接類型聲明。你須要將對象放入對應的域中,而後 Storm 能夠動態地實現對象的序列化。在學習序列化接口以前,咱們先來了解一下爲何 Storm 的 tuple 是動態類型化的。
爲 tuple fields 增長靜態類型會大幅增長 Storm 的 API 的複雜度。好比 Hadoop 就將它的 key 和 value 都靜態化了,這就要求用戶本身添加大量的註解。使用 Hadoop 的 API 很是繁瑣,而相應的「類型安全」不值得。相對的,動態類型就很是易於使用。
進一步說,也不可能有什麼合理的方法將 Storm 的 tuple 的類型靜態化。假如一個 Bolt 訂閱了多個 stream,從這些 stream 傳入的 tuple 極可能都帶有不一樣的類型。在 Bolt 的 execute 方法接收到一個 tuple 的時候,這個 tuple 可能來自任何一個 stream,也可能包含各類組合類型。也許你可使用某種反射機制來爲 bolt 訂閱的每一個 tuple stream 聲明一個方法類處理 tuple,可是 Storm 能夠提供一種更簡單、更直接的動態類型機制來解決這個問題。
最後,Storm 使用動態類型定義的另外一個緣由就是爲了用簡潔直觀的方式使用 Clojure、JRuby 這樣的動態類型語言。java
前面已經提到,Storm 使用 Kryo 來處理序列化。若是要實現自定義的序列化生成器,你須要用Kryo註冊一個新的序列化生成器。強烈建議讀者先仔細閱讀 Kryo主頁 來理解它是怎樣處理自定義的序列化的。
能夠經過topology的 topology.kryo.register 屬性來添加自定義序列化生成器。該屬性接收一個註冊器列表,每一個註冊項均可以使用如下兩種註冊格式中的一種格式:
1.只有一個待註冊的類的名稱。在這種狀況下,Storm 會使用 Kryo 的 FieldsSerializer 來序列化該類。這也許並不必定是該類的最優化方式 —— 能夠查看 Kryo 的文檔來了解更多細節內容。
2.一個包含待註冊的類的名稱和實現了com.esotericsoftware.kryo.Serializer接口的類組成的集合。
舉例:git
topology.kryo.register: - com.mycompany.CustomType1 - com.mycompany.CustomType2: com.mycompany.serializer.CustomType2Serializer - com.mycompany.CustomType3
com.mycompany.CustomType1 和 com.mycompany.CustomType3 會使用 FieldsSerializer,而com.mycompany.CustomType2 則會使用 com.mycompany.serializer.CustomType2Serializer來實現序列化。
在topology的配置中,Storm 提供了用於註冊序列化生成器的幫助類。Config 類有一個 registerSerialization 方法能夠將序列化生成器註冊到配置中。
Config 中有一個更高級的配置項作 Config.TOPOLOGY_SKIP_MISSING_KRYO_REGISTRATIONS。若是你將該項設置爲 true,Storm 會忽略掉全部已註冊可是在topology的類路徑上沒有相應的代碼的序列化器。不然,Storm 會在沒法查找到序列化器的時候拋出錯誤。若是你在集羣中運行有多個topology而且每一個topology都有不一樣的序列化器,可是你又想要在storm.yaml 中聲明好全部的序列化器,在這種狀況下這個配置項會有很大的幫助。github
若是 Storm 發現了一個沒有註冊序列化器的類型,它會使用 Java 序列化器來代替,若是這個對象沒法被 Java 序列化器序列化,Storm 就會拋出異常。
注意,Java 自身的序列化機制很是耗費資源,並且無論在 CPU 的性能上仍是在序列化對象的大小上都沒有優點。強烈建議讀者在生產環境中運行topology 的時候註冊一個自定義的序列化器。保留 Java 的序列化機制主要爲了便於設計新topology 的原型。
你能夠經過將 Config.TOPOLOGY_FALL_BACK_ON_JAVA_SERIALIZATION 配置爲 false 的方式來將序列化器回退到 Java 的序列化機制。apache
Storm 0.7.0 支持對特定組件的配置(詳情請參閱Storm配置一文)。固然,若是某個組件定義了一個序列化器,這個序列化器也須要可以支持其餘的 bolt —— 不然,後續的 bolt 將會沒法接收來自該組件的消息!
在提交topology 的時候,topology 會選擇一組序列化器用於在全部的組件間傳遞消息。這是經過將特定組件的序列化器註冊信息與普通的序列化器信息融合在一塊兒實現的。若是兩個組件爲同一個類定義了兩個序列化器,Storm 會從中任意選擇一個。
若是在兩個組件的序列化器註冊信息衝突的時候須要強制使用一個序列化器,能夠在topology 級的配置中定義你想要的序列化器。對於序列化器的註冊信息,拓撲中配置的值是優先於具體組件的配置的。安全