日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

在Dubbo中使用高效的Java序列化(Kryo和FST)

發布時間:2024/1/17 java 56 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在Dubbo中使用高效的Java序列化(Kryo和FST) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:沈理

文檔版權:?Apache 2.0許可證 署名-禁止演繹

完善中……

TODO 生成可點擊的目錄

目錄

  • 序列化漫談
  • 啟用Kryo和FST
  • 注冊被序列化類
  • 無參構造函數和Serializable接口
  • 序列化性能分析與測試
    • 測試環境
    • 測試腳本
    • Dubbo RPC中不同序列化生成字節大小比較
    • Dubbo RPC中不同序列化響應時間和吞吐量對比
  • 未來

序列化漫談

dubbo RPC是dubbo體系中最核心的一種高性能、高吞吐量的遠程調用方式,我喜歡稱之為多路復用的TCP長連接調用,簡單的說:

  • 長連接:避免了每次調用新建TCP連接,提高了調用的響應速度
  • 多路復用:單個TCP連接可交替傳輸多個請求和響應的消息,降低了連接的等待閑置時間,從而減少了同樣并發數下的網絡連接數,提高了系統吞吐量。

dubbo RPC主要用于兩個dubbo系統之間作遠程調用,特別適合高并發、小數據的互聯網場景。

而序列化對于遠程調用的響應速度、吞吐量、網絡帶寬消耗等同樣也起著至關重要的作用,是我們提升分布式系統性能的最關鍵因素之一。

