功能實現前端
這個自沒必要說。web
性能與可伸縮性redis
根據預期的訪問量,評估機器負載狀況。若是在可預期的將來一臺服務器能夠撐得住,則不必使用多臺服務器。須要對多個環節進行性能評估:web服務器、邏輯服務器、DB等等。同時每一個環節均可以考慮是否須要緩存。sql
在web服務器層面,有一個重要的點,即系統的 URL 選擇。首先,要盡最大可能避免訪問量差異很大的系統共用一個域名。由於隨着系統的發展,頗有可能須要對訪問量大的系統進行擴容。擴容引入分流機制。若是這兩個系統共用同一個域名,且 URL 的區分度不高,會對分流機制形成很大的障礙。雖說有些系統或模塊(或頁面)的 URL 相對可變,可是對於開放給外部(尤爲是公司外部)訪問的 URL 來講,變動是不可能的。這種類型的 URL 本質上是 API。這又牽扯到另一個主題:《API 設計》。這裏暫且 pass。數據庫
在邏輯服務器層面,切記讀寫分離,若是預計系統不須要多臺服務器,也該爲讀寫分離留下後路。還有一點須要關注的是,不一樣的服務之間互相訪問,不要直接以 ip:端口 的形式,而儘可能以域名的方式。若是是用前者,後期擴容時,也能夠引入虛擬 ip 補救。設計模式
在 DB 層面,考慮是否須要引入 memcache 或 redis 之類的緩存。考慮是否須要作 M-S。另外,考慮 DB 層是直接對上層暴露 ip 端口,仍是引入一個抽象層(如虛擬 ip)。再者,作庫表設計時,考慮是否應該分庫、分表。瀏覽器
在引入了多服務器架構以後,隨之而來的是數據同步與合併問題。好比,A 服務器上產生了一張圖片,可能須要把它同步到 B 服務器上。或者數據庫須要作 M-S 同步。須要合併的,最典型是日誌。若是日誌分散在許多臺機器上,定位問題和分析日誌都顯得很是麻煩,須要有一種合併機制。還有一個也是很重要的點,即 session 的合併。同一個用戶,可能第一次請求到 A 服務器上,下一次請求到 B 服務器上,如何使這兩臺機器能共享一個 session,是一個須要解決的問題。一個解決方案是使用 redis 存儲會話信息。緩存
在多服務器架構下,動態腳本和靜態文件分離是一個比較好的經驗。這裏的分離指使用不一樣的域名,代碼文件放在不一樣的機器上。這是由於動態腳本和靜態文件的性能屬性差異比較大。將它們分開能夠對它們使用不一樣的部署策略。例如,靜態文件能夠更有效地利用瀏覽器緩存。安全
可用性服務器
可用性這個方面,有不少與上一個重疊的地方,由於都涉及到多服務器。他們之間的區別是:可伸縮性考慮的是系統能不能撐得住很大的訪問量,以及當訪問量意外性的出現暴增時,系統可否快速提高自身的處理能力來進行響應。而可用性關注的問題是:這個服務的重要性如何?若是特別重要,怎麼保證它不會掛?
提高可用性的經常使用手段之一是引入冗餘災備措施。一樣涵蓋上面提到的那幾個環節。若是要引入冗餘,切記重點關注兩個問題:1,單點故障;2,跨機房。
單點故障。假設把架構設計成:前端兩臺 web 服務器,域名經過 dns 解析到這兩臺機器上,邏輯服務器也兩臺,可是 DB 只有一臺。那麼 DB 這個環節就是一個單點。若是 DB 服務器掛掉,整個系統都會掛掉。前面設計了兩臺 web 服務器和兩臺邏輯服務器都沒有任何意義。
而後說一下跨機房。跨機房是一個很大的挑戰,除非十分必要,不然儘可能不要使用跨機房架構。由於一般狀況下,咱們幾乎不可能把全部的服務都在兩個地方部署一份。99.99% 會出現這樣的狀況:部署了跨機房的系統,須要訪問另一個只在一個機房有部署的服務。這個時候,其中一個機房必須經過通道訪問另一個機房。這樣,兩個機房就不是徹底同樣的了。此外,兩個機房的數據、日誌等都須要同步、合併。這些都會使運維的難度大大提升。
除了冗餘以外,考慮可用性,還應想到監控措施。監控有多種方法。經常使用的方法有:
1,日誌或數據分析。服務器上後臺跑進程,不停地對日誌或類日誌的數據進行分析,一旦發生異常,報警。
2,代碼中植入對服務或接口的監控。當用代碼訪問一個服務時,檢查其響應。若是響應異常,報警。
3,心跳式輪詢檢測。每隔一段時間向服務發送特殊的請求,檢查其響應。若是響應異常,報警。
4,服務器負載監控。例如 CPU、內存、硬盤、IO、cgi 進程數等等。有些狀況下這些工做有運維工程師去作。
5,代碼中植入對響應時間的統計,並另起後臺進程,對響應時間進行監控。
其中,一、二、四、5是系統內部的監控,3是系統外部監控。系統內部監控能夠更加細緻,能監控到一些外部監控不到的東西。可是,一旦系統自己掛掉(例如服務器掛了),內部監控也會失效。
可擴展性
這個方面涉及到軟件的邏輯架構,更多的與業務相關。考慮可擴展性的目的是爲了應對需求變動。這要求首先對需求有較深刻的瞭解,而且可以大體把握到需求變動的方向。這以後,在代碼結構層面,爲預期的變動方向留下空間。要求設計者具備很是豐富的編碼經驗和對設計模式有深入的理解。
可調試性
這個方面容易被忽略,倒是很是重要的一環。web 系統的部署環境和交互流程愈來愈複雜,有時候定位一個線上問題很是困難。一般是開發環境沒法重現,同時又得到不到足夠的信息進行定位。所以這個因素應該在系統設計時就考慮進去:當出現問題時,如何方便地進行定位和調試?這裏分服務端和頁面兩個部分考慮。
日誌沒必要說,是重要的信息來源。服務端寫日誌,須要對日誌進行有效的組織(這裏也是一門學問)。
另外,服務端須要注意的一點,是統一的錯誤碼處理。錯誤碼管理混亂會影響問題的定位。最好的狀況是,錯誤碼分得很細,而且保證絕對無重複。這樣,開發一拿到錯誤碼,馬上就能大概判斷出問題所在。
再者,服務端,可能須要備好調試工具。能夠理解爲後門,可是隻有通過受權才能使用。
前端寫不了日誌是個大問題,須要另尋途徑把錯誤信息拿到手。最差的方法是犧牲部分用戶體驗,把錯誤碼以某種方式展現出來,而後經過詢問用戶來得到錯誤碼。這種方式不建議使用。更好的作法是,在前端蒐集錯誤信息,而後經過接口上報到服務器進行存儲。
可測試性
可測試性和可調試性的區別是什麼?可調試性考慮的問題是:系統上線運行以後,如何快速定位並處理線上出現的問題;可測試性考慮的問題是:測試人員怎麼測這個系統。
在開發以前就考慮測試,一來是未雨綢繆,爲未來的測試階段提供便利;二來有利於提升代碼質量。關於這一點,實踐過TDD的人都心照不宣。
安全
安全的重要性再怎麼強調都不爲過。xss、csrf、sql注入、敏感信息泄露、刷接口、重放等等等等。安全領域涉及到的東西不少。
數據統計與後臺
考慮系統是否須要後臺管理、是否須要收集數據進行統計分析,這些都會影響到系統的設計。後臺管理者一般在通過受權以後會獲得高權限,所以系統設計上須要區分角色。而數據的收集容易致使所謂的「霰彈式修改」,引發系統的快速腐爛。