1. 程式人生 > >用簡單的方法構建一個高可用服務端

用簡單的方法構建一個高可用服務端

高可用 架構 redis 服務器

一. 什麽是高可用性

服務端,顧名思義就是為用戶提供服務的。
停工時間,就是不能向用戶提供服務的時間。
高可用,就是系統具有高度可用性,盡量減少停工時間。

停工的原因一般有:

服務器故障。例如服務器宕機,服務器網絡出現問題,機房或者機架出現問題等。
訪問量急劇上升,導致服務器壓力過大。導致訪問量急劇上升的原因有:
時間和訪問量都可以預見的,例如秒殺活動,售票系統。
時間和訪問量都不可以預見的,例如特發性新聞(馬航失聯的事件)
停工的原因,可以理解為災難,所以系統的高可用性就是容災,即應對災難的能力,系統有較好的容災能力,也就是即使災難出現,系統依然可以正常工作。

二. 怎麽提升系統的高可用性

  1. 機器層面的災難

例如:
機器宕機(其中一臺服務器宕機了)
機房故障(機房被水淹了)
網絡異常(電信的某條光纖被挖斷了)
從範圍了說,有可能是一臺機器,也有可能是多臺機器(機房或者某個區域,例如廣東),甚至全部機器(那就沒救了。。)。

思路就是在多臺機器上部署服務,即使一臺機器出現問題,其他機器依然可以提供服務。當然,比較可靠的是,多臺機器最好在不同的機房,不同的地域,但是對應的成本也會上升。

  1. 主從方式
    主服務負責提供服務,從服務負責監測主服務器的心跳。當主服務出現問題,立刻轉換為從服務器提供服務。例如Mysql的主從架構。

2.多機多工方式
在N臺機器上面,運行N個服務,通過負載均衡,把請求分發到不同的機器。當其中一臺機器出現問題。系統會自動的切換流量,也就是把請求都導流到其他正常的機器上。

  1. 業務層面的災難
    例如:

程序出bug了
訪問量急劇上升(預計QPS是1k,突然去到1w)
優化思路:

大系統小做。一個大系統,必然會有許多模塊,把這些模塊切分為多個小服務。例如用戶系統,是一個獨立的服務,消費系統,是一個獨立的服務。每個服務都提供訪問的API,給其他服務訪問。缺點是服務與服務之間的通訊成本增加,開發成本也會增加,因為要開發API。但是好處是:
必要的時候,這些API可以提供給外部
符合高內聚低耦合的原則
當某個服務壓力上升時,或者服務出現bug時,其他不依賴於問題服務的服務,依然可以正常工作。例如消費服務出現問題,但是聊天服務可以依然可以正常工作。
有損服務。讓服務延遲執行,以保證核心需求得到很好的處理。例如微信搶紅包,核心需求是立刻知道搶紅包的結果,所以服務端先返回搶紅包的結果,而用戶對是否即時入賬並不關心,所以,把入賬這個過程,放在異步隊列裏面做。

柔性可用。在正常服務和停工之間增加一個狀態:部分可用。當壓力上來的時候,可以停止某些非必要服務,以保證必要服務可以正常運行。又例如遇到bug的時候,短時間內不能立刻修復,而且出bug的業務又是非必要業務,可以先停止bug的業務,當然,這些要事先跟產品方商量好。
快速拒絕(過載保護)。檢查當前系統的負載請求,如果負載過高,立刻返回等待提示,例如:系統繁忙,請稍後再試。否則,用戶會不斷重試,讓已經負載很高的系統雪上加霜。在客戶端,要限制重試的頻率,例如30s後才能重試,或者沒有收到服務端的返回前,不能再次提交請求。也可以在Nginx層加入限制,同一IP1秒內不能發送多於N個請求,多於的就快速拒絕,防止被攻擊。

  1. 驗證高可用
    當我們采用了各種措施來提升系統的容災能力後,怎麽測試我們的措施是否有用呢?

模擬客戶端低網速。這個可以通過Fiddler來模擬
模擬服務端丟包。可以使用netern和tc
使用ab進行壓測。
模擬服務器宕機,可以直接斷開服務器網絡來模擬
三、應用
應用一般都是針對上面的機器問題導致的機器層面的災難,因為業務層面的,一般是在代碼開發階段考慮的。

高可用可以分為兩個關鍵點:

多節點
自動切換流量
多節點,也就是要部署多個節點,無論其他節點是掛起狀態(主從),還是工作昨天(多機多工)。
當有了多節點後,還是不夠的,因為當災難來臨的話,如果要人工去切換流量,必然要花費較長時間,所以需要有自動切換流量的機制。
自動切換流量的另一個功能就是,當損壞的節點恢復後,流量又會自動得切回去。

四、HTTP的應用
常用的服務端架構,一般是這樣:
技術分享圖片

Alt text
客戶端從DNS服務器獲取服務器的IP
客戶端發起請求,請求先到Nginx層
Nginx層分發請求到服務層
如果需要,服務層會請求上遊的服務層,例如向用戶系統獲取用戶數據。一般會已通過HTTP來實現。
如果需要,服務層會訪問緩存層,獲取數據
如果需要,服務層會訪問數據庫層,獲取數據

  1. 客戶端層到Nginx層
    會部署多個Nginx層,DNS服務器中部署多個IP,這樣DNS服務器會把流量均勻地分到多個Nginx。
    缺點是:

不能自動切換流量。當其中一臺Nginx不可用了,DNS服務器並不知道,所以不會自動切換流量
本機的hosts配置中,可以設置一個域名對應多個IP,設置方法:
192.168.137.130 www.test.com
192.168.137.133 www.test.com
hosts的解析策略是,先訪問第一個IP,如果失敗,才會訪問第二個IP
所以沒有負載均衡的功能,但是有自動流量切換的功能。

  1. Nginx到服務層
    Nginx裏面可以配置多個服務層。
    Nginx有監聽服務層是否可用的機制(upstream),所以可以實現自動切換流量

nginx配置

upstream gunicorn_pool
{
#server 地址:端口號 weight表示權值,權值越大,被分配的幾率越大;max_fails表示在fail_timeout中失敗的最大次數,如果達到該次數,就不再導流量到該server
server 192.168.137.130:9098 weight=4 max_fails=2 fail_timeout=30s;
server 192.168.137.133:9098 weight=4 max_fails=2 fail_timeout=30s;
}

server {
listen 80;
server_name 127.0.0.1 www.test.com;
access_log /data/logs/nginx_access.log;
error_log /data/logs/nginx_error.log;
location @gunicorn_proxy {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://gunicorn_pool;
}
}
配置一個upstream,gunicorn_pool。裏面有兩個服務層(130和137)
如果兩個服務層都正常,Nginx會把流量根據weight值,導流到兩個服務器。
同一個請求中,如果nginx導流到server1,發現返回的是錯誤響應(例如502),nginx會把請求再發送server2,相當於重試。這時會記錄server1的fail次數+1
如果再fail_timeout時間內,server1的fail次數超過max_fails,在fail_timeout時間內,nginx就不會再把其他請求導流到server1了。

上面的機制,就可以實現自動的流量切換。當然也有負載均衡的功能,這個就是高並發的範疇了。

  1. 服務層到上遊服務器
    DNS服務器。使用DNS服務器把流量均分到上遊服務層。缺點也是不能自動切換流量
    RPC-client。在服務器的機器中,部署一個RPC-client,一般的實現方案是啟動一個Nginx,利用Nginx的upstream功能來分發流量,同時可以實現自動流量切換。服務層到上遊服務層的請求,會先發到RPC-client,然後再到上遊服務層,相當於加了一個HTTP代理。
    4.服務層到緩存層
    常用的緩存有redis和mongodb

1.redis
主從架構
哨兵架構
集群架構
redis cluster

2.mongo
主從架構
副本集架構
分片
mongo HA

5.服務層到數據庫層
常用的數據庫就是Mysql了。

一主多從(主從復制)
二主多從(主主復制)
五、TCP的應用

  1. DNS方法
    配置DNS服務器,一個域名,對應多個IP。
    缺點是不能實現流量自動切換,例如S1掛了,DNS還是會返回S1的iP給客戶端。客戶端可能要重試幾次,才會拿到其他Server的IP,才能實現連接。

2.get-ip接口
由於TCP是長連接,所以獲取IP的請求是很少的,所以可以自己寫一個接口,客戶端通過接口來獲取TCP Server的IP地址。
這樣接口裏面就可以做到自動切換流量了。例如A機器已經掛了,就不會返回A機器的IP了。
TCP Server可以把自身的狀態在Redis,然後接口那邊就可以獲取TCP Server的狀態了
也可以TCP Server提供一個http接口,返回自身的狀態,供get-ip接口那邊調用。
在互聯網公司面試中,架構的底層一定是面試官會問問的問題,針對面試官一般會提到的問題,我錄制了一些分布式,微服務,性能優化等技術點底層原理的錄像視頻,加群619881427可以免費獲取這些錄像,裏面還有些分布式,微服務,性能優化,春天設計時,MyBatis的等源碼知識點的錄像視頻。這些視頻都是 找一些資深架構師朋友一起錄制出來的,這些視頻幫助以下幾類程序員:

1.對現在的薪資不滿,想要跳槽,卻對自己的技術沒有信心,不知道如何面對面試官。

2.想從傳統行業轉行到互聯網行業,但沒有接觸過互聯網技術。

3.工作1 - 5年需要提升自己的核心競爭力,但學習沒有系統化,不知道自己接下來要學什麽才是正確的,踩坑後又不知道找誰,百度後依然不知所以然。

4.工作5 - 10年無法突破技術瓶頸(運用過很多技術,在公司一直寫著業務代碼,卻依然不懂底層實現原理)

如果你現在正處於我上述所說的幾個階段可以加下我的群來學習。而且我也能夠提供一些面試指導,職業規劃等建議。

用簡單的方法構建一個高可用服務端