導語:工作也有幾多年了,無論是身邊遇到的還是耳間聽聞的,多多少少也積攢了自己的一些經驗和思考,當然,我并沒有接觸太多高大上的分布式架構實踐,是以總結的經驗相對比較零碎,歡迎大家随時補充。
俗話說得好,冰凍三尺非一日之寒,滴水穿石非一日之功,羅馬也不是一天就建成的,對于開發人員來說,一個好的架構并不是一蹴而就的。
最開始,就是各種架構一搭,然後扔到 Tomcat 容器中跑,這時候我們的檔案、資料庫、應用都在一個伺服器上。

随着系統的上線,使用者量也會逐漸上升,很快一台伺服器已經滿足不了系統的負載,這時我們就要在伺服器還沒有超載時,提前做好準備。
由于我們是單體架構,優化架構在短時間内是不現實的,增加機器是一個不錯的選擇。這時,我們可能要把應用和資料庫服務單獨部署,如果有條件也可以把檔案伺服器單獨部署。
為了提升服務處理能力,我們在 Tomcat 容器前加一個代理伺服器,一般使用 Nginx,當然你如果更熟悉 Apache 也未嘗不可。
使用者的請求發送給反向代理,然後反向代理把請求轉發到後端的伺服器。
從嚴格意義上說,Nginx 是屬于 Web 伺服器,一般處理靜态 HTML、CSS、JS 請求;而 Tomcat 屬于 Web 容器,專門處理 JSP 請求,當然 Tomcat 也是支援 Html 的,隻是效果沒 Nginx 好而已。
反向代理的優勢,如下所示:
隐藏真實後端服務。
負載均衡叢集。
高可用叢集。
緩存靜态内容實作動靜分離。
安全限流。
靜态檔案壓縮。
解決多個服務跨域問題。
合并靜态請求(HTTP/2.0後已經被弱化)。
防火牆。
SSL 以及 http2。
基于以上 Nginx 反向代理,我們還可以實作動靜分離,靜态請求如 HTML、CSS、JS 等請求交給 Nginx 處理,動态請求分發給後端 Tomcat 處理。
Nginx 更新到 1.9.5+ 可以開啟 HTTP/2.0 時代,加速網站通路。當然,如果公司不差錢,CDN 也是一個不錯的選擇。
在這分布式微服務已經普遍流行的年代,我們沒必要踩過多的坑,就很容易進行拆分。
市面上已經有相對比較成熟的技術,比如阿裡開源的 Dubbo(官方明确表示已經開始維護了),Spring 家族的 Spring Cloud,當然具體如何去實施,無論是技術還是業務方面都要有很好的把控。
服務發現——Netflix Eureka
客服端負載均衡——Netflix Ribbon
斷路器——Netflix Hystrix
服務網關——Netflix Zuul
分布式配置——Spring Cloud Config
同步通信和異步通信
遠端調用 RPC
REST
消息隊列
服務拆分以後,随之而來的就是持續內建部署,你可能會用到以下工具:Docker、Jenkins、Git、Maven。
基本拓撲結構如下所示:
整個持續內建平台的架構演進,如下圖所示:
Linux 叢集主要分成三大類:
科學計算叢集。
我們最常見的也是生産中最常接觸到的就是負載均衡叢集。
負載均衡實作的三種方法:
DNS 負載均衡,一般域名注冊商的 DNS 伺服器不支援,但我用的阿裡雲解析已經支援。
四層負載均衡(F5、LVS),工作在 TCP 協定下。
七層負載均衡(Nginx、haproxy),工作在 HTTP 協定下。
大家都知道,服務一般分為有狀态和無狀态,而分布式 Session 就是針對有狀态的服務。
分布式 Session 的幾種實作方式:
基于資料庫的 Session 共享。
基于 resin/tomcat web 容器本身的 Session 複制機制。
基于 oscache/Redis/memcached 進行 Session 共享。
基于 cookie 進行 Session 共享。
分布式 Session 的幾種管理方式:
Session Replication 方式管理 (即 Session 複制)。 簡介:将一台機器上的 Session 資料廣播複制到叢集中其餘機器上。 使用場景:機器較少,網絡流量較小。 優點:實作簡單、配置較少、當網絡中有機器 Down 掉時不影響使用者通路。 缺點:廣播式複制到其餘機器有一定延時,帶來一定網絡開銷。
Session Sticky 方式管理。 簡介:即粘性 Session、當使用者通路叢集中某台機器後,強制指定後續所有請求均落到此機器上。 使用場景:機器數适中、對穩定性要求不是非常苛刻。 優點:實作簡單、配置友善、沒有額外網絡開銷。 缺點:網絡中有機器 Down 掉時,使用者 Session 會丢失、容易造成單點故障。
緩存集中式管理。 簡介:将 Session 存入分布式緩存叢集中的某台機器上,當使用者通路不同節點時先從緩存中拿 Session 資訊。 使用場景:叢集中機器數多、網絡環境複雜。 優點:可靠性好。 缺點:實作複雜,穩定性依賴于緩存的穩定性、Session 資訊放入緩存時要有合理的政策寫入。
目前生産中使用到的:
基于 Tomcat 配置實作的 Mem Cache 緩存管理 Session 實作(麻煩)。
基于 Os Cache 和 shiro 多點傳播的方式實作(網絡影響)。
基于 Spring-Session+Redis 的方式實作(最适合)。
負載均衡政策的優劣及其實作的難易程度有兩個關鍵因素:負載均衡算法,對網絡系統狀況的檢測方式和能力。
rr 輪詢排程算法
顧名思義,輪詢分發請求。優點是實作簡單,缺點是不考慮每台伺服器的處理能力。
wrr 權重排程算法
我們給每個伺服器設定權值 weight,負載均衡排程器根據權值排程伺服器,伺服器被調用的次數跟權值成正比。優點是考慮了伺服器處理能力的不同。
sh 原位址散列
提取使用者 IP,根據散列函數得出一個 key,再根據靜态映射表,查出對應的 value,即目标伺服器 IP。一單目标機器超負荷,則傳回空。
dh 目标位址散列
同上,隻是現在提取的是目标位址的 IP 來做哈希。優點是以上兩種算法都能實作同一個使用者通路同一個伺服器。
lc 最少連接配接
優先把請求轉發給連接配接數少的伺服器。優點是使得叢集中各個伺服器的負載更加均勻。
wlc 權重最少連接配接
在 lc 的基礎上,為每台伺服器加上權值。算法為:(活動連接配接數*256+非活動連接配接數)÷權重 ,計算出來的值小的伺服器優先被選擇。優點是可以根據伺服器的能力配置設定請求。
sed 最短期望延遲
sed 跟 wlc 類似,差別是不考慮非活動連接配接數。算法為:(活動連接配接數+1)*256÷權重,同樣計算出來的值小的伺服器優先被選擇。
nq 永不排隊
改進的 sed 算法,我們想一下什麼情況下才能“永不排隊”,那就是伺服器的連接配接數為 0 的時候,那麼假如有伺服器連接配接數為 0,均衡器直接把請求轉發給它,無需經過 sed 的計算。
LBLC 基于局部性的最少連接配接
均衡器根據請求的目的 IP 位址,找出該 IP 位址最近被使用的伺服器,把請求轉發之,若該伺服器超載,則采用最少連接配接數算法。
LBLCR 帶複制的基于局部性的最少連接配接
均衡器根據請求的目的 IP 位址,找出該 IP 位址最近使用的“伺服器組”,注意,這裡不是具體某個伺服器,然後采用最少連接配接數算法,從該組中挑出具體的某台伺服器出來,把請求轉發之。
若該伺服器超載,那麼根據最少連接配接數算法,從在叢集的非本伺服器組的伺服器中,找出一台伺服器出來,加入本伺服器組,然後把請求轉發之。
MySQL 主從配置,讀寫分離并引入中間件,開源的 MyCat,阿裡的 DRDS 都是不錯的選擇。
如果是對高可用要求比較高,但是又沒有相應的技術保障,建議使用阿裡雲的 RDS 或者 Redis 相關資料庫,省事省力又省錢。
如果有搜尋業務需求,引入 solr 或者 elasticsearch 也是一個不錯的選擇,不要什麼都塞進關系型資料庫。
引入緩存無非是為了減輕後端資料庫服務的壓力,防止其"罷工"。
常見的緩存服務有:Ehcache、OsCache、MemCache、Redis,它們都是主流經得起考驗的緩存技術實作,特别是 Redis 已大規模運用于分布式叢集服務中,并證明了自己優越的性能。
異步通知:比如短信驗證,郵件驗證這些非實時回報性的邏輯操作。
流量削鋒:應該是消息隊列中的常用場景,一般在秒殺或團搶活動中使用廣泛。
日志處理:系統中的日志是必不可少的,但是如何去處理高并發下的日志卻是一個技術活,一不小心可能會壓垮整個服務。
工作中我們常用到的開源日志 ELK,為嘛中間會加一個 Kafka 或者 Redis 就是這麼一個道理(一群人湧入和排隊進的差別)。
消息通訊:點對點通信(個人對個人)或釋出訂閱模式(聊天室)。
消息隊列中提到的 ELK 開源日志元件對于中小型創業公司是一個不錯的選擇。
以上種種,沒有安全做保證,一切都會歸于零:
阿裡雲的 V** 虛拟專有網絡以及安全組配置。
自建機房的話,要自行配置防火牆安全政策。
相關服務通路,比如 MySQL、Redis、Solr 等如果沒有特殊需求盡量使用内網通路并設定鑒權。
盡量使用代理伺服器,不要對外開放過多的端口。
HTTPS 配合 HTTP/2.0 也是個不錯的選擇。
負載均衡(負載均衡算法)
反向代理
服務隔離
服務限流
服務降級(自動優雅降級)
失效轉移
逾時重試(代理逾時、容器逾時、前端逾時、中間件逾時、資料庫逾時、NoSql逾時)
復原機制(上線復原、資料庫版本復原、事務復原)
02 高并發
應用緩存
HTTP 緩存
多級緩存
分布式緩存
連接配接池
異步并發
二階段送出(強一緻)
三階段送出(強一緻)
消息中間件(最終一緻性),推薦阿裡的 RocketMQ。
任務隊列
請求隊列
擴容
單體垂直擴容
單體水準擴容
應用拆分
資料庫拆分
資料庫分庫分表
資料異構
分布式任務
SQL 注入
XSS 攻擊
CSRF 攻擊
拒絕服務(DoS,Denial of Service)攻擊
Linux(必備)、某軟的
DNS、F5、LVS、Nginx、OpenResty、HAproxy、負載均衡SLB
Dubbo、Motan、Spring-Could
DRDS 、Mycat、360 Atlas、Cobar (不維護了)
RabbitMQ、ZeroMQ、Redis、ActiveMQ、Kafka
Zookeeper、Redis
Redis、Oscache、Memcache、Ehcache
Docker、Jenkins、Git、Maven
OSS、NFS、FastDFS、MogileFS
MySQL、Redis、MongoDB、PostgreSQL、Memcache、HBase
專用網絡 VPC、彈性公網 IP、CDN
作者:張志朋 簡介:資深 Java 愛好者,深耕于線上教育領域。 來源:51CTO技術棧微信公衆号 \ https://blog.52itstyle.com