爲何選擇Kryo?java
首先,Kryo的序列化方式,在性能方面是比較好的,和Protobuf差很少,比Java原生的序列化方式快多了。因爲本篇文章主要想說明Kryo和Netty的整合,因此關於Kryo序列化的原理請查閱其餘文章。git
其次,Protobuf是個跨語言的解決方案,須要預先定義schema,而後經過預編譯生成代碼。若是是Java單語言調用,Kryo是更好的選擇,不須要預編譯,不須要schema。github
使用鏈接池
apache
Kryo對象非線程安全,可是頻繁new會形成巨大的性能損耗,因此應該使用鏈接池。推薦使用apache的commons-pool2。安全
使用Kryo序列化對象要注意的地方性能
正常狀況下,須要被序列化的對象有默認的無參構造器。測試
不須要實現Serializable接口。spa
若是想使用不帶無參構造器的對象也能正確反序列化,能夠考慮kryo-serializers包,使用其提供的KryoReflectionFactorySupport,會採用jdk的ReflectionFactory反射的生成對象。該方式不須要提供默認的構造器也能夠成功反序列化,可是因爲不調用構造器,若是在構造器中維護了別的類的狀態, 會致使別的類狀態失效。因此最佳實踐是,構造器最好只用於初始化本類的屬性。注意:若是使用KryoReflectionFactorySupport而致使錯誤,有可能不拋異常,而是狀態直接錯誤,很難調試,建議謹慎使用。線程
若是調用了List的sublist方法生成的SubList對象,或者使用Arrays.asList方法生成的對象,都不能正確的序列化。仍然可使用kryo-serializers包所提供的SubListSerializers,ArraysAsListSerializer等完成正確序列化。調試
對於自定義的特殊類,能夠自定義實現FieldSerialier的create方法,並註冊到Kryo的實例化對象中去。
使用Kryo做爲Netty序列化對象的協議
經過實現MessageToByteEncoder接口,實現encode對象
經過實現LengthFieldBasedFrameDecoder接口,實現decode對象
作了一下測試,發送1萬次請求,java內置序列化耗時6.776秒,Kryo耗時3.160秒;發送10萬次請求,java內置序列化耗時48.555秒,Kryo耗時15.423秒。固然這個數據因環境而異,可是提高效果很是顯著。
具體代碼可參見:
Kryo和Netty整合部分:https://github.com/terrymanu/miracle-framework/tree/master/miracle-framework-remote/miracle-framework-remote-netty