放翁(文初)的一畝三分地

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            210 隨筆 :: 1 文章 :: 320 評論 :: 0 Trackbacks

          #

             今天是轉崗到淘寶的第七天,也算是一周吧,期待來這個團隊已經有快大半年了,這次阿軟的重組給了一個機會,過去的就過去吧,不再回首有任何的抱怨和遺憾,需要面對的是新的將來。

              很奇怪,來到淘寶,都是熟人,Boss是早就相識的菲青,TOP團隊的自雪,鳳先,秀芳及我不認識但是認識我的其他同學都很熱情,運營,PD,OST都是以前阿軟的老同學,還有其他幾個團隊的朋友,感覺回到了家,而不是離開了家。

              原先來淘寶是比較堅決的,同時也得到王博士的支持,心里還是比較有底的,不過就是擔心過來以后和淘寶已有的團隊合作可能會有磨合期,因為擔心有“小圈子”。結果卻是很出乎我的意料,TOP的人就和做的事情一樣,是一批開放的人,自雪,鳳先,張三各個都很放的開的和我聊,對于架構,對于技術,對于未來的發展,這些人坐在一起什么都可以說,自己覺得自己早先是用老思維來看待這個團隊了。這個團隊很年輕,很有活力和創造力,缺少的只是一些經驗,而我經驗是有一些,但是那些斗志已經在去年一年被磨礪的差不多了,正好是我回爐好好再熱一熱的時候了。來之前就和黑羽有過接觸,也看過他對于TOP的一些構想,在我的計劃中就有和他交流的部分,上周找了一個時間碰了一下,果然有很多和我一致的想法,同時還有一些比我更加深入的idea,特別是對于大淘寶未來的一個構想。其實來到TOP我所要做的就是在技術的架構上找到商業的感覺,讓商業驅動技術,技術沉淀積累來支持商業的暢想。

              這七天過的很快,全身心投入的工作,時間總是過的很快,而且過去那種沉悶的心情和處事的態度在這里得到了改變。明天基本上就看完了TOP的大部分代碼,整理了一些review的建議,同時昨天還花了一些時間去看了看google appengine,寫了幾個小應用,看了看源碼(部分反編譯),因為要給boss對于小應用hosting方面的一些想法。

             總的來說還是和我原先的計劃一樣,商業上和PD運營交流,了解未來TOP商業發展方向,以及對技術架構的一些需求。架構上從代碼和文檔看起,文檔不是很多,所以就只好每個工程看過來,也不錯,看到自雪同學寫的代碼還是不錯的,同時也看到了淘寶的基礎組件的推廣力度之大,這比在阿里軟件強的多,其實也是我一直希望看到的,人人都是技術牛人,都在做重復的事情,但是卻沒有技術沉淀,其實大家完全可以吧自己的構想增強在別人的基礎之上,而不是什么都自己搞一套,淘寶的技術應該來說在政策上得到了支持,技術積累效果還是不錯的,這里還不得不提到我的淘寶同學畢玄同學的服務基礎框架HSF,雖然現在還沒有接觸,但是應該已經發展的挺好的。

             有兩個能夠用人,擔得起起技術團隊發展的Boss,有這么一些年輕有沖勁的小同學,有這么一些樂于傾聽分享協作的老同學,有這么一些很有商業feeling的非技術團隊同學,要做好TOP,我想只有三個字:“沒問題”。這是我在入職七天寫的隨記,一年后再來回看我今天說的這些話,在來看看這個團隊創造的價值。

             附:在淘寶申請好了花名:放翁。陸游的字,武俠小說的人就連掃地的都沒有了,歷史名人也沒有了,不過詩人倒是沒有人用,指不定還開創了淘寶同學入職的花名新取法。

             好好工作,天天向上,為了TOP,為了家里的BB,為了自己的一點理想,踏踏實實的走自己的路,讓別人開車去吧,^_^

           

          本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/cenwenchu79/archive/2009/08/12/4440248.aspx

          posted @ 2009-08-12 23:16 岑文初 閱讀(1172) | 評論 (1)編輯 收藏

             昨天是去淘寶工作的第一天,最近最頭痛的就是花名,在我兒子出生的時候我就知道起名字是最麻煩的事情,而起花名更是痛苦,因為你的選擇余地更小,同時還不能和前人重復,好不容易找到兩個還不錯的,結果一個給其他部門的老大保留了,一個因為拼音和一個同學相似而無法使用。想用文初,結果還給一個淘寶的活躍用戶使用了,問了HR不取花名是否可以,回答說,不可以,太折騰了。

             昨天開了一整天的會,主要還是協調兩個平臺之間將來的合作模式,同時也梳理了雙方的現有功能,將未來雙方的邊界做了初步定奪,同時也對將來的一些需求做了初步的規劃,系統的模塊化也提上了最近的日程。

            今天會化一些時間看看已有的代碼熟悉一下Top的情況,同時也看看一些流程性的文檔,希望能夠盡快的對Top全方位的了解,這樣便于從細節實現到整體架構設計都能給出自己的意見。

            初來乍到不容易,很多需要從新開始的,不過對我來說合作的人,做的事情還是有一定的基礎,因此只是需要一周左右的過渡期,后續應該會走的更加順暢。

           

           
          posted @ 2009-08-06 05:12 岑文初 閱讀(1032) | 評論 (0)編輯 收藏

               摘要: Author : 岑文初 Email: wenchu.cenwc@alibaba-inc.com Blog: http://blog.csdn.net/cenwenchu79 Date: 2009-5-26 目錄 需求轉而學習 “軟”負載均衡 LVS (Linux Virtual Server) Virtual Server三種模式介紹 Virtual...  閱讀全文
          posted @ 2009-08-04 22:32 岑文初 閱讀(2281) | 評論 (1)編輯 收藏

               摘要: “軟”負載均衡學習點滴  閱讀全文
          posted @ 2009-08-04 22:30 岑文初 閱讀(2091) | 評論 (0)編輯 收藏

          Author : 岑文初

          Email: wenchu.cenwc@alibaba-inc.com

          Blog: http://blog.csdn.net/cenwenchu79

          Date: 2009-5-26

          目錄

          需求轉而學習

          “軟”負載均衡

          LVS Linux Virtual Server

          Virtual Server三種模式介紹

          Virtual Server三種模式的比較

          Virtual Server三種模式實踐

          三種模式下的簡單壓力測試

          HA-Proxy

          HA-Proxy安裝和使用

          HA-Proxy的壓力測試結果

          負載學習心得

          需求轉而學習

                   很多時候不少做開發的同學都認為技術更新的快,新技術、新概念層出不窮,大家樂此不疲的去跟隨著所謂的“技術趨勢”走在風頭浪尖上,但其實往往忘記了一個最重要的問題“滿足客戶需求”。其實技術就是為滿足需求服務的,用最小的代價來滿足用戶的需求,以最簡單高效的方式來達到目標,就是每個開發者應該追求的。(不要因為自己的架構很簡單就臉紅拿不出手,只要你在滿足用戶當前需求的基礎上對未來有所考慮,那么化繁為簡就是一種能力的表現)

                   SIP(服務集成平臺)5.7版本中對于未來多個服務提供商,多種類型的服務,在每日幾億的調用壓力下,需要找到一個解決方案:可以分流不同服務提供商的服務,分流不同類型的服務,服務隔離化來減少服務相互之間影響以及服務提供商之間的影響。

                   當前SIP的前端是通過硬件F5作負載均衡,因此是無狀態無差別的服務負載,這也使得無法區分不同的服務提供商的服務請求和不同類型的服務請求,導致服務提供商之間的服務會產生相互影響(旺旺即時通信類API在峰值占用了大部分的服務處理資源,淘寶寶貝上傳類API占用了大量的帶寬)。近期還有更大的兩類API將會接入,因此尋找一個服務可分流的方案勢在必行。(當然過去也考慮通過三級域名配置在負載均衡上來解決這些問題,但是這樣首先對于開發者來說不透明,其次也是一種比較僵化的設計方案,擴展和維護也有一定的難度)

                   在過去也嘗試過ApacheWeb容器自己的一些load balance特性,當然效果不是很好,和硬件基本無法比擬,而一些專有的“軟”負載均衡方案和開源項目也沒有深入的去了解,因此借著這次機會,好好深入的挖一挖“軟”負載均衡。

          “軟”負載均衡

                   作為互聯網應用,隨時都需要做好用戶量突然增大,訪問量突然上升的準備。今年熱門的詞匯“云”我就不多說了,這里就簡單說說服務器的橫向擴展。其實和DB,文件系統等一樣,當資源成為瓶頸的時候,就需要考慮如何通過擴展或者提升資源能力來滿足用戶的需求,這就是我們常說的橫向擴展和縱向擴展。(對于橫向擴展和縱向擴展的優劣大家應該都很清楚了,這里也不做贅述)橫向擴展中就會要求使用負載均衡的能力,如何根據資源能力不同以及資源在運行期負荷動態變化將負載合理分配是判斷負載均衡優劣的標準。

                   軟件負載均衡一般通過兩種方式來實現:基于操作系統的軟負載實現和基于第三方應用的軟負載實現。LVS就是基于Linux操作系統實現的一種軟負載,HA Proxy就是基于第三應用實現的軟負載。(后面會詳細介紹這兩種方式的使用)

                   最早期也是最原始的軟負載均衡:“Round Robin DNS”,通過輪詢方式在DNS綁定多個IP的情況下,將用戶對于同一個域名的請求分配到后端不同的服務節點。這種方案的優點:配置簡單,負載分配效率高。缺點:無法知曉后端服務節點服務情況(是否已經停止服務),無法保證在一個Session中多次請求由一個服務節點服務,每一個節點都要求有一個外網IP

                   另一種較為常見的就是基于分發器的Load balance。服務使用者通過向分發器發起請求獲得服務,分發器將請求分發給后端實際服務處理的節點,給客戶提供服務,最常說的反向代理模式就是典型的分發器Load Balance。這類負載均衡處理可以基于應用級轉發,也可以基于IP級別轉發,當然基于應用轉發效率和損耗比較大,同時分發器本身也會成為瓶頸。

          LVS Linux Virtual Server

                   LVS是在Linux操作系統基礎上建立虛擬服務器,實現服務節點之間的負載均衡。LVS主要是處理OSI模型中的4層消息包,根據一定的規則將請求直接轉發到后端的服務處理節點,有較高轉發效率。

                   Virtual ServerLoad Balancer和一組服務器的邏輯組合統稱,使用服務者只需要與Virtual Server進行交互就可以獲得高效的服務。真實服務器和Load Balancer通過高速LAN進行交互。Load Balancer能夠將請求分發到不同的服務端,在一個虛擬IP下并行處理多個請求。

          Virtual Server三種模式介紹

          Virtual Server有三種基于IP級別的負載均衡實現方式:IP address translationNAT)、Direct routingIP Tunneling

                   NAT(Network address translation)由于IPV4的某些缺陷和安全原因,某些網段例如(10.0.0.0/255.0.0.0, 172.16.0.0/255.240.0.0 and 192.168.0.0/255.255.0.0)不能被用于互聯網,因此常常被用作內部局域網,通過網絡地址翻譯的方式可以讓這些網段的服務器訪問互聯網或者被互聯網訪問。網絡地址翻譯主要作用就是將一組ip地址映射到其他的一組ip地址,當映射比例為1:1的時候通常稱作靜態映射,而當映射地址為M:N(M>N)的時候(M為被映射地址數量,通常是內部ip),則成為動態映射。而對于Virtual ServerNAT模式來說,就是利用了NAT的特性,將內部的一組服務器通過映射到一個虛擬的IP,然后以一個外網虛擬服務節點的身份對外提供服務。

                   上圖是一個實際的NAT范例,對外的服務IP202.103.106.5,內部建立了虛擬IP172.16.0.1,然后將內部其他兩臺實際服務的服務器172.16.0.2172.16.0.3映射到172.16.0.1這個虛擬IP。客戶端向202.103.106.5發起請求服務,Load Balancer查看請求數據包,如果是請求目標地址是注冊的虛擬IP及監聽端口的時候,那么通過NAT按照一定算法選擇某一臺實體服務器,再重寫報文目標地址,轉發請求到實際的目標服務器,當目標服務器處理完畢以后,將處理結果返回給Load Balancer,由Load Balancer修改源地址,返回給客戶端。

                   IP TunnelingIP管道技術是在IP報文上再次封裝IP報文協議的一種技術。允許將一個目標為AIP數據報文封裝成為目標為BIP數據報文,在特定的IP 管道中傳輸。

                   上圖就是IP Tunneling模式的運作原理。首先客戶端還是通過訪問對外的一個服務IP請求服務,當Load Balancer接受到請求以后,檢查VIP注冊信息,然后根據算法選擇實際的一臺后臺服務器,通過IP管道封裝技術對IP報文再次封裝,然后將消息通過IP管道轉發到實際的服務器,實際的服務器通過解包處理請求,然后根據包體內實際的服務請求地址,將處理結果直接返回給客戶端。

                   Direct routing利用Load Balancer和實際服務器共享同一VIP,簡單的通過修改消息報體目標MAC地址,轉發請求,然后再通過實際服務器配置VIP為本地回環,直接處理消息報文,而不再轉發,當處理完以后,直接將處理結果返回給客戶端。

           

                   上圖就是Direct Routing的運作流程,當外部請求到Load Balancer時,通過查找VIP注冊信息,直接選擇一臺后端服務器作為新的目標地址,修改消息報文中的目標地址Mac地址,轉發到目標服務器,目標服務器由于配置VIP在本地網卡回路中,因此直接處理消息,將處理完的結果直接返回給客戶端。

          Virtual Server三種模式的比較

                   下表是官方整理出的關于Virtual Server三種不同模式的區別:

          NAT

          TUNNEL

          DR

          服務器要求

          無要求

          需要支持IP管道

          arp組件(當前也有補丁)

          網絡要求

          Private

          LAN/WAN

          LAN

          可支持后端服務器節點數

          較少(10-20

          較多

          較多

          服務網關

          Load Balancer

          本身

          本身

          NAT:根據其實現原理,可以知道這種模式對于操作系統,網絡都沒有太多的要求和約束,但是由于消息需要打解包,同時消息的響應都必須經過Load Balancer,因此Load Balancer自身成為了瓶頸,這樣一個Load Balancer能夠支持的后端服務節點數量就有限了。當然可以采用混合模式來解決這個問題,也就是通過TUNNEL或者DR模式作為前端模式串聯起多個NAT模式Balancer

          TUNNEL:這種模式要求操作系統支持IP Tunnel,通過對IP報文再次封裝轉發,達到負載均衡的目的。設計這種模式的初衷是考慮,對于互聯網很多服務來說,服務請求數據量和返回數據量是不對稱的,返回的數據往往要遠遠大于請求的數據量,因此如果請求和返回都走Load Balancer會大量占用帶寬,影響處理能力。IP Tunnel設計中請求是通過Load Balancer,但是返回是直接返回到客戶端的,因此節省了返回的帶寬,提高了請求處理的能力。

          DR:這種模式要求Load Balancer和后端服務器處于同一個局域網段。DR模式處理消耗最小,消息轉發和回復基本沒有損耗,因此效率應該是最高的,但是約束是相對來說最多的。

          posted @ 2009-08-04 22:24 岑文初 閱讀(3392) | 評論 (2)編輯 收藏

              小A,30,所在公司在去年的經濟危機中沒有倒下,但是在今年卻倒下了。小A覺得能夠把一個公司混倒閉了,也算是人生的一點經歷。

              公司是沒了,但是工作還要繼續,生活還要繼續,現在將要面對一個新的環境,環境很陌生,但也比較熟悉,工作職責很清晰,但也充滿了挑戰。人過30,有了孩子,真的成熟了很多,知道了什么叫做責任感,知道了未來真的需要好好規劃,需要一個機會,需要一個平臺來找到自己,實現自己的價值,不讓這黃金時代就這么過去。

             小A將要面對的挑戰在心里面已經做好了準備,也有了自己的一套短期的規劃及工作安排,要成長有時候就要有壓力。在小A即將離開原來團隊的時候,和手下的一個同學發了火,因為在這陣子調整過程中,同學的心態一直變的很差,但是小A已經竭盡全力去分析他的未來,雖然聽進去,但是過幾天依然又開始放棄自己,這種態度讓小A原本很看好他發展的心情變得很沉重,最后就在那個探討會上說了他一些比較重的話,雖然說完以后自己也有些后悔,可能我對他和對我自己一樣,要求太高了吧,就像博士說的,如果對一個人沒有想法了,就恭維幾句即可,大家你好我好大家好,只有當對這個人還存在一定的期望的時候才會表現出這種比較急切的感覺。

             新的開始,新的挑戰,新的環境,新的機遇,新的難題,新的稱呼

             好的心態,好的溝通,好的未來

             一切都需要小A用自己的能力去證明,走自己的路,讓自己走的更好。

          posted @ 2009-08-03 09:58 岑文初 閱讀(882) | 評論 (0)編輯 收藏

              轉眼到了7月份了,今年的blog更新的很慢很慢。寫點東西記錄自己的生活和工作狀態。
             生活:
             兒子提早10天在六月八號來到我們這個小家庭,每個好友在祝福我的同時告訴我,辛苦的日子剛剛開始。不過和大家的感覺一樣,辛苦但快樂著,在別人忙著在互聯網上種花種草,養豬養雞的時候,我開始扛起培養祖國新一代的責任。睡覺基本上很難保證連續性,早晨的運動也移到了晚上給兒子洗好澡以后。以前覺得就算到30歲還是覺得自己比較年輕,但是在那個23:25分兒子出來的一瞬間,自己覺得自己真的老了,需要成熟一點了,對兒子,對老婆。

              工作:
              其實今年年初的時候就有些彷徨,自己一手培養出來的SIP和原來的目標漸行漸遠,7月份我在產品會議上提出了SIP6(第一階段最終版),功能,性能,可擴展性都能夠滿足到明年中旬。雖然日訪問量就快突破1億,年底可能會到幾個億,但是這些數字對我來說只能證明這個架構還可以,但是SIP原有的目標已經被拋棄,成為了一個內部的服務集成平臺。
             下個階段會在做一些中心來滿足團隊的需要,但在我看來其實這些東西對我對團隊的價值有限,創新有限,但這就是工作。
              公司內部有些變化,當然是好是壞不得而知,不過作為我們這些level已經處于地面的人來說也沒啥影響。

             文章:
             最近的文章素材其實不少,但是受到內部技術專利申請,外部投稿的影響,能夠寫出來直接貼的越來越少,有時候也是這樣,分享固然好,但是有些時候有些東西只能夠小范圍分享。

             睡覺,睡覺,中午的休息是很寶貴的,一覺醒來還繼續自己的路。(走自己的路,讓自己無路可走。沒寫錯,呵呵,覺得這樣挺搞笑的)
          posted @ 2009-07-09 12:38 岑文初 閱讀(752) | 評論 (0)編輯 收藏

           

                   這篇blog的問題不能算是解決,僅僅只是一種分析和猜測,后續的一些行動可能會證明一些猜想,也可能什么都解決不了。如果有和我相同情況的同學,也知道是什么問題造成的,請不吝賜教。

          問題:

          上周周末,沒有和同事們出去Outing,在家管孩子,去生產環境觀察了一下集群機器的當前運行狀態,發現應用在這些多核機器上壓力極端不均勻。

                   Top一下大致狀態如下:



                   峰值的時候,單CPU的使用率都到了80%,這種情況對于多核服務器來說是很不正常的使用。對于Java的開發者來說,多線程編程是無法控制線程如何在CPU上分配的,因為Java本身不實現線程機制,說是跨平臺的語言,但是性能及特性會根據操作系統的實現有很大的差異,因此Java調優有時候需要對系統配置甚至內核作調優。

          分析:

                   首先在測試環境下作了多次同樣的壓力測試,嘗試了與線上一樣的操作系統版本,相似的配置,但測試結果卻是負載分配很均勻。

             
               

                   此時重新啟動了一臺問題機器,發現負載降下來了,同時也很均衡,也就是說在當前的壓力下不應該有這樣高的cpu消耗,同時也排除了硬件或者操作系統的一些配置問題。

                   CPU滿負荷的情況下,很多時候會認為應該是循環造成的,對于單個CPU的消耗更是。通過Top H查看具體到底哪一個線程會長時間消耗CPU

                   可以看到PID13659的線程是“罪魁禍首”,但13659究竟在干什么,是應用的線程還是系統的線程,是否是陷入了死循環,不得而知。接著就按照Java的土辦法,Kill -3 pid,然后看看輸出日志。

                   根據線程號來查找dump出來的日志中nid,發現這個線程是VM Thread,也就是虛擬機線程。(這里作一下轉換,將13659轉換成為16進制就是0x355b



                   pstack看了一下這個線程的工作,結果如下:

          Thread 2074 (Thread 1846541216 (LWP 13659)):

          #0 0x0659fa65 in ObjectSynchronizer::deflate_idle_monitors ()

          #1 0x065606e5 in SafepointSynchronize::begin ()

          #2 0x06613e83 in VMThread::loop ()

          #3 0x06613a6f in VMThread::run ()

          #4 0x06506709 in java_start ()

          #5 0x00aae3cc in start_thread () from /lib/tls/libpthread.so.0

          #6 0x00a1896e in clone () from /lib/tls/libc.so.6

                   搜索了一下ObjectSynchronizer::deflate_idle_monitors,發現了sunbug庫中有bug關于jdk1.6中由于這個方法導致運行期問題的說法:http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=803cb2d95886bffffffff9a626d3b9b28573?bug_id=6781744

                   然后就直接去openjdk官方網站去查找這個類的代碼,大致了解一下他的作用,具體的代碼鏈接如下:http://xref.jsecurity.net/openjdk-6/langtools/db/d8b/synchronizer_8cpp-source.html
          主要工作應該是對資源對象的回收,在加上pstack的結果,應該大致知道是對線程資源的管理。但具體代碼就沒有進一步分析了。

          接著就分析一下自己的應用:

                   壓力測試(高強度、長時間)都做過,沒有發現什么異常。

                   本身應用是否會存在的缺陷導致問題呢。有人說VM Thread兼顧著GC的工作,因此內存泄露,對象長期積壓過多也可能影響,但其實在dump的結果可以看到,GC有單獨的工作線程,同時我也觀察到GC這些線程的工作時間長度,因此由于GC繁忙導致CPU上去,基本上來說可以排除。

                   其次在SIP項目中使用了JDK的線程池(ExecutorService)LinkedBlockingQueue。后者以前的文章里面提到在1.5版本里使用poll方法會有內存泄露,到1.6雖然沒有內存泄露,但是臨時鎖對象增長的很快,會導致GC的頻度增加。

          行動:

                   上面零零散散的一些分析,最終讓我決定有如下的行動:

          1.       升級某一臺服務器的JDK,當前是1.6.0_10-b33,打算升級到1.614版本。比較觀察多臺機器的表現,看是否升級了JDK可以解決問題。

          2.       去除LinkedBlockingQueue作為消息隊列,直接由生產者將生產結果按照算法分配給消費者線程,避免競爭,鎖的消耗,同時也防止LinkedBlockingQueue帶來的資源消耗。

          3.       測試環境繼續作長時間的壓力測試,同時可以結合Jprofile之類的工具來分析長時間后可能出現的問題。

          后話:

                   這年頭真的啥都要學一點,求人不如求己。

          SA,DBA,測試都需要能夠去學習一些,起碼在初期排查問題上自己能夠做點啥,要不然別人也忙,自己又無從下手。就好比這次壓力測試好不容易排上隊,但是還是滿足不了及時上線的需求,因此自己去LoadRunner壓,好歹給出一個零時的報告先大家看著。應用的異常有時候是應用本身設計問題,也可能是開發語言的問題,也可能是操作系統的問題,因此要去定位這種比較復雜的問題,真的需要有耐心去好好的學習各種知識,現在看來知識還是匱乏啊,要不然就可以分析出openjdk中可能存在的問題。

          posted @ 2009-07-09 11:59 岑文初 閱讀(4427) | 評論 (3)編輯 收藏

           

                   昨天在看Cache Client代碼的時候,發現在從資源池中獲取SocketIO部分代碼在高并發情況下效率不高,因此考慮通過一些變通的方式來提高效率,下面說的內容僅僅是當前自己琢磨出來可以部分提高效率的方法,希望看了這篇文章的同學能夠有更好的方式或者算法來提高效率。

          情景:

                 Cache Client SocketIO資源池是一個兩級的Map,具體定義為:ConcurrentMap<String, ConcurrentMap<SockIO, Integer>>。第一級MapHost作為Key,第二級MapSockIO本身作為Key,三種SockIO狀態(可用,占用,廢棄)作為value。之所以采用一個Pool來存儲三種狀態主要是考慮到在高并發下,多個池之間保持原子性的復雜。

          每一次獲取可用的SocketIO的操作需要經歷:1.遍歷Host所在的Map2.逐個比較狀態。3.原子方法獲取可用SocketIO。(并發問題所要求的,具體代碼可以下載:http://memcache-client-forjava.googlecode.com/files/alisoft-xplatform-asf-cache-2.5.1-src.jar )。

          在修改過去的版本里面,首先遍歷的過程是一個固定順序的過程(keyset),這樣會導致在高并發的情況下,越來越多的資源申請命中率會下降,因為壓力總是落在keyset靠前的那些SockIO上(重復比較)。需要考慮通過什么手段可以提高在高并發下的申請命中率。

          思考:

          1. 資源申請的越早,被釋放的可能性越高,因此是否可以考慮采用更新SockIO最后申請時間來作為后續申請的初步依據。(本身復雜度帶來的耗時可能會超過命中率降低帶來的損耗)

          2. 采用隨機數的方式來確定keyset的起始游標,也就不是每次都從keyset第一位開始(可以把keyset看作一個首尾相接的數組)。

          3. 在每次資源回收的時候紀錄下該資源為可用(當前為每一個Host就記錄一個可能可用的資源,簡單化操作),作為申請的首選嘗試。(嘗試不成功在去遍歷)。

          當前實現了2,3組合,發現效果明顯,在500個并發下,每個線程200次操作(一系列動作),壓力測試結果如下:

          Cache test consume(cache測試總共耗時)average boundle consume(每個線程總耗時),average per request(每個線程每次操作總耗時)

          沒有作任何改動以前的測試結果:

          cache test consume: 11507741, average boundle consume: 57538, average per request :115

          采用了2策略以后的測試結果:

          cache test consume: 10270512, average boundle consume: 51352, average per request :102

          采用了23策略以后的測試結果:

          cache test consume: 9140660, average boundle consume: 45703, average per request :91

          posted @ 2009-05-07 17:15 岑文初 閱讀(1962) | 評論 (0)編輯 收藏

           

                 服務集成平臺5.6的性能測試進入尾聲,這期的優化也算告一段落。這次主要的優化工作還是在三個方面:應用服務器(Apache,JBoss)配置,業務流程,Cache Client包(http://code.google.com/p/memcache-client-forjava/ )。這里把過去和這次優化對于Cache的使用作一個經驗分享,希望大家能夠用好Cache,提速你的應用。

                 這里還是通過一些點滴的啟示來介紹優化的一些心得,很多時候還是要根據具體情況來判斷如何去具體實施,因此這里所說的僅僅是在一些場景下適用,并非放之四海皆準的教條。同時也希望看此文的各位同學,如果有更好的思路可以給我反饋,技術在交流中才會有發展。

          積少成多,集腋成裘

                 性能提不上去,多半是在一些容易成為瓶頸的“暗點”(IO,帶寬,連接數,資源競爭等等)。Memcached Cache現在已經被大家廣泛使用,但是千萬不要認為對Cache的操作是低損耗的,要知道這類集中式CacheSocket連接數(會牽涉到linux操作系統文件句柄可用數),帶寬,網絡IO都是有要求的,有要求就意味著會有損失,因此積少成多,集腋成裘。服務集成平臺是一個高速的服務路由器,其大部分的業務數據,訪問控制策略,安全策略以及對應的一些控制閥值被緩存在Cache服務端,因此對于Cache的依賴性很強。每一次對于客戶端的性能提升,總會給服務集成平臺性能帶來不小的影響,但是每一次優化速度后,客戶端可以優化的空間越來越小,這時候需要一些策略來配合,提升應用整體性能。當前主要采用了以下幾點策略:

          1.  從數據獲取角度來做優化,采用本地數據緩存。(因為大家的應用需要能夠線形擴展,支持集群,所以才不使用應用服務器本地緩存,但是在某些緩存數據時間性不敏感或者修改幾率較小的情況下,可以采用本地緩存結合集中式緩存,減少對遠端服務器訪問次數,提升應用性能)。

          Cache ClientIMemcachedCache 接口中的public Object get(String key,int localTTL)方法就是本地數據緩存結合遠程Cache獲取數據的接口。具體流程參看下圖:

           

           

          2.  從數據更新角度,采用異步數據更新。(即不等待數據更新結果,直接進行其他業務流程)。這類操作使用場景比較局限,首先數據不會用作判斷(特別是高并發系統中的閥值),其次不需要返回結果作為后續流程處理輸入(例如計數器),時時性要求比較低。(這類操作其實是采用了集群數據傳播的一種策略,原先對于集群中所有節點都想即時傳播到,但是這樣對于性能損失很大,因此采用key對應的主Node采用即時設置數據,其他的通過后臺任務數據傳播來實現,由于key對應的主Node是數據第一操作和讀取節點,因此這類數據傳播操作時時性要求較低,適合這樣處理)。具體接口參見Cache Client 使用文檔。

          3.  一次獲取,多次使用。這點和系統設計有關,當前服務集成平臺的安全流程是鏈狀的,一次請求會經歷很多安全攔截器,而在每一個安全攔截器中會根據情況獲取具體的業務數據或者流程控制策略等緩存數據,每一個安全攔截器都是彼此獨立的,在很早以前是每一個安全攔截器各自在需要數據的時候去遠程獲取,但是壓力測試下來發現請求次數相當多,而且好些重復獲取,因此將這些業務數據作為上下文在鏈式檢查中傳遞,按需獲取和設置,最大程度上復用了數據。(其實也是一種減少數據獲取的方式)。

          4.  規劃好你的Cache區。有些同學在使用Cache的時候問我是否有什么需要注意的,我覺得在使用Cache之前,針對需要緩存的數據需要做好規劃。那些數據需要放在一個Cache虛擬節點上,那些數據必須分開放。一方面是根據自己業務系統的數據耦合程度(未來系統是否需要合并或者拆分),另一方面根據數據量及讀寫頻繁度來合理分配(畢竟網絡IO還是稀缺資源)。當然有時候業務系統設計者自己也不知道未來的發展,那么最簡單的方式給Key加上前綴,當前可以合并,未來也可以拆分。同時數據粒度也需要考慮,粒度設計太小,那么交互頻繁度就會很高,如果粒度太大,那么網絡流量就會很大,同時將來業務模塊拆分就會有問題。

           

           

          巧用Memcached Cache特有接口

                 Memcached Cache提供了計數器一整套接口和addreplace兩個接口。這些特有接口可以很好的滿足一些應用的高并發性處理需求。例如對于資源訪問次數控制,采用Cache的計數器接口就可以實現在集群中的數量控制,原本通過Cachegetput是無法解決并發問題的(就算是本地緩存一樣),這就是一組原子操作的接口。而AddReplace可以滿足無需通過get方法獲取內容,就可以對于key是否存在的不同情況作出相應處理,也是一種原子性操作。這些原子操作接口對于高并發系統在集群中的設計會很有幫助。

           

          Cache Client Cluster

                 Memcached Cache是集中式Cache,它僅僅是支持將數據能夠分片分區的存儲到一臺或者多臺的Cache Server實例中,但是這些數據并沒有作冗余,因此任何一個服務實例不可用,都會導致部分緩存數據丟失。當然很多人采取持久化等方式來保證數據的完整性,但是這種方式對于效率以及恢復的復雜性都會有影響。

                 簡單的來想,為什么不把數據在多保存一份或者多份呢,當其中一份不可用的情況下,就用另外一份補上。這就是最原始的Cache Client Cluster的構想。在這里具體的設計細節就不多說了,主要說一下幾個要點,也讓使用Cache Client Cluster的同學有大致的一個了解。

                 先來看看Cache Cluster的結構圖:




                 這張圖上需要注意四個角色:Application(使用Cache的應用),Cache ClusterCache配置的虛擬集群),Cache NodeCache的虛擬節點,在同一個Cluster中的Cache Node數據保持完全一致),Cache InstanceCache虛擬節點中實際包含的Memcached Cache服務端實例)。

                 應用僅僅操作Cache Node,不了解具體數據存儲或數據獲取是操作哪一個Cache 服務端實例。(這點也就是Memcached Cache可擴展性的基礎設計)。Cache Cluster又將多個Cache Node組成了虛擬的集群,通過數據冗余,保證了服務可用性和數據完整性。

           

                 當前 Cache Client Cluster主要有兩種配置模式:active standby。(這里是借鑒了硬件的名詞,其實并不完全一樣,因為還是考慮到了效率問題)

                 Cache Client Cluster主要的功能點:

          1.  容錯。當被分配到讀取或者操作數據的Cache虛擬節點不可用的情況下,集群其他節點支持代替錯誤節點服務于客戶端應用。

          2.  數據冗余。當操作集群中某一個Cache虛擬節點時,數據會異步傳播到其他集群節點。

          3.  軟負載。客戶端通過對操作的key作算法(當前采用簡單的key hash再取余的方式)選擇集群中的節點,達到集群中節點簡單的負載分擔。同時也由于這種模式,可以使得key都有默認的第一操作節點,此節點的操作保持時時更新,而其他節點可以通過客戶端異步更新來實現效率提升。

          4.  數據恢復。當集群中某一節點失效后恢復時,其數據可能已經完全丟失,此時通過配置成為Active模式可以將其他節點上冗余的數據Lazy復制到該節點(獲取一個復制一個,同時只支持一個冗余節點的數據獲取(不采取遍歷,防止低效))。

           

          Active模式擁有1,2,3,4的特性。Standby模式擁用1,2,3特性。(其實本來只考慮讓Standby擁有1特性)。未來不排除還會有更多需要的特性加入。Activekey不存在的情況下會有些低效,因為會判斷一個冗余節點是否存在內容,然后決定是否修復當前節點。(考慮采用短期失敗標示之類的,不過效率不一定高,同時增加了復雜度)

           

           

          運行期動態擴容部署

                 Memcached cache客戶端算法中比較出名的是Consistent Hashing算法,其目的也就是為了在節點增加或者減少以后,通過算法盡量減小數據重新分布的代價。采用虛擬節點,環狀和二叉樹等方式可以部分降低節點增加和減少對于數據分布的影響,但是始終還是有部分數據會失效,這點還是由于Memcached Cache是集中式Cache所決定的。

                 但如果有了Cache Cluster的話,數據有了冗余,就可以通過逐步修改集群中虛擬節點配置,達到對于單個虛擬節點的配置動態擴容。

                 支持動態部署前提:

          配置文件動態加載。(配置文件可以在Classpath中,也可以是Http資源的方式)通過Cache Client Cache Manager可以停止Cache 服務,重新加載配置文件,即時生效。

          當前動態部署的兩種方式:

          1.              修改集群配置中某一套虛擬節點的服務實例配置(socketPool配置),增加或者減少后端數據存儲實例。然后動態加載新的配置文件(可以通過指定遠端的http配置作為新的配置文件),通過集群的lazy的修復方式,逐漸的將數據從冗余節點復制到新的節點上來,最終實現數據遷移。

          2.              修改集群配置中某一套虛擬節點的服務實例配置(socketPool配置),增加或者減少后端數據存儲實例。然后動態加載新的配置文件(可以通過指定遠端的http配置作為新的配置文件),在調用Cache Manager主動將數據由某一虛擬節點復制到指定的集群中,實現數據批量遷移,然后根據需要看是否需要修改其他幾套虛擬節點配置。

           

          存在的問題:

          1.       當前沒有做到不停止服務來動態部署。(后續考慮實現,當前將編譯配置和重新啟動服務器的工作節省了)

          2.       不論是lazy復制還是批量數據遷移,都是會將原本有失效時間的數據變成了無失效時間的數據。(這個問題暫時還沒有一種可行的高效的方式解決)

           

           

          后話

                 性能優化這點事還是那句老話,需要了再去做也不遲。同時如果你開發的是一個每天服務訪問量都是上億,甚至更高的系統,那么有時候斤斤計較會收獲不少。(當然是不影響系統本身業務流程的基礎)。

                 Cache客戶端自從作為開源放在Google上也收到了不少朋友的支持和反饋,同時自己業務系統以及其他部門同學的使用促使我不斷的去優化和滿足必要的一些功能擴展(但是對于Cache來說,還是那句話,簡單就是美,高效是使用Cache的最原始的需求)。

                 當前Cache Client版本已經到了2.5版本,在Google上有詳細的Demo(單元測試,壓力測試,集群測試)和說明使用文檔。是否速度會慢于其他Memcached客戶端,這不好說的很絕對,反正大家自己拉下去比較一下看看就知道了,當然為了集群和其他的一些必要的附加功能還是做了一些性能犧牲。

           

          項目地址在:http://code.google.com/p/memcache-client-forjava/

          在首頁的右側有demo,doc,binary,src的鏈接,直接可以下載使用和察看。希望對需要的同學有幫助。

          posted @ 2009-04-28 23:19 岑文初 閱讀(3381) | 評論 (6)編輯 收藏

          僅列出標題
          共12頁: First 上一頁 3 4 5 6 7 8 9 10 11 下一頁 Last 
          主站蜘蛛池模板: 长沙县| 安国市| 乌鲁木齐县| 福泉市| 普定县| 齐齐哈尔市| 福安市| 东安县| 桐梓县| 沧源| 东宁县| 常州市| 福清市| 泰兴市| 武夷山市| 湖口县| 郯城县| 乌海市| 珲春市| 彩票| 甘谷县| 松滋市| 嵊泗县| 青田县| 鲜城| 登封市| 伊金霍洛旗| 周宁县| 噶尔县| 开封县| 萨嘎县| 咸宁市| 文山县| 集贤县| 浠水县| 赤水市| 湄潭县| 康定县| 大姚县| 乌什县| 鄂温|