第一部分昨天一個新同事向我問起了Push Mail的解決方案的整體架構(gòu)和思路,滔滔不絕的講完以后,勾起了我不少的回憶。那是在3年前發(fā)生的事情,當(dāng)時這個客戶(美國人)的需求就是一句話:“我要做一個Push Mail全套解決方案。” 就是這句話我們寫了厚厚的一份英文需求文檔。從需求分析到最后交付我們將盡用了2年左右的時間,從 系統(tǒng)架構(gòu)、程序發(fā)開、再到系統(tǒng)重構(gòu)、這樣的經(jīng)歷依然 歷歷在目。 項(xiàng)目當(dāng)時就我們5個人在做,可以說這5個人都是百里挑一的人選,但我們需要面對以下挑戰(zhàn): 但是再我們所有成員的不斷努力下,這些困難都被我們一一解決。 項(xiàng)目里面牽涉打了J2EE 領(lǐng)域多項(xiàng)技術(shù),也算是一個難點(diǎn)吧,因?yàn)橄铝屑夹g(shù)跨度都比較大,例如: 客戶全部選擇了將服務(wù)器部署在Amazon云環(huán)境上,大約總共有40幾臺。其中數(shù)據(jù)庫采用了MySQL服務(wù)器,我們運(yùn)用分庫+同步技術(shù)來解決大規(guī)模存儲和查詢,應(yīng)用服務(wù)器我們采用了Jboss。 MQ服務(wù)器采用的是Jboss的MQ。前端采用Apache和CDN做請求壓力分載。操作系統(tǒng)采用64位的 Ubuntu 8。
第二部分這個 Push Mail 項(xiàng)目留給我最深的影響就是給我們團(tuán)隊(duì)來了豐厚的利潤,客戶他是一個美籍印度佬,就是我們常說的那種有錢人,做事爽快、干脆,也是全球移動領(lǐng)域具有影響的專家,因此他要求我們提供的服務(wù)必須是具有一個國際化專業(yè)水準(zhǔn)的團(tuán)隊(duì)(International Corporate)。所謂專業(yè)化的主要需要體現(xiàn)在 1執(zhí)行規(guī)范、2執(zhí)行效率、3執(zhí)行細(xì)節(jié) 這3個重要的環(huán)節(jié)上。 在項(xiàng)目實(shí)施過程中除了搞J2EE 的開發(fā)者, TA、QA 、SA、DBA 一個也不能少。 2、QA 測試團(tuán)隊(duì)在我們需求和概要設(shè)計(jì) 就開始對jboss和mysql其他幾項(xiàng)技術(shù)學(xué)習(xí),其中測試人員與我們一同參與需求分析,這樣將來他們才知道該如何配合我們做各種測試,進(jìn)行深入的測試,而不是我們在引導(dǎo)他們在測試,他們100%能知曉業(yè)務(wù) 并且制定出不同的測試計(jì)劃。并不是依靠我們自己測試或者我們在指導(dǎo)他們測試,那樣運(yùn)動員和裁判員都是同一人,那樣肯定出問題。 3、SA 的壓力最大 需要對系統(tǒng)整體的架構(gòu)進(jìn)行設(shè)計(jì)這個都是分內(nèi)的事情,更重要的 在真實(shí)生產(chǎn)的環(huán)境遇到致命性錯誤,可以回退或者拿出現(xiàn)成的備份方案,把問題在短時間內(nèi)化解。 4、DBA 需要從高往低的系統(tǒng)架構(gòu)層次進(jìn)行對數(shù)據(jù)庫設(shè)計(jì)與整體規(guī)劃,必須根據(jù)客戶需求設(shè)計(jì)出具有遠(yuǎn)景的 方案,不是一成不變,更不是所謂“一步到位”的規(guī)劃設(shè)計(jì),是根據(jù)預(yù)計(jì)的數(shù)據(jù)增長 進(jìn)行實(shí)施規(guī)劃的不同方案。 5、開發(fā)者們需要對每個業(yè)務(wù)模塊都要詳細(xì)了解。因?yàn)槲覀冃枰档惋L(fēng)險 開發(fā)者們?nèi)绻霈F(xiàn)有人家里有事或者生病 任何一個成員都可以替代,不會出現(xiàn)我今天不來上班,導(dǎo)致項(xiàng)目進(jìn)度拖慢一天的現(xiàn)象。 在產(chǎn)品在設(shè)計(jì)開發(fā)到發(fā)布的過程中,我們分為四個階段 prototype、demo、stage、producting。 prototype 是一個原型,主要完成核心的部分,完成核心的功能和業(yè)務(wù)邏輯,開發(fā)團(tuán)隊(duì)內(nèi)部評估使用。 demo 階段是將產(chǎn)品的主要部分演示給客戶看,讓客戶確認(rèn)主體的方向。 stage 根據(jù)項(xiàng)目計(jì)劃分為多個不同的stage版本,每個stage階段的版本都會在stage服務(wù)器上由我們 測試人員先測試5-7天,再發(fā)布到真實(shí)的生產(chǎn)環(huán)境中??蛻魧@樣的流程要求的非常的嚴(yán)格。因此 stage 服務(wù)器的配置和數(shù)量與 producting 環(huán)境是100%相同的,沒有他們的郵件確認(rèn)我們是不能擅自發(fā)布到 producting 環(huán)境中的,如果 producting 環(huán)境出現(xiàn)問題,必須在短時間內(nèi)能回歸到上一個穩(wěn)定版本的狀態(tài) 。 后期會在 stage 和 producting 服務(wù)器上輪回 ,fix –> testing —> release。 我們當(dāng)時使用SVN和Trac,值得一提的是Trac這個東西,客戶有任何需求變更 通過 Trac 系統(tǒng) TA,QA,DBA,SA 統(tǒng)統(tǒng)都會知道,并且知道我們會在下個版本 什么時候 會 發(fā)布在stage 服務(wù)器上,我們也能在第一時間知道他們對 當(dāng)前版本的 性能情況,客戶也能看見但似乎他們并不在意這個結(jié)果,因?yàn)樗麄冃枰牢覀儺?dāng)前的執(zhí)行狀態(tài)是否符合計(jì)劃,其實(shí)TA的成員比他們更加關(guān)注我們的項(xiàng)目進(jìn)度,呵呵。因此,所有人的開發(fā)進(jìn)度執(zhí)行情況都在trac上進(jìn)行展現(xiàn)??蛻粢部梢钥匆?,也可以回復(fù),所有信息所有人同步。 呵呵,另外那三十幾臺需要發(fā)布應(yīng)用程序的機(jī)器,分別發(fā)布不同的應(yīng)用程序或者不同的版本不可能完全依靠人工完成,我們需要一個半自動化的工具幫助我們完成,所以我們選擇了hudson和自己編寫的liunx腳本。這樣可以提供效率,并且大大減少了發(fā)布時出錯的機(jī)率。 先寫這么多,有什么忘記的地方我回頭補(bǔ)上,下一篇將開始 講述 純 技術(shù)方面的那點(diǎn)事兒了。 第三部分
自從1998年 Google 利用廉價的互聯(lián)網(wǎng)計(jì)算機(jī),以最快的速度提供最精確的搜索結(jié)果, 這一創(chuàng)新技術(shù)成功地縮短了響應(yīng)時間,提高了可擴(kuò)展性,并降低了成本。是當(dāng)今眾多公司一直在效仿的技術(shù)。在這一項(xiàng)目中完全采用低廉的硬件投入,期望能通過軟件的手段、利用分布式計(jì)算、集群技術(shù) 達(dá)到高效的計(jì)算,并且能加強(qiáng)系統(tǒng)的可擴(kuò)展性,提高系統(tǒng)軟硬件資源的使用率, 降低系統(tǒng)運(yùn)行中瞬間的瓶頸。
通過這個項(xiàng)目讓我們充分的認(rèn)識到一個用戶的系統(tǒng) 例如:單用戶的 OutLook 和 一個百萬級的系統(tǒng)的是截然不同的,系統(tǒng)中僅有100條數(shù)據(jù)和100w條數(shù)據(jù)的系統(tǒng)更是截然不同的,從100w條數(shù)據(jù)上升到上億條數(shù)據(jù)那樣的系統(tǒng)更會讓人感受到無論從代碼結(jié)構(gòu)、數(shù)據(jù)庫設(shè)計(jì)還是從系統(tǒng)架構(gòu)都是完全不同的設(shè)計(jì)。 客戶端環(huán)境 服務(wù)器端環(huán)境 壓力測試工具 當(dāng)前運(yùn)行狀態(tài) 整體架構(gòu) 概覽 后端發(fā)送郵件實(shí)現(xiàn)過程 1.手機(jī)客戶端通過http網(wǎng)絡(luò)協(xié)議發(fā)送XML數(shù)據(jù)到服務(wù)器端, 2.服務(wù)器端接收到xml數(shù)據(jù)進(jìn)行解析,服務(wù)器端傳輸層的web請求模塊將xml 協(xié)議解析,并且重新包裝成pojo 對象, 3.中間有一個業(yè)務(wù)模塊分發(fā)器將 獲得pojo對象交給不同的業(yè)務(wù)模塊進(jìn)行處理,如:DAL層、消息中間件, 4.將處理完成的業(yè)務(wù)通過業(yè)務(wù)模塊分發(fā)器包裝成xml報文回送給客戶端。 整個業(yè)務(wù)處理組成部分如圖所示:
內(nèi)部業(yè)務(wù)邏輯 1.定時器從數(shù)據(jù)庫裝載帳戶,采用多線程實(shí)現(xiàn)一個線程池,我們稱這個玩意兒叫做任務(wù)工廠, 2.定時向JMS服務(wù)器中不同的消息隊(duì)列發(fā)送消息 ,消息接收端收到消息后驅(qū)動業(yè)務(wù)模塊去 SP Mail Server 收取郵件, 3.收郵件模塊 上SP Mail Server 獲取郵件列表頭信息,并且和數(shù)據(jù)庫中已存在的郵件列表頭信息進(jìn)行新郵件比對, 4.收取新郵件并且將郵件信息保存到數(shù)據(jù)庫或者緩存,當(dāng)用戶需要讀取的時候?qū)南到y(tǒng)的數(shù)據(jù)庫或者緩存中讀取, 5.保存完畢后,將通過IP Push 或者 SMS Push 技術(shù) 通知用戶上服務(wù)器獲得新郵件。 后端內(nèi)部架構(gòu) Web層 任務(wù)調(diào)度 BTW:任務(wù)工廠模塊最開始在demo的時候采用Quartz 放入Spring微容器中進(jìn)行集群,因?yàn)椴荒軓木彺嬷兄苯幼x取,將來系統(tǒng)賬戶會越來越多,導(dǎo)致數(shù)據(jù)庫那邊的壓力越來越大,所以后期我們用 線程池+oscache集群技術(shù) 自己開發(fā)了一套類似 Quartz+spring集群的方案。另外,這個項(xiàng)目發(fā)生在沒有Memcached的年代,如果當(dāng)時使用Memcached也許設(shè)計(jì)上會更加完美些。 分布式應(yīng)用 EJB消息驅(qū)動Bean /JMS 消息系統(tǒng) 數(shù)據(jù)庫 分片(sharding) 分布式文件系統(tǒng)(DFS) JavaMail
經(jīng)驗(yàn)與教訓(xùn) 1.HAProxy的擴(kuò)展使用,不僅僅可以使用在Web方面,還可以使用到其他應(yīng)用層,進(jìn)行壓力分鐘, 例如,可以應(yīng)用到 數(shù)據(jù)MySQL??梢詤⒖歼@篇文章,http://www./blog/2009/08/10/using-haproxy-for-mysql-failover-and-redundancy 2.JVM的優(yōu)化是任何大型J2EE項(xiàng)目中必不可少的話題,當(dāng)然并不是你把JVM的內(nèi)存使用空間設(shè)置的越大越好,SUN的官方網(wǎng)站已經(jīng)指出,不同的操作系統(tǒng),不同的應(yīng)用,建議你的JVM內(nèi)存分配大小是不同的。另外,對與不同的JVM也有不同的參數(shù)配置,通常的JVM配置參數(shù)可以參見這里,http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html 3.Linux系統(tǒng)上的swap 空間,4G和4G內(nèi)存 以內(nèi)的機(jī)器還是非常有必要使用swap空間的,有一次有一個應(yīng)用服務(wù)器系統(tǒng)down機(jī),花了很久的時間才發(fā)現(xiàn),居然是忘記建立Swap空間,多么簡單的問題啊,可是把我們折磨了3個星期,3個星期里被老板和客戶罵的慘不忍睹,血的教訓(xùn),讓我們再也不會忘記小內(nèi)存機(jī)器建立swap空間了。 4.Jboss MQ的抱怨,首先聲明我不是在給Apache 的JMS做廣告,因?yàn)镴bossMQ實(shí)在是不好用,而且性能也不咋地,我看見有一篇文章說到JbossMQ的性能在同類產(chǎn)品中是最好的,不知道結(jié)果是怎么來的,還是建議大家還是使用Apache的JMS,文檔全面啊,不懂就可以找到很全面的資料,jboss MQ 資料的支持不多。 5.MySQL的優(yōu)化,MySQL的一些參數(shù)調(diào)優(yōu)就不說了,但使用MySQL 插件以后給我們帶來了不少性能上的提升,特別是在數(shù)據(jù)查詢上的瓶頸可以得到不少緩解。 6.MySQL集群,這玩意兒是個不錯的解決方案,可是沒有足夠的內(nèi)存是玩不起的,因?yàn)镸ySQL的集群因?yàn)橥耆蕾噧?nèi)存,另外對表的字段也有特別的限制,用起來有點(diǎn)不太自然,不支持所有大字段的類型。如果是老系統(tǒng)遷移過來,估計(jì)要折騰一段時間才能合用。 7.JMS 消息的使用,不需要放入數(shù)據(jù)庫,將消息內(nèi)存當(dāng)中,并且對JVM運(yùn)行參數(shù)進(jìn)行優(yōu)化 ,對與客戶端的代碼也需要進(jìn)行優(yōu)化,關(guān)閉消息id (setDisableMessageID),減少消息的大小并且 省去了創(chuàng)建唯一ID的時間。關(guān)閉消息的時間戳。如果不需要時間戳,用MessageProducer的setDisableMessageTimeStamp()方法將其關(guān)閉。避免使用AUTO_ACKNOWLEDGE。 AUTO_ACKNOWLEDGE 使得每收到一個消息就要向服務(wù)器發(fā)送一個通知--這樣增加的網(wǎng)絡(luò)傳輸?shù)呢?fù)擔(dān)。如果可能,盡量使用 DUPS_OK_ACKNOWLEDGE或者CLIENT_ACKNOWLEDGE?;蛘呤褂檬聞?wù)性會話,將通知在提交時批量完成。 |
|
|