莊周夢蝶

          生活、程序、未來
             :: 首頁 ::  ::  :: 聚合  :: 管理

          初識Kestrel

          Posted on 2009-09-15 11:34 dennis 閱讀(15389) 評論(9)  編輯  收藏 所屬分類: java源碼解讀
              Kestrel是一個scala寫的twitter開源的消息中間件,特點是高性能、小巧(2K行代碼)、持久存儲(記錄日志到journal)并且可靠(支持可靠獲取)。Kestrel的前身是Ruby寫的Starling項目,后來twitter的開發人員嘗試用scala重新實現。它的代碼非常簡潔并且優雅,推薦一讀。

              Kestrel采用的協議是memcached的文本協議,但是并不完全支持所有memcached協議,也不是完全兼容現有協議。標準的協議它僅支持GET、SET、FLUSH_ALL、STATS,擴展的協議有:
                     
                        SHUTDOWN       關閉kestrel server     
                        RELOAD         動態重新加載配置文件
                        DUMP_CONFIG    dump配置文件
                        FLUSH queueName   flush某個隊列

              每個key對應都是一個隊列。標準memcached文本協議的支持上也沒有完全兼容,SET不支持flag,因此現有大多數基于flag做序列化的memcached client都無法存儲任意java類型到kestrel;FLUSH_ALL返回"Flushed all queues.\r\n"而不是"OK\r\n"。

              GET協議支持阻塞獲取和可靠獲取,都是在key上作文章,例如你要獲取queue1的消息,并且在沒有消息的時候等待一秒鐘,如果有消息馬上返回,超時時間后還沒有就返回空,kestrel允許你通過發送
                               "GET queue1/t=1000\r\n"

          來阻塞獲取。本來的key應該queue1,這里變成了"queue1/t=1000",因此如果你使用的client有對返回的key和發送的key做校驗,那么可能就認為kestrel返回錯誤。
              什么是可靠獲取呢?默認的GET是從隊列中獲取消息后,server端就將該消息從隊列中移除,客戶端需要自己保證不把這個消息丟失掉,也就是說這里是類似JMS規范中的自動應答(auto-acknowledge),如果客戶端在處理這個消息的時候異常崩潰或者在接收消息數據的時候連接斷開,那么可能導致這個消息永久丟失。Kestrel的可靠獲取就是類似JMS規范中的CLIENT_ACK mode,客戶端獲取消息后,server將這個消息從隊列移除并正常發送給客戶端,如果這時候客戶端崩潰或者連接斷開,那么server將不會確認該消息被消費并且"un-get"這個消息,重新放到隊列頭部,那么當client重新連接上來的時候還可以獲取這個消息;只有當server收到客戶端的明確確認消息成功的時候,才將消息移除。這個功能也是通過key做手腳,

          "GET queue1/open\r\n"   開始一次可靠獲取
          "GET queue1/close\r\n"  確認消費成功


          你要關閉前一次可靠獲取開啟新的一次,還可以這樣調用
          "GET queue1/close/open\r\n"


              要注意的是每個連接的client只能有一個正在執行的可靠獲取,關閉一個沒有開啟的reliable fetch或者在執行一次reliable fetch再次open一個新的獲取都將直接返回空。

              從kestrel的協議方面,我們可以學習到的一點就是在做一份協議的時候,如果有多種不同語言的client的話,應該盡量用通用協議,通用協議通常都已經有很多成熟的client可以使用,避免了為私有協議開發不同語言的client;并且我們可以在通用協議上作擴展,例如kestrel在key上面做的花樣,通過給key附加不同的屬性即可實現一些特殊功能

              XMemcachedClient默認是無法支持kestrel對memcached的協議的擴展,也就是說無法支持阻塞獲取、可靠獲取和flush_all,這是因為xmemcached會對返回的key和發送的key做校驗,如果不相等就認為解碼錯誤;并且由于kestrel不支持flag,因此無法存儲java序列化類型;另外一個問題是,xmemcached(spymemcached)都會將連續的GET協議合并成一個bulk get協議,而kestrel也并不支持bulk get,所以需要關閉這個優化,這個可以通過下列代碼關閉:
          memcachedClient.setOptimizeGet(false);

          Spymemcached似乎不提供這個選項。為了解決序列化問題,我添加了一個新的KestrelCommandFactory,使用這個CommandFactory后,將默認關閉get優化,并且不對GET返回的key做校驗從而支持阻塞獲取和可靠獲取,并且將在存儲的數據之前加上4個字節的flag(整型),因此可以支持存儲任意可序列化類型。但是有一些應用只需要存儲字符串類型和原生類型,這是為了在不同語言的client之間保持可移植(如存儲json數據),那么就不希望在數據之前加上這個flag,關閉這個功能可以通過
          memcachedClient.setPrimitiveAsString(true);

          方法來設置,所有的原生類型都將調用toString轉成字符串來存儲,字符串前不再自動附加flag。

              KestrelCommandFactory已經提交到svn trunk,預計在xmemcached 1.2.0-RC2的時候發布。

              使用KestrelCommandFactory對kestrel做的性能測試,server和client都跑在linux上,jdk6,單線程單client連續push消息

                         消息個數       消息長度       是否啟用journal   時間       TPS(/s)
                          500000          256             否              123.0s     4065
                          500000          1024            否              126.3s     3959
                          500000          4096            否              120.6s     4145
                          500000          4096            是              122.1s     4095
                          500000          8192            是              121.2s     4125

          從數據上來看比官方數據好很多,可能機器配置不同。是否啟用journal帶來的影響似乎很小,寫文件都是append,還是比較高效的。

          kestrel的項目主頁  http://github.com/robey/kestrel
          kestrel的wiki頁    http://wiki.github.com/robey/kestrel
          xmemcached項目主頁  http://code.google.com/p/xmemcached/



          評論

          # re: 初識Kestrel[未登錄]  回復  更多評論   

          2009-09-16 12:38 by tenderuser
          scala 現在已經有人在使用了? 太快了。。

          # re: 初識Kestrel  回復  更多評論   

          2009-09-16 13:00 by Unmi
          是啊發展太快了
          請問是否可以轉載

          # re: 初識Kestrel  回復  更多評論   

          2009-09-16 14:38 by Sparkle
          其實我不認同kestrel這種用memcached協議的做法,看上去兼容性強了,實際上很多暗病。而且memcached的文本協議也不見得是什么好協議

          # re: 初識Kestrel  回復  更多評論   

          2009-09-16 14:55 by dennis
          @Sparkle
          通用協議,肯定沒辦法做到效率的最大化,針對應用做優化,勝在可以有多種成熟的client可用,對于沒有能力或者時間開發多種語言client的團隊來說是有價值的。memcached的文本協議確實不怎么樣,我在寫xmemcached的時候就覺的解析起來不是很方便,有些拐彎抹角的地方。一開始它的協議是簡單的,隨著功能的附加,又要考慮兼容性,導致不得不開發二進制協議了。

          # re: 初識Kestrel  回復  更多評論   

          2009-09-16 14:55 by dennis
          @Unmi
          請注明出處即可

          # re: 初識Kestrel  回復  更多評論   

          2009-10-15 10:14 by Xuefeng
          分析得很精到,
          歡迎加入Scala中文社區郵件列表,保持Scala愛好者之間聯系,加強和方便交流,分享和合作。
          發送空郵件到: scalacn+subscribe@googlegroups.com 加入郵件列表

          # re: 初識Kestrel  回復  更多評論   

          2009-10-15 10:14 by Xuefeng
          或訪問http://groups.google.com/group/scalacn

          # re: 初識Kestrel  回復  更多評論   

          2009-10-15 10:16 by Xuefeng
          http://groups.google.com/group/scalacn

          # re: 初識Kestrel  回復  更多評論   

          2009-10-15 13:01 by dennis
          @Xuefeng
          已加入,感謝
          主站蜘蛛池模板: 疏附县| 霍州市| 双城市| 隆昌县| 陇西县| 阳春市| 榆林市| 清新县| 平昌县| 西乌珠穆沁旗| 同江市| 衡阳市| 米易县| 西乡县| 克拉玛依市| 盘山县| 邮箱| 金坛市| 安图县| 阜阳市| 宁晋县| 洛扎县| 化州市| 华容县| 临夏县| 许昌市| 大名县| 天柱县| 新乡县| 南宫市| 南丹县| 吉木萨尔县| 旺苍县| 玉田县| 罗源县| 上蔡县| 屯昌县| 渝中区| 侯马市| 平和县| 绩溪县|