在dubbo RPC中,同時支持多種序列化方式,例如:

  • dubbo序列化:阿里尚未開發成熟的高效java序列化實現,阿里不建議在生產環境使用它
  • hessian2序列化:hessian是一種跨語言的高效二進制序列化方式。但這里實際不是原生的hessian2序列化,而是阿里修改過的hessian lite,它是dubbo RPC默認啟用的序列化方式
  • json序列化:目前有兩種實現,一種是采用的阿里的fastjson庫,另一種是采用dubbo中自己實現的簡單json庫,但其實現都不是特別成熟,而且json這種文本序列化性能一般不如上面兩種二進制序列化。
  • java序列化:主要是采用JDK自帶的Java序列化實現,性能很不理想。
  • 在通常情況下,這四種主要序列化方式的性能從上到下依次遞減。對于dubbo RPC這種追求高性能的遠程調用方式來說,實際上只有1、2兩種高效序列化方式比較般配,而第1個dubbo序列化由于還不成熟,所以實際只剩下2可用,所以dubbo RPC默認采用hessian2序列化。

    但hessian是一個比較老的序列化實現了,而且它是跨語言的,所以不是單獨針對java進行優化的。而dubbo RPC實際上完全是一種Java to Java的遠程調用,其實沒有必要采用跨語言的序列化方式(當然肯定也不排斥跨語言的序列化)。

    最近幾年,各種新的高效序列化方式層出不窮,不斷刷新序列化性能的上限,最典型的包括:

    • 專門針對Java語言的:Kryo,FST等等
    • 跨語言的:Protostuff,ProtoBuf,Thrift,Avro,MsgPack等等

    這些序列化方式的性能多數都顯著優于hessian2(甚至包括尚未成熟的dubbo序列化)。

    有鑒于此,我們為dubbo引入Kryo和FST這兩種高效Java序列化實現,來逐步取代hessian2。

    其中,Kryo是一種非常成熟的序列化實現,已經在Twitter、Groupon、Yahoo以及多個著名開源項目(如Hive、Storm)中廣泛的使用。而FST是一種較新的序列化實現,目前還缺乏足夠多的成熟使用案例,但我認為它還是非常有前途的。

    在面向生產環境的應用中,我建議目前更優先選擇Kryo。

    啟用Kryo和FST

    使用Kryo和FST非常簡單,只需要在dubbo RPC的XML配置中添加一個屬性即可:

    <dubbo:protocol name="dubbo" serialization="kryo"/> <dubbo:protocol name="dubbo" serialization="fst"/>

    注冊被序列化類

    要讓Kryo和FST完全發揮出高性能,最好將那些需要被序列化的類注冊到dubbo系統中,例如,我們可以實現如下回調接口:

    public class SerializationOptimizerImpl implements SerializationOptimizer {public Collection<Class> getSerializableClasses() {List<Class> classes = new LinkedList<Class>();classes.add(BidRequest.class);classes.add(BidResponse.class);classes.add(Device.class);classes.add(Geo.class);classes.add(Impression.class);classes.add(SeatBid.class);return classes;} }

    然后在XML配置中添加:

    <dubbo:protocol name="dubbo" serialization="kryo" optimizer="com.alibaba.dubbo.demo.SerializationOptimizerImpl"/>

    在注冊這些類后,序列化的性能可能被大大提升,特別針對小數量的嵌套對象的時候。

    當然,在對一個類做序列化的時候,可能還級聯引用到很多類,比如Java集合類。針對這種情況,我們已經自動將JDK中的常用類進行了注冊,所以你不需要重復注冊它們(當然你重復注冊了也沒有任何影響),包括:

    GregorianCalendar InvocationHandler BigDecimal BigInteger Pattern BitSet URI UUID HashMap ArrayList LinkedList HashSet TreeSet Hashtable Date Calendar ConcurrentHashMap SimpleDateFormat Vector BitSet StringBuffer StringBuilder Object Object[] String[] byte[] char[] int[] float[] double[]

    由于注冊被序列化的類僅僅是出于性能優化的目的,所以即使你忘記注冊某些類也沒有關系。事實上,即使不注冊任何類,Kryo和FST的性能依然普遍優于hessian和dubbo序列化。

    當然,有人可能會問為什么不用配置文件來注冊這些類?這是因為要注冊的類往往數量較多,導致配置文件冗長;而且在沒有好的IDE支持的情況下,配置文件的編寫和重構都比java類麻煩得多;最后,這些注冊的類一般是不需要在項目編譯打包后還需要做動態修改的。

    另外,有人也會覺得手工注冊被序列化的類是一種相對繁瑣的工作,是不是可以用annotation來標注,然后系統來自動發現并注冊。但這里annotation的局限是,它只能用來標注你可以修改的類,而很多序列化中引用的類很可能是你沒法做修改的(比如第三方庫或者JDK系統類或者其他項目的類)。另外,添加annotation畢竟稍微的“污染”了一下代碼,使應用代碼對框架增加了一點點的依賴性。

    除了annotation,我們還可以考慮用其它方式來自動注冊被序列化的類,例如掃描類路徑,自動發現實現Serializable接口(甚至包括Externalizable)的類并將它們注冊。當然,我們知道類路徑上能找到Serializable類可能是非常多的,所以也可以考慮用package前綴之類來一定程度限定掃描范圍。

    當然,在自動注冊機制中,特別需要考慮如何保證服務提供端和消費端都以同樣的順序(或者ID)來注冊類,避免錯位,畢竟兩端可被發現然后注冊的類的數量可能都是不一樣的。

    無參構造函數和Serializable接口

    如果被序列化的類中不包含無參的構造函數,則在Kryo的序列化中,性能將會大打折扣,因為此時我們在底層將用Java的序列化來透明的取代Kryo序列化。所以,盡可能為每一個被序列化的類添加無參構造函數是一種最佳實踐(當然一個java類如果不自定義構造函數,默認就有無參構造函數)。

    另外,Kryo和FST本來都不需要被序列化都類實現Serializable接口,但我們還是建議每個被序列化類都去實現它,因為這樣可以保持和Java序列化以及dubbo序列化的兼容性,另外也使我們未來采用上述某些自動注冊機制帶來可能。

    序列化性能分析與測試

    本文我們主要討論的是序列化,但在做性能分析和測試的時候我們并不單獨處理每種序列化方式,而是把它們放到dubbo RPC中加以對比,因為這樣更有現實意義。

    測試環境

    粗略如下:

    • 兩臺獨立服務器
    • 4核Intel(R) Xeon(R) CPU E5-2603 0 @ 1.80GHz
    • 8G內存
    • 虛擬機之間網絡通過百兆交換機
    • CentOS 5
    • JDK 7
    • Tomcat 7
    • JVM參數-server -Xms1g -Xmx1g -XX:PermSize=64M -XX:+UseConcMarkSweepGC

    當然這個測試環境較有局限,故當前測試結果未必有非常權威的代表性。

    測試腳本

    和dubbo自身的基準測試保持接近:

    10個并發客戶端持續不斷發出請求:

    • 傳入嵌套復雜對象(但單個數據量很小),不做任何處理,原樣返回
    • 傳入50K字符串,不做任何處理,原樣返回(TODO:結果尚未列出)

    進行5分鐘性能測試。(引用dubbo自身測試的考慮:“主要考察序列化和網絡IO的性能,因此服務端無任何業務邏輯。取10并發是考慮到http協議在高并發下對CPU的使用率較高可能會先打到瓶頸。”)

    Dubbo RPC中不同序列化生成字節大小比較

    序列化生成字節碼的大小是一個比較有確定性的指標,它決定了遠程調用的網絡傳輸時間和帶寬占用。

    針對復雜對象的結果如下(數值越小越好):

    序列化實現請求字節數響應字節數
    Kryo27290
    FST28896
    Dubbo Serialization430186
    Hessian546329
    FastJson461218
    Json657409
    Java Serialization963630

    Dubbo RPC中不同序列化響應時間和吞吐量對比

    遠程調用方式平均響應時間平均TPS(每秒事務數)
    REST: Jetty + JSON7.8061280
    REST: Jetty + JSON + GZIPTODOTODO
    REST: Jetty + XMLTODOTODO
    REST: Jetty + XML + GZIPTODOTODO
    REST: Tomcat + JSON2.0824796
    REST: Netty + JSON2.1824576
    Dubbo: FST1.2118244
    Dubbo: kyro1.1828444
    Dubbo: dubbo serialization1.436982
    Dubbo: hessian21.496701
    Dubbo: fastjson1.5726352

    測試總結

    就目前結果而言,我們可以看到不管從生成字節的大小,還是平均響應時間和平均TPS,Kryo和FST相比Dubbo RPC中原有的序列化方式都有非常顯著的改進。

    未來

    未來,當Kryo或者FST在dubbo中當應用足夠成熟之后,我們很可能會將dubbo RPC的默認序列化從hessian2改為它們中間的某一個。

    總結

    以上是生活随笔為你收集整理的在Dubbo中使用高效的Java序列化(Kryo和FST)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。