這些年背過的面試題——SpringCloud篇
來源:阿里雲開發者
阿里妹導讀
Why SpringCloud
Spring cloud 是一系列框架的有序集合。它利用 spring boot 的開發便利性巧妙地簡化了分散式系統基礎設施的開發,如服務發現註冊、配置中心、訊息匯流排、負載均衡、斷路器、資料監控等,都可以用 spring boot 的開發風格做到一鍵啟動和部署。
SpringBoot是Spring推出用於解決傳統框架配置檔案冗餘,裝配元件繁雜的基於Maven的解決方案,旨在快速搭建單個微服務,SpringCloud是依賴於SpringBoot的,而SpringBoot並不是依賴與SpringCloud,甚至還可以和Dubbo進行優秀的整合開發。
RestTemplate:基於HTTP協議;
Feign:封裝了ribbon和Hystrix 、RestTemplate 簡化了客戶端開發工作量;
RPC:基於TCP協議,序列化和傳輸效率提升明顯;
MQ:非同步解耦微服務之間的呼叫;
Spring Boot
Spring Boot 透過簡單的步驟就可以建立一個 Spring 應用。 Spring Boot 為 Spring 整合第三方框架提供了開箱即用功能。 Spring Boot 的核心思想是約定大於配置。
搭建後端框架時需要手動新增 Maven 配置,涉及很多 XML 配置檔案,增加了搭建難度和時間成本。
將專案編譯成 war 包,部署到 Tomcat 中,專案部署依賴 Tomcat,這樣非常不方便。
應用監控做的比較簡單,通常都是透過一個沒有任何邏輯的介面來判斷應用的存活狀態。
spring-boot-starter-web //用於快速構建基於 Spring MVC 的 Web 專案。spring-boot-starter-data-redis //用於快速整合並操作 Redis。spring-boot-starter-data-mongodb //用於對 MongoDB 的整合。spring-boot-starter-data-jpa //用於操作 MySQL。
自定義一個Starter
建立 Starter 專案,定義 Starter 需要的配置(Properties)類,比如資料庫的連線資訊;
編寫自動配置類,自動配置類就是獲取配置,根據配置來自動裝配 Bean;
編寫 spring.factories 檔案載入自動配置類,Spring 啟動的時候會掃描 spring.factories 檔案;
編寫配置提示檔案 spring-configuration-metadata.json(不是必須的),在新增配置的時候,我們想要知道具體的配置項是什麼作用,可以透過編寫提示檔案來提示;
在專案中引入自定義 Starter 的 Maven 依賴,增加配置值後即可使用。
顯示應用程式的監控狀態、檢視 JVM 和執行緒資訊
應用程式上下線監控
視覺化的檢視日誌、動態切換日誌級別
HTTP 請求資訊跟蹤等實用功能
GateWay / Zuul
GateWay⽬標是取代Netflflix Zuul,它基於Spring5.0+SpringBoot2.0+WebFlux等技術開發,提供統⼀的路由⽅式(反向代理)並且基於 Filter(定義過濾器對請求過濾,完成⼀些功能) 鏈的⽅式提供了⽹關基本的功能,例如:鑑權、流量控制、熔斷、路徑重寫、⽇志監控。
路由route: ⽹關最基礎的⼯作單元。路由由⼀個ID、⼀個⽬標URL、⼀系列的斷⾔(匹配條件判斷)和Filter過濾器組成。如果斷⾔為true,則匹配該路由。
斷⾔predicates:參考了Java8中的斷⾔Predicate,匹配Http請求中的所有內容(類似於nginx中的location匹配⼀樣),如果斷⾔與請求相匹配則路由。
過濾器filter:標準的Spring webFilter,使⽤過濾器在請求之前或者之後執⾏業務邏輯。
請求前pre型別過濾器:做引數校驗、許可權校驗、流量監控、⽇志輸出、協議轉換等;
請求前post型別的過濾器:做響應內容、響應頭的修改、⽇志的輸出、流量監控等。
Eureka / Zookeeper
服務註冊中⼼本質上是為了解耦服務提供者和服務消費者,為了⽀持彈性擴縮容特性,⼀個微服務的提供者的數量和分佈往往是動態變化的。
us-east-1c、us-east-1d,us-east-1e代表不同的機房,每⼀個Eureka Server都是⼀個叢集;
Service作為服務提供者向Eureka中註冊服務,Eureka接受到註冊事件會在叢集和分割槽中進⾏資料同步,Client作為消費端(服務消費者)可以從Eureka中獲取到服務註冊資訊,進⾏服務調⽤;
微服務啟動後,會週期性地向Eureka傳送⼼跳(預設週期為30秒)以續約⾃⼰的資訊;
Eureka在⼀定時間內(預設90秒)沒有接收到某個微服務節點的⼼跳,Eureka將會登出該微服務節點;
Eureka Client會快取Eureka Server中的資訊。即使所有的Eureka Server節點都宕掉,服務消費者依然可以使⽤快取中的資訊找到服務提供者;
新服務上線後,服務消費者不能立即訪問到剛上線的新服務,需要過⼀段時間後才能訪問?或是將服務下線後,服務還是會被調⽤到,⼀段時候後才徹底停⽌服務,訪問前期會導致頻繁報錯!
第⼀層快取是readOnlyCacheMap,採⽤ConcurrentHashMap來儲存資料的,主要負責定時與readWriteCacheMap進⾏資料同步,預設同步時間為 30 秒⼀次。
第⼆層快取是readWriteCacheMap,採⽤Guava來實現快取。快取過期時間預設為180秒,當服務下線、過期、註冊、狀態變更等操作都會清除此快取中的資料。
如果兩級快取都無法查詢,會觸發快取的載入,從儲存層拉取資料到快取中,然後再返回給 Client。
Eureka之所以設計⼆級快取機制,也是為了提⾼ Eureka Server 的響應速度,缺點是快取會導致 Client獲取不到最新的服務例項資訊,然後導致⽆法快速發現新的服務和已下線的服務。
我們可以縮短讀快取的更新時間讓服務發現變得更加及時,或者直接將只讀快取關閉,同時可以縮短客戶端如ribbon服務的定時重新整理間隔,多級快取也導致C層⾯(資料⼀致性)很薄弱。
Eureka Server 中會有定時任務去檢測失效的服務,將服務例項資訊從登錄檔中移除,也可以將這個失效檢測的時間縮短,這樣服務下線後就能夠及時從登錄檔中清除。
期望最小每分鐘能夠續租的次數(例項* 頻率 * 比例==10* 2 *0.85) 期望的服務例項數量(10)
Eureka Client 會定時傳送心跳給 Eureka Server 來證明自己處於健康的狀態;
整合SBA以後可以把所有健康狀態資訊一併返回給eureka;
Feign / Ribbon
Feign 可以與 Eureka 和 Ribbon 組合使用以支援負載均衡; Feign 可以與 Hystrix 組合使用,支援熔斷回退; Feign 可以與ProtoBuf實現快速的RPC呼叫;
InvocationHandlerFactory 代理
採用 JDK 的動態代理方式生成代理物件,當我們呼叫這個介面,實際上是要去呼叫遠端的 HTTP API;
Contract 契約元件
比如請求型別是 GET 還是 POST,請求的 URI 是什麼;
Encoder 編碼元件 \ Decoder 解碼元件
透過該元件我們可以將請求資訊採用指定的編碼方式進行編解碼後傳輸;
Logger 日誌記錄
負責 Feign 中記錄日誌的,可以指定 Logger 的級別以及自定義日誌的輸出;
Client 請求執行元件
負責 HTTP 請求執行的元件,Feign 中預設的 Client 是透過 JDK 的 HttpURLConnection 來發起請求的,在每次傳送請求的時候,都會建立新的 HttpURLConnection 連結,Feign 的效能會很差,可以透過擴充套件該介面,使用 Apache HttpClient 等基於連線池的高效能 HTTP 客戶端。
Retryer 重試元件
負責重試的元件,Feign 內建了重試器,當 HTTP 請求出現 IO 異常時,Feign 會限定一個最大重試次數來進行重試操作。
RequestInterceptor 請求攔截器
可以為 Feign 新增多個攔截器,在請求執行前設定一些擴充套件的引數資訊。
繼承特性
攔截器
比如新增指定的請求頭資訊,這個可以用在服務間傳遞某些資訊的時候。
GET 請求多引數傳遞
日誌配置
FULL 會輸出全部完整的請求資訊。
異常解碼器
異常解碼器中可以獲取異常資訊,而不是簡單的一個code,然後轉換成對應的異常物件返回。
原始碼檢視是如何繼承Hystrix
HystrixFeign.builder 中可以看到繼承了 Feign 的 Builder,增加了 Hystrix的SetterFactory, build 方法裡,對 invocationHandlerFactory 進行了重寫, create 的時候返回HystrixInvocationHandler, 在 invoke 的時候會將請求包裝成 HystrixCommand 去執行,這裡就自然的整合了 Hystrix。
原生 API,Ribbon 是 Netflix 開源的,沒有使用 Spring Cloud,需要使用 Ribbon 的原生 API;
Ribbon + RestTemplate,整合Spring Cloud 後,可以基於 RestTemplate 提供負載均衡的服務;
Ribbon + Feign;
RoundRobinRule 是輪詢的演算法,A和B輪流選擇。
RandomRule 是隨機演算法,這個就比較簡單了,在服務列表中隨機選取。
BestAvailableRule 選擇一個最小的併發請求 server。
實現 Irule 介面 繼承 AbstractLoadBalancerRule 類
灰度釋出
灰度釋出是能夠平滑過渡的一種釋出方式,在釋出過程中,先發布一部分應用,讓指定的使用者使用剛釋出的應用,等到測試沒有問題後,再將其他的全部應用釋出。如果新發布的有問題,只需要將這部分恢復即可,不用恢復所有的應用。
多版本隔離
多版本隔離跟灰度釋出類似,為了相容或者過度,某些應用會有多個版本,這個時候如何保證 1.0 版本的客戶端不會呼叫到 1.1 版本的服務,就是我們需要考慮的問題。
故障隔離
當線上某個例項發生故障後,為了不影響使用者,我們一般都會先留存證據,比如:執行緒資訊、JVM 資訊等,然後將這個例項重啟或直接停止。然後線下根據一些資訊分析故障原因,如果我能做到故障隔離,就可以直接將出問題的例項隔離,不讓正常的使用者請求訪問到這個出問題的例項,只讓指定的使用者訪問,這樣就可以單獨用特定的使用者來對這個出問題的例項進行測試、故障分析等。
Hystrix / Sentinel
封裝請求會將使用者的操作進行統一封裝,統一封裝的目的在於進行統一控制。
資源隔離限流會將對應的資源按照指定的型別進行隔離,比如執行緒池和訊號量。
計數器限流,例如5秒內技術1000請求,超數後限流,未超數重新計數;
滑動視窗限流,解決計數器不夠精確的問題,把一個視窗拆分多滾動視窗;
令牌桶限流,類似景區售票,售票的速度是固定的,拿到令牌才能去處理請求;
漏桶限流,生產者消費者模型,實現了恆定速度處理請求,能夠絕對防止突發流量;
失敗回退其實是一個備用的方案,就是說當請求失敗後,有沒有備用方案來滿足這個請求的需求。
斷路器這個是最核心的,,如果斷路器處於開啟的狀態,那麼所有請求都將失敗,執行回退邏輯。如果斷路器處於關閉狀態,那麼請求將會被正常執行。有些場景我們需要手動開啟斷路器強制降級。
指標監控會對請求的生命週期進行監控,請求成功、失敗、超時、拒絕等狀態,都會被監控起來。
配置可以對接配置中心進行動態調整
Hystrix 的配置項非常多,如果不對接配置中心,所有的配置只能在程式碼裡修改,在叢集部署的難以應對緊急情況,我們專案只設定一個 CommandKey,其他的都在配置中心進行指定,緊急情況如需隔離部分請求時,只需在配置中心進行修改以後,強制更新即可。
回退邏輯中可以手動埋點或者透過輸出日誌進行告警
當請求失敗或者超時,會執行回退邏輯,如果有大量的回退,則證明某些服務出問題了,這個時候我們可以在回退的邏輯中進行埋點操作,上報資料給監控系統,也可以輸出回退的日誌,統一由日誌收集的程式去進行處理,這些方式都可以將問題暴露出去,然後透過實時資料分析進行告警操作。
用 ThreadLocal配合執行緒池隔離模式需當心
當我們用了執行緒池隔離模式的時候,被隔離的方法會包裝成一個 Command 丟入到獨立的執行緒池中進行執行,這個時候就是從 A 執行緒切換到了 B 執行緒,ThreadLocal 的資料就會丟失。
Gateway中多用訊號量隔離
閘道器是所有請求的入口,路由的服務數量會很多,幾十個到上百個都有可能,如果用執行緒池隔離,那麼需要建立上百個獨立的執行緒池,開銷太大,用訊號量隔離開銷就小很多,還能起到限流的作用。
Sentinel是⼀個⾯向雲原⽣微服務的流量控制、熔斷降級元件。 替代Hystrix,針對問題:服務雪崩、服務降級、服務熔斷、服務限流
獨⽴可部署Dashboard(基於 Spring Boot 開發)控制檯元件; 不依賴任何框架/庫,減少程式碼開發,透過UI界⾯配置即可完成細粒度控制;
Sentinel不會像Hystrix那樣放過⼀個請求嘗試⾃我修復,就是明明確確按照時間窗⼝來,熔斷觸發後,時間窗⼝內拒絕請求,時間窗⼝後就恢復。
Sentinel Dashboard中新增的規則資料儲存在記憶體,微服務停掉規則資料就消失,在⽣產環境下不合適。可以將Sentinel規則資料持久化到Nacos配置中⼼,讓微服務從Nacos獲取。
Config / Nacos
Nacos是阿⾥巴巴開源的⼀個針對微服務架構中服務發現、配置管理和服務管理平臺。 Nacos就是註冊中⼼+配置中⼼的組合(Nacos=Eureka+Confifig+Bus)
服務發現與健康檢查 動態配置管理 動態DNS服務 服務和後設資料管理
Namespace 代表不同的環境,如開發dev、測試test、⽣產環境prod Group 代表某項⽬,⽐如爪哇雲項⽬ Service 某個項⽬中具體xxx服務 DataId 某個項⽬中具體的xxx配置⽂件
Bus / Stream
Spring Cloud Stream 訊息驅動元件幫助我們更快速,更⽅便的去構建訊息驅動微服務的; 本質:遮蔽掉了底層不同MQ訊息中介軟體之間的差異,統⼀了MQ的程式設計模型,降低了學習、開發、維護MQ的成本,⽬前⽀持Rabbit、Kafka兩種訊息;
Sleuth / Zipkin
安全認證
Session
認證中最常用的一種方式,也是最簡單的。存在多節點session丟失的情況,可透過nginx粘性Cookie和Redis集中式Session儲存解決。
HTTP Basic Authentication
服務端針對請求頭中base64加密的Authorization 和使用者名稱和密碼進行校驗。
Token
Session 只是一個 key,會話資訊儲存在後端。而 Token 中會儲存使用者的資訊,然後透過加密演算法進行加密,只有服務端才能解密,服務端拿到 Token 後進行解密獲取使用者資訊。
JWT認證
JWT(JSON Web Token)使用者提供使用者名稱和密碼給認證伺服器,伺服器驗證使用者提交資訊的合法性;如果驗證成功,會產生並返回一個 Token,使用者可以使用這個 Token 訪問伺服器上受保護的資源。
認證服務提供認證的 API,校驗使用者資訊,返回認證結果;
透過JWTUtils中的RSA演算法,生成JWT token,token裡封裝使用者id和有效期;
服務間引數透過請求頭進行傳遞,服務內部透過 ThreadLocal 進行上下文傳遞;
Hystrix導致ThreadLocal失效的問題可以透過,重寫 Hystrix 的 Callable 方法,傳遞需要的資料;
設定較短(合理)的過期時間。
登出的 Token 及時清除(放入 Redis 中做一層過濾)。
雖然不能修改 Token 的資訊,但是能在驗證層面做一層過濾來進行處理。
監控 Token 的使用頻率。
為了防止資料被別人爬取,最常見的就是監控使用頻率,程式寫出來的爬蟲程式訪問頻率是有跡可循的
核心功能敏感操作可以使用動態驗證(驗證碼)。
比如提現的功能,要求在提現時再次進行驗證碼的驗證,防止不是本人操作。
網路環境、瀏覽器資訊等識別。
銀行 APP 對環境有很高的要求,使用時如果斷網,APP 會自動退出,重新登入,因為網路環境跟之前使用的不一樣了,還有一些瀏覽器的資訊之類的判斷,這些都是可以用來保證後端 API 的安全。
加密金鑰支援動態修改。
如果 Token 的加密金鑰洩露了,也就意味著別人可以偽造你的 Token,可以將金鑰儲存在配置中心,以支援動態修改重新整理,需要注意的是建議在流量低峰的時候去做更換的操作,否則 Token 全部失效,所有線上的請求都會重新申請 Token,併發量會比較大。
灰度釋出
服務數量多,業務變動頻繁,一週一發布;
灰度釋出能降低釋出失敗風險,減少影響範圍;
透過灰度釋出,先讓一部分使用者體驗新的服務,或者只讓測試人員進行測試,等功能正常後再全部發布,這樣能降低釋出失敗帶來的影響範圍;
當釋出出現故障時,可以快速回滾,不影響使用者; 灰度後如果發現這個節點有問題,那麼只需回滾這個節點即可,當然不回滾也沒關係,透過灰度策略隔離,也不會影響正常使用者;
基於Discovery 服務註冊發現、Ribbon 負載均衡、Feign 和 RestTemplate 呼叫等元件的企業級微服務開源解決方案,包括灰度釋出、灰度路由、服務隔離等功能。
首先將需要釋出的服務從轉發過程中移除,等流量剔除之後再發布。
部分機器中的版本進行升級,使用者預設還是請求老的服務,透過版本來支援測試請求。
測試完成之後,讓新的版本接收正常流量,然後部署下一個節點,以此類推。
grayVersions = {"discovery-article-service":["1.01"]}
多版本隔離
各元件調優
server.tomcat.accept-count //請求佇列排隊數server.tomcat.max-threads //最大執行緒數server.tomcat.max-connections //最大連線數
Hystrix 的訊號量(semaphore)隔離模式,併發量上不去很大的原因都在這裡,訊號量預設值是 100,也就是最大併發只有 100,超過 100 就得等待。
//訊號量zuul.semaphore.max-semaphores //訊號量:最大併發數//執行緒池hystrix.threadpool.default.coreSize //最大執行緒數hystrix.threadpool.default.maximumSize //佇列的大hystrix.threadpool.default.maxQueueSize //等引數
gateway.host.max-per-route-connections //每個路由的連線數 gateway.host.max-total-connections //總連線數
ribbon.MaxConnectionsPerHost //單服務併發數ribbon.MaxTotalConnections //總併發數
feign.httpclient.max-connections-per-route//每個路由的連線數feign.httpclient.max-connections //總連線數
來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70024924/viewspace-3007525/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 這些年背過的面試題——MySQL篇面試題MySql
- 這些年背過的面試題——Redis篇面試題Redis
- 這些年背過的面試題——Kafka篇面試題Kafka
- 轉載 -這些年背過的面試題——架構設計篇面試題架構
- 面試雲端計算崗位時這些面試題不能錯過面試題
- 【面試篇】金九銀十面試季,這些面試題你都會了嗎?面試題
- 最新阿里Java面試題,這些面試題你會嗎?阿里Java面試題
- 面試中的這些坑,你踩過幾個?面試
- 面試 HTTP ,99% 的面試官都愛問這些問題面試HTTP
- 那些年,碰上過的面試題面試題
- MyBatis面試題集合,90%會遇到這些問題MyBatis面試題
- 征服面試官:OkHttp 原理篇 掌握這篇面試題彙總,吊打面試官!HTTP面試題
- 面試現場:這些常問的面試題你都會了嗎面試題
- 這些 SpringBoot 面試題你會嗎?Spring Boot面試題
- 這些 iOS 面試基礎題,你會麼?iOS面試
- 有了這些java面試題目和答案,你還有什麼過不去的梗Java面試題
- 3年Java工程師面試必問!這些題一定要會!Java工程師面試
- 2020年SpringCloud 必知的18道面試題SpringGCCloud面試題
- 做到這些面試事半功倍面試
- 08年出的一些前端面試題前端面試題
- Linux常見面試題,這些你知道多少?Linux面試題
- CEO面試你時喜歡問這些問題面試
- 這些javascript面試題,你做對了幾道?JavaScript面試題
- 講課這些天(二):那些年踩過的坑
- C,java,Python,這些名字背後的江湖!JavaPython
- 看了這篇Dubbo RPC面試題,讓天下沒有難面的面試題!RPC面試題
- 前端開發面試題——HTML篇(你想要的,都在這裡)前端面試題HTML
- 大廠Android面試,居然還問這些問題!Android面試
- 學習Python這些面試題你都知道嗎?Python面試題
- 跳槽時,這些Java面試題99%會被問到Java面試題
- 你可能也罵過這兩個面試題!面試題
- 看完這篇關於MVVM的文章,面試通過率提升了80%MVVM面試
- 前端面試送命題:面試題篇前端面試題
- 面試中關於Redis的問題看這篇就夠了面試Redis
- 這些瀏覽器面試題,看看你能回答幾個?瀏覽器面試題
- 這些年網際網路公司們做過的那些弊
- 看完這篇 HashSet,跟面試官扯皮沒問題了面試
- 這是面試專題系列第四篇,Dubbo系列面試