單體架構(gòu)
下圖簡單展示了單體架構(gòu)的工作流程

單體架構(gòu)是把所有的模塊和功能集中到一起,部署到一臺服務(wù)器中,這種一把梭的方式,贏了還好,輸了就下海干活。如果請求過大,一臺機(jī)器撐不住,也只能通過添加機(jī)器的方式來進(jìn)行橫向擴(kuò)展。
微服務(wù)架構(gòu)
微服務(wù)架構(gòu)中我們的應(yīng)用往往是拆分成不同的模塊,取而代之的是多個不同的Service獨(dú)立部署。他們之間的通信通過http或者rpc等方式,這樣每個模塊我們就可以獨(dú)立開發(fā),互不影響。

可以看到之前的單體系統(tǒng)提供的功能被我們拆分成了很多個模塊,分別部署成不同的服務(wù)。
手機(jī)端用戶直接通過Nginx訪問不同的后端服務(wù),但是在手機(jī)端需要完成聚合功能。比如首頁需要顯示的數(shù)據(jù)需要在不同的服務(wù)中獲取數(shù)據(jù),就需要將數(shù)據(jù)請求回來組合之后才能進(jìn)行顯示,所以一般我們會在手機(jī)客戶端和微服務(wù)之間增加一層。

這一層主要做什么呢?聚合數(shù)據(jù)之后返回統(tǒng)一格式的數(shù)據(jù),還可以根據(jù)不同設(shè)備類型進(jìn)行裁剪(比如平板和手機(jī)顯示就不一樣),由于增加了BFF(backend for frontend,為前端開發(fā)的后端),APP和后端API就解除了強(qiáng)耦合的關(guān)系,兩邊是可以獨(dú)立變化的,不會受到另一方影響。
有的服務(wù)返回的數(shù)據(jù)可能是xml格式,有的有可能是json格式
微服務(wù)看起來很棒,但是也存在一些挑戰(zhàn),在微服務(wù)架構(gòu)之下,服務(wù)被拆的非常零散,降低了耦合度的同時也給服務(wù)的統(tǒng)一管理增加了難度。
在舊的服務(wù)治理體系之下,鑒權(quán),限流,日志,監(jiān)控等通用功能需要在每個服務(wù)中單獨(dú)實(shí)現(xiàn),這使得系統(tǒng)維護(hù)者沒有一個全局的視圖來統(tǒng)一管理這些功能。而計算機(jī)的問題都可以通過增加一層來解決這個問題,所以我們可以增加一層API網(wǎng)關(guān)來容納這些通用的功能,在此基礎(chǔ)上提供系統(tǒng)可擴(kuò)展性。

可以看到這里又提出來了一層gateway,而對于BFF,有些公司可能將其和gateway合并了,具體怎么處理,得看實(shí)際情況是怎樣的了。
API 網(wǎng)關(guān)模式意味著你要把API 網(wǎng)關(guān)放到你的微服務(wù)們的最前端,并且要讓API 網(wǎng)關(guān)變成由應(yīng)用所發(fā)起的每個請求的入口。這樣就可以明顯的簡化客戶端實(shí)現(xiàn)和微服務(wù)應(yīng)用程序之間的溝通方式。
沒有網(wǎng)關(guān)之前,客戶端將商品加入購物車不得不去請求用戶服務(wù),然后再到商品服務(wù),然后是購物車服務(wù)??蛻舳诵枰ブ涝趺慈ヒ黄饋硐M(fèi)這三個不同的service。使用API網(wǎng)關(guān),我們可以抽象所有這些復(fù)雜性,并創(chuàng)建客戶端們可以使用的優(yōu)化后的端點(diǎn),并向那些模塊們發(fā)出請求。
你還可以通過API網(wǎng)關(guān)中心化中間件的能力。當(dāng)你開始創(chuàng)建越來越多的服務(wù)時,你會發(fā)現(xiàn)自己面臨了一個新的問題 – 就是你發(fā)現(xiàn)你需要對一些服務(wù)進(jìn)行身份驗(yàn)證和流量控制。
有的服務(wù)是public的;有的是private的;有的則是合作伙伴的API,這些你只能提供給一些特定的用戶。遲早你會發(fā)現(xiàn)自己在實(shí)現(xiàn)每個微服務(wù)時總是一次次的重復(fù)編寫一些相同的代碼,這些代碼其實(shí)都是可以抽象為中間件的。
這顯然不是每個微服務(wù)應(yīng)該去關(guān)注的事情。API網(wǎng)關(guān)才應(yīng)該把這件事情攬下,也就是說微服務(wù)只負(fù)責(zé)接收進(jìn)來的request-然后返回一個類似JSON格式的response即可。然后API網(wǎng)關(guān)就把這些例如身份驗(yàn)證、日志(logging)以及流量控制都?xì)w于麾下。
微服務(wù)并不都是優(yōu)點(diǎn),它同樣有一長串需要考慮的問題,比如日志、監(jiān)控、異常處理、容錯、回滾、通信、消息格式、容器、服務(wù)發(fā)現(xiàn)、備份、測試、報警、跟蹤、工具、文檔、擴(kuò)展、時區(qū)、API版本、網(wǎng)絡(luò)延遲、健康檢查、負(fù)載均衡等等問題,一個新的方式解決問題的同時也會面臨新的問題,所以不要覺得微服務(wù)就一定好,每個階段面臨的問題不一樣,我們處理問題,看待問題的方式也不一樣。
微服務(wù)要關(guān)心的事情太多,所以如果你的公司準(zhǔn)備轉(zhuǎn)成微服務(wù)就一定要有具備這些解決微服務(wù)面臨問題的能力。
云原生服務(wù)
微服務(wù)之后,又興起了云原生服務(wù),什么是云原生服務(wù)呢?
云原生應(yīng)用定義: 基于微服務(wù)原理而開發(fā)的應(yīng)用,以容器方式打包。在運(yùn)行時,容器由運(yùn)行于云基礎(chǔ)設(shè)施之上的平臺(比如kubernetes)進(jìn)行調(diào)度。應(yīng)用開發(fā)采用持續(xù)交付和DevOps實(shí)踐。
云原生服務(wù)還是離不開微服務(wù),只是它是運(yùn)行在具備云原生基礎(chǔ)的平臺中的,而且采用的是持續(xù)交付和DevOps實(shí)踐。這個云原生平臺有什么作用呢?用過Kubernetes的都知道它不用擔(dān)心擴(kuò)展、服務(wù)發(fā)現(xiàn)、負(fù)載均衡、容錯、回滾、更新等等問題,并且對于gateway,監(jiān)控等等都有配套的成熟解決方案。真的是誰用誰知道。
這里就不展開說了,感興趣的可以去了解下Kubernetes
API Gateway選擇
網(wǎng)關(guān)需要考慮哪些內(nèi)容
- 限流熔斷
- 動態(tài)路由和負(fù)載均衡
- 基于path的路由,比如 example.com/user 訪問問用戶服務(wù), example.com/shopping 訪問購物服務(wù)
- 截獲器鏈
- 日志采集和Metrics埋點(diǎn)
- 響應(yīng)流優(yōu)化
- 可編程API
- Header頭重寫
各大網(wǎng)關(guān)對比
| 支持公司 | 實(shí)現(xiàn)語言 | 亮點(diǎn) | 不足 | |
|---|---|---|---|---|
| Nginx(2004) | Nginx Inc | C/Lua | 高性能,成熟穩(wěn)定 | 門檻高,偏運(yùn)維,可編程弱 |
| Zuul1(2012) | Netflix/Pivotal | Java | 成熟,簡單門檻低 | 性能一般,可編程一般 |
| Spring Cloud Gateway(2016) | Pivotal | Java | 異步,配置靈活 | 早期產(chǎn)品 |
| Envoy(2016) | Lyft | C++ | 高性能,可編程API/ServiceMesh集成 | 門檻較高 |
| Kong(2014) | Kong Inc | OpenResty/Lua | 高性能,可編程API | 門檻較高 |
| Traefik(2015) | Containous | Golang | 云原生,可編程API/對接各種服務(wù)發(fā)現(xiàn) | 生產(chǎn)案例不太多 |
實(shí)際中我們使用的是云原生服務(wù),而Zuul和Spring Cloud Gateway結(jié)合Spring Cloud全家桶結(jié)合使用效果較好,所以它不太適合我們現(xiàn)在的選擇。
我們將目光集中在Kong和traefik中,經(jīng)過對比發(fā)現(xiàn),我們最終還是選擇了traefik,相比較于Kong,traefic的優(yōu)勢如下:
1. traefik較為輕量,非常易于使用和設(shè)置
2. traefic通過Kubernetes存儲狀態(tài)(Kong要使用Postgres或者Cassandra來存儲狀態(tài)),并利用Ingress通過https將所有流量路由到對應(yīng)的服務(wù)
3. 已在全球范圍內(nèi)用戶生產(chǎn)環(huán)境,并經(jīng)過了嚴(yán)格的測試和基準(zhǔn)測試,在我司其他項(xiàng)目中有運(yùn)用
4. Kong儀表板,它是單獨(dú)開發(fā)的,與最新版本的Kong兼容需要花點(diǎn)時間。Traefik帶有自己的儀表板,它始終與最新的Traefik版本兼容,Traefik的用戶界面也比Kong的用戶界面好看。
traefik的Middlewares真心好用,traefik建議升級到traefik2
并且traefik還可以作為Kubernetes ingress controller,可以完全替代我們之前說過的nginx controller
如何使用traefick作為網(wǎng)關(guān)進(jìn)行用戶驗(yàn)證

ingress route的配置:

代碼:

通過上面的配置之后,當(dāng)我們想要訪問/api/orders這個api的時候就會先去/api/auth中進(jìn)行授權(quán)驗(yàn)證用戶是否登錄,如果登錄后則會將攜帶對應(yīng)的http header到對應(yīng)的后端服務(wù),后端服務(wù)在根據(jù)這個header進(jìn)行驗(yàn)證
