目前網站架構通常分紅網頁緩存層、負載均衡層、 WEB層和數據庫層,我其實通常還會多加一層,即文件服務器層,這樣咱們在後面的討論過程當中,咱們能夠依次用這五層對網站架構來進行討論。html
網頁緩存層 首先說下這個網頁緩存層,好比CDN租賃(效果比公司本身部署Squid/Varnish要好,他們專業,價格低廉,好比快網/CC等(價格80元/M/月不到)並且覆蓋的城市更多),本身架設squid/Varnish是次選。另外,不少朋友喜歡嘗試自建CDN,這個是一個比較吃力不討好的活兒,未必能達到預期目標,這塊系統架構師在架設網站初期就有規劃好,不要等到網站流量及壓力巨大時纔去規劃。事實上,這一層有不少優 秀的開源軟件都能勝利,好比傳統的Squid Cache,另外,後起之秀Nginx和Varnish由於性能優異,愈來愈多的朋友嘗試在本身的網站使用他們做爲本身的網頁緩存,事實上,Nginx已經具有Squid所擁有的Web緩存加速功能,此外,Nginx對多核CPU的利用,賽過Squid很多,如今愈來愈來的架構師都喜歡將Nginx同時做爲「負載均衡服務器」與「Web緩存服務器」來使用,你們能夠根據本身網站的狀況,來決定究竟使用哪一種軟件來做爲本身網站的網頁緩存。前端
負載均衡層 首先說下負載均衡層,咱們熟悉的硬件/軟件技術有F5,LVS/HAProxy,還有Nginx,它們的性能都是很是優異的,F5/LVS如今在全世界範圍內的應用,並且淘寶如今升級架構,也將LVS取代了F5,HAProxy可能你們不是特別熟悉,但HAproxy+Keepalived確實在生產環境下表現優異,強大的吞吐能力,穩定性比之 硬件過尤不及,並用淘寶也在大規模的推廣使用HAProxy,有興趣的朋友也能夠關注。再說下Nginx,我是將Nginx+Keepalived架構用於了各類生產環境中的,通過長時間的線上觀察,發現Nginx做爲負載均衡器/反向代理也很穩定,若是併發壓力過大,咱們前面能夠用F5/LVS做爲最前端的負載均衡,而將Nginx做爲七層代理,這樣的效果其實也不差,因此負載均衡層的壓力不能算是特別大。java
WEB層 WEB層這塊壓力比較大的網站如今都換成了Nginx做爲WEB應用服務器,事實上,它的抗併發能力確實超過了預期;我如今維護的一家門戶網站,高峯期時某臺Nginx應用服務器的併發達到了一萬以上,但Nginx也很負責和穩定的提供服務,在實際的生產環境中,若是咱們考慮到後端的數據庫服務時,一萬併發應該也算是一個比較大的數值了。另外,Linux集羣有一個優點,就是它的高擴展性,就算咱們的網站的併發有一萬以上,咱們後端的WEB服務是Apache,咱們多加幾臺 Apache服務器便可,在實際的線上維護時,咱們發現,高峯期間,實際上每臺WEB的併發並不算是特別大,因此網站的壓力在這一層咱們也能經過技術手段加以克服。c++
文件服務器層 如今你們的生產服務器通常是使用以下四種來做爲本身的文件服務器層: 1)單NFS+備份NFS做爲文件服務器,這樣的好處是維護方便,但存在着單點故障,須要人爲手動干預; 2)DRBD+Heartbeat+NFS高可用文件服務器,維護方便,也不存在着單點故障,但隨着訪問量的增大,後期同樣存在着壓力過大的狀況; 3)分佈式文件系統MFS、Gluster,,MFS易用,穩定,對海量小文件很高效,並且新版的MFS解決了 Master Server存在着單點故障的問題, 國內愈來愈多的公司在使用MFS。事實上,分佈式文件系統是解決文件服務器壓力過大的最終途徑,但這個同時也有隱患,網站功能越多,攤子越大,機器越多,維護起來越複雜。 4)若是你們的公司是淘寶和騰記這種巨量級的公司,能夠嘗試開發本身的分佈式文件系統了,你們能夠嘗試根據本身網站的狀況,來決定究竟選擇哪種軟件來做爲本身的文件服務器。程序員
數據庫層 數據庫層的壓力,我以爲網站的PV和併發上去之後,數據庫這塊的壓力是最大的,CDN大型廣告網站咱們用的是Oacle RAC方案,它保證了數據的高可用性,固然了價格也是很是昂貴的(若是使用高配置的PC服務器,Oracle通常按照CPU個數收費);那麼免費的 MySQL數據庫,面對這種併發壓力大的狀況,這個時候咱們應該怎麼辦呢?首先,咱們能夠在數據庫加入memcached數據緩存,在實際線上使用時,咱們也發現memcached功能強大,性能穩定,在數據庫頻繁讀寫,壓力過大的狀況下,增長一臺memcached數據緩存服務器的效果能超過咱們的預期。數據庫的硬件方面能夠考慮投入,磁盤陣列作成RAID10,若是資金充裕,磁盤能夠用固定硬盤來代替SAS硬盤,畢竟數據庫的壓力主要來自於磁盤I/O方面。合理的設計MySQL數據庫的架構,事實上,在生產環境下,一主多從、讀寫分離是靠譜的設計方案,從 MySQL的負載均衡我這裏推薦你們使用LVS,這是由於當後面的MySQL機器超過十臺時,HAProxy在這方面的性能不如LVS。若是網站的業務量過大,咱們能夠採用分庫的方法,好比將網站的業務量分紅Web、BBS、Blog等幾組,每一組均採用主從架構,這樣設計的話就避免了單組數據庫壓力過大的狀況。 另外,咱們還應該配合公司的MySQL DBA和開發人員,在數據庫參數優化、SQL語句優化、數據切分上多作功夫,避免數據庫成爲咱們網站的瓶頸。web
但願你們可以經過以上網站的五層分解,結合本身網站的狀況,瞭解每一層在網站設計中的做用和重要性,找出網站瓶頸加以優化,將本身的網站打形成高可用高可擴展性的網站。
總結: 開始的架構設計也是最難的,須要調研同類產品的狀況以及技術特徵,瞭解當前世界上對這種產品所能提供的理論支持和技術平臺支持,再結合本身項目的特色(須要透徹的系統分析),才能逐步造成本身項目的架構藍圖。 好比要開發網站引擎系統,就從Yahoo的我的主頁生成工具 到虛擬主機商提供的網站自動生成系統,以及IBM Webphere Portal的特色和侷限 從而從架構設計角度定立本身產品的位置。spring
好的設計確定須要通過反覆修改,從簡單到複雜的循環測試是保證設計正確的一個好辦法。數據庫
因爲在開始選擇了正確的方向,後來項目的實現過程也驗證了這種選擇,但在一些架構設計的細部方面,還須要對方案進行修改,屬於那種螺旋上升的方式,顯然這是經過測試第一的思想和XP工程方法來實現的。編程
若是咱們開始的架構設計在技術平臺定位具備必定的世界先進水平,那麼,項目開發實際有一半至關於作實驗,是研發,存在至關的技術風險。後端
所以,一開始咱們不可能將每一個需求都實現,而是採起一種簡單完成架構流程的辦法,使用最簡單的需求將整個架構都簡單的完成一遍(加入人工幹 預),以檢驗各個技術環節是否能協調配合工做(很是優秀先進的兩種技術有時沒法在一塊兒工做),同時也能夠探知技術的深淺,掌握項目中的技術難易點。這個過 程完成後,咱們就對設計方案作出上面的重大修改,豐富完善了設計方案。
設計模式是支撐架構的重要組件
架構設計也相似一種工做流,它是動態的,這點不象建築設計那樣,一開始就能徹底肯定,架構設計伴隨着整個項目的進行過程之中,有兩種具體操做保證架構設計的正確完成,那就是設計模式(靜態)和工程項目方法(RUP或XP 動態的)。
設計模式是支撐架構的一種重要組件,這與建築有很相象的地方,一個建築物創建設計須要建築架構設計,在具體施工中,有不少建築方面的規則和模式。
咱們從J2EE藍圖模式分類 http://java.sun.com/blueprints/patterns/catalog.html中就能夠很清楚的看到J2EE這樣一個框架軟件的架構與設計模式的關係。
架構設計是骨架,設計模式就是肉
這樣,一個比較豐富的設計方案能夠交由程序員進一步完成了,載輔助以適當的工程方法,這樣就可保證項目的架構設計能正確快速的完成。
時刻牢記架構設計的目標
因爲架構設計是在動態中完成的,所以在把握架構設計的目標上就很重要,所以在整個項目過程當中,甚至每一步咱們都必須牢記咱們架構設計的整體目標,能夠歸納下面幾點:
好比,咱們項目中有用戶註冊和用戶權限系統驗證,這實際上是個通用課題,每一個項目只是有其內容和一些細微的差異,若是咱們以前有這方面成功研發經 驗,能夠直接重用,若是沒有,那麼咱們就要進行這個子項目的研發,在研發過程當中,不能僅僅看到這個項目的需求,也要以架構的概念去完成這個能夠稱爲組件的 子項目。
我認爲落實到每一個類的具體實現上要真正能體現系統事物的本質特徵,由於事物的本質特徵只有一個,你的代碼越接近它,表示你的設計就是簡單明瞭, 越簡單明瞭,你的系統就越可靠。更多狀況是,一個類並不能反應事物本質,須要多個類的組合協調,那麼可以正確使用合適的設計模式就稱爲重中之重。
咱們看一個具有好的架構設計的系統代碼時,基本看到的都是設計模式,寵物店(pet store)就是這樣的例子。或者能夠這樣說,一個好的架構設計基本是由簡單明瞭的多個設計模式完成的。
要具有靈活的拓展性,就要站在理論的高度去進行架構設計,好比如今工做流概念逐步流行,由於咱們具體不少實踐項目中都有工做流的影子,工做流中有一個樹形結構權限設定的概念就對不少領域比較通用。
樹形結構是組織信息的基本形式,咱們如今看到的網站或者ERP前臺都是以樹形菜單來組織功能的,那麼咱們在進行架構設計時,就能夠將樹形結構和 功能分開設計,他們之間聯繫能夠經過樹形結構的節點link在一塊兒,就象咱們能夠在聖誕樹的樹枝上掛各類小禮品同樣,這些小禮品就是咱們要實現的各類功 能。
有了這個概念,一般比較難實現的用戶級別權限控制也有了思路,將具體用戶或組也是和樹形結構的節點link在一塊兒,這樣就間接實現了用戶對相應功能的權限控制,有了這樣的基本設計方案的架構無疑具有很靈活的拓展性。
Java架構設計
軟件架構做爲一個概念,體如今技術和業務兩個方面。
從技術角度來講:軟件架構隨着技術的革新不斷地更新其內容,軟件架構創建於當前技術和一些基本原則的基礎之上。
先說一些基本原則:
分層原則:分層是爲了下降軟件深度複雜性而使用的關鍵思想,就像社會有了階級同樣,軟件有了層次結構。 模塊化原則:模塊化是化解軟件廣度複雜的必然手段,模塊化的目的就是讓軟件分工。 接口實現分離原則隨着軟件模塊化的不斷深刻改進,面向接口編程而不是面向實現編程可讓複雜度日趨增高的軟件下降模塊之間的耦合度,從而讓各模塊更輕鬆改進。從這個原則出發,軟件也從微觀進行了細緻的規範化。
還有兩個比較小但很重要的原則:
細節隱藏原則很顯然把複雜問題簡化,把難看的細節隱去,能讓軟件結構更清晰。其實這個原則使用很廣泛,java/c++語言中的封裝原則以及設計模式中的Facade(外觀)模式就很能體現這個原則的精神。
依賴倒置原則隨着軟件結構的進一步發展,層與層之間、模塊與模塊之間的依賴逐漸加深,而層、模塊的動態可插拔要求不端增大。依賴倒置原則可看視 爲接口實現分離原則的深化,根據此原則的精神,軟件進入了工具時代。這個原則有點相似於知名的好萊塢法則:Don't call us, we'll call you。
以上這些原則奠基了咱們的軟件架構的價值指標。但軟件架構畢竟是創建在當前技術之上的。而每一代技術都有架構模式。過去的再也不說了,讓咱們如今就來看一下當前流行的技術,以及當前咱們能採用的架構。
由於面向對象是當前最流行開發技術,且設計模式的大量使用使面向對象的走向成熟,而數據庫是當前最有效的存儲結構、web界面是當前最流行的用 戶接口,因此當前最典型的三層次架構就架構在以上幾項技術的基礎之上,用數據庫做存儲層、用面向對象來實現業務層、用web來做爲用戶接口層。咱們從三層 次架構談起:
由於面向對象技術和數據庫技術不適配,因此在標準三層次架構的基礎上,咱們增長了數據持久層,來管理O-R雙向映射,但目前一直沒有最理想的實 現技術。cmp和entity bean技術由於其實現複雜,功能前景有限,已接近被淘汰的邊緣。JDO及hibernate做爲o-r映射的後期之秀,尤爲是hibernate,功能 至關完備。推薦做爲持久層的首選
在業務層,由於當前業務日趨負載,且變更頻繁,因此咱們必須有足夠敏捷的技術來保證咱們的適應變化的能力,在標準j2ee系統中session bean負責業務處理,且有不錯的性能表現,但採用ejb系統對業務架構模式改變太大,且其複雜而昂貴,業務代碼移植性差。而spring 做爲一個bean配置的輕量級架構,漂亮的IOC模式實現,對業務架構影響小,因此推薦做爲中間層業務框架。
在用戶結構層,雖然servlet/jsp/jstl/javaBean 可以實現MVC架構,但終究過於粗糙。struts對MVC架構的實現就比較完美,Taperstry也極好地實現MVC架構,且採用基於事件的方式,非 常誘人,惜其不夠成熟,咱們仍舊推薦struts做爲用戶接口層基礎架構。
由於業務層是三層次架構中最有決定意義的,因此讓咱們回到業務層細緻地分析一下,在複雜的業務咱們經常須要如下基礎服務的一種或幾種:事務一致 性服務acid(tool:jta/jts)、併發加鎖服務concurrent&&lock、池化管理服務cache、訪問控制服務 (tool:jaas)、流程控制服務workflow、動態實現服務IOC,串行化消息服務(tool:jms)、負載平衡服務blance等。若是我 們不採用重量級應用服務器(如weblogic,websphere,jboss等)及重量級組件(EJB),咱們必須本身實現其中一些服務。雖然咱們大 多狀況下,不須要全部這些服務,但實現起來卻非易事。幸運的是咱們有大量的開源實現代碼,但採用開源代碼卻經常是件不輕鬆的事。
隨着xml做爲結構化信息傳輸和存儲地位日漸重要,一些xml文檔操做工具(DOM,Digester,SAX等)的使用愈發重要,而隨着 xml schema的java binding工具(jaxb,xmlbean等)工具的成熟,採用xml schema來設計xml文檔格式,而後採用java binding來生成java bean 會成爲主要編程模式,而這又進一步使數據中心向xml轉移,使在中小數據量上,愈發傾向於以xquery爲查詢語言的xml數據庫。最近還有一個趨勢, microsoft,ibm等紛紛大量開發中間軟件如(microsoft office之infopath),能夠直接從xml schema 生成 錄入頁面等很是實用的功能。還有web service 的普遍應用,都將對軟件的架構有很是重大的影響。至於面向服務架構(SOA)前景如何,三層次架構何時走入歷史,如今還很難定論。
aop的發展也會對軟件架構有很深的影響,但在面向對象架構裏,不管aspectJ仍是jboss-aop抑是aspectWerks、 nanning都有其自身的嚴重問題:維護性不好,因此說它將很難走遠。也許做爲一個很好的思想,它將在web service裏大展身手。
rdf,owl做爲w3c語義模型的標誌性的語言,也很難想象能在當前業務架構發揮太大影響。但若是真如它所聲稱那樣,普遍地改變着信息的結構。那麼對軟件架構也會有深遠影響。
有關架構設計的一些忠告:
儘可能創建完整的持久對象層.可得到高回報 儘可能將各功能分層,分塊,每一模塊均依賴假定的其它模塊的外觀 不能依賴靜態數據來實現IOC模式,應該依賴數據特徵接口,靜態數據僅是數據特徵接口實現方式之一 架構設計時xml是支持而不是依賴.但能夠提供單一的xml版本的實現
從業務角度說:軟件架構應是深入體現業務內部規則的業務架構,但由於業務變化頻紝,因此軟件架構很難保持恆定不變,但業務的頻繁變化不該是軟件架構大規模頻繁變化的緣由,軟件架構應是基於變化的架構。
一種業務有其在一段時間內穩定存在的理由(暫且不談),業務內部有許多用例,每一種用例都有固定的規則,每一規則都有一些可供斷定的項,每一項 從某一維度來觀察都是可測量的,咱們的架構首先必須保證完美適應每一項每一種測量方式,不少失敗的架構都是由於不少項的測量方式都發生變動這種微觀變化 中。
每一個用例都有規則,咱們在做業務用例分析,經常假定一些規則是先驗的,持久穩定的,然然後來的業務改變經常又證實這種見解是錯誤的,然而經常我 們的架構已經爲之付出了不可挽回的代價。大量事實證實:規則的變化經常用例變化的根本緣由。因此咱們的架構要儘量適應規則的變化,儘量創建規則模版。
每一個用例都關係着不一樣的角色。每個用例的產生都必然是由於角色的變動(注意:不是替換,而是加強或減弱),因此注意角色的各類可能狀況,對架構的設計有舉足輕重的意義。在咱們當前的三層架構裏,角色完美地對應接口概念。
在一個系統裏不少用例都相互關聯,考慮到每一個用例均有可能有不一樣的特例,因此在架構設計中,儘可能採用依賴倒置原則。如架構許可可採用消息通訊模式(JMS)。這樣可下降耦合度。
如今咱們談一下業務穩定存在理由對業務的影響。存在便是合理,在這裏固然是正確的。業務因人而存在,因此問業務存在的理由便是問不一樣角色的須要這項業務的理由以及喜歡不喜歡當前業務用例的理由,全部這樣的角色都應該在系統裏預留。
在架構設計中有幾個原則能夠考慮:
用例儘可能細分 用例儘可能抽象 角色儘可能獨立 項測量獨立原則 追求簡單性 這裏未提供相關的例子,例子會在之後的更新時提供。
業務和模式之間的關係
業務中的一些用例之間的關係經常和一些常規的模式很類似。但隨着時間的演化,慢慢地和先前的模式有了分歧。這是個正常的現象。但這對系統架構卻要求很是高,要求系統架構能適應一些模式的更替。在這裏咱們儘量早地注意到用例之間的相互角色變化,爲架構更新作好準備.