1. 程式人生 > >Java面試題精選,大型網站系統架構你不得不懂的10個問題

Java面試題精選,大型網站系統架構你不得不懂的10個問題

百度 spring 運行 出現 網站 性能測試 企業 產品 多個

技術分享圖片

作者:JavaGuide(公眾號)

下面這些問題都是一線大廠的真實面試問題,不論是對你面試還是說拓寬知識面都很有幫助。之前發過一篇8 張圖讀懂大型網站技術架構 可以作為不太了解大型網站系統技術架構朋友的入門文章。

文章目錄
1. 你使用過哪些組件或者方法來提升網站性能,可用性以及並發量
2. 設計高可用系統的常用手段
3. 現代互聯網應用系統通常具有哪些特點?
4. 談談你對微服務領域的了解和認識
5. 談談你對 Dubbo 和 Spring Cloud 的認識(兩者關系)
6. 性能測試了解嗎?說說你知道的性能測試工具?
7. 對於一個單體應用系統,隨著產品使用的用戶越來越多,網站的流量會增加,最終單臺服務器無法處理那麽大的流量怎麽辦?


8. 大表優化的常見手段
9. 在系統中使用消息隊列能帶來什麽好處?
1) 通過異步處理提高系統性能
2) 降低系統耦合性
10. 說說自己對 CAP 定理,BASE 理論的了解
CAP 定理
BASE 理論

1. 你使用過哪些組件或者方法來提升網站性能,可用性以及並發量

  1. 提高硬件能力、增加系統服務器。(當服務器增加到某個程度的時候系統所能提供的並發訪問量幾乎不變,所以不能根本解決問題)
  2. 使用緩存(本地緩存:本地可以使用JDK自帶的 Map、Guava Cache.分布式緩存:Redis、Memcache.本地緩存不適用於提高系統並發量,一般是用處用在程序中。比如Spring是如何實現單例的呢?大家如果看過源碼的話,應該知道,Spiring把已經初始過的變量放在一個Map中,下次再要使用這個變量的時候,先判斷Map中有沒有,這也就是系統中常見的單例模式的實現。)
  3. 消息隊列 (解耦+削峰+異步)
  4. .采用分布式開發 (不同的服務部署在不同的機器節點上,並且一個服務也可以部署在多臺機器上,然後利用 Nginx 負載均衡訪問。這樣就解決了單點部署(All In)的缺點,大大提高的系統並發量)
  5. 數據庫分庫(讀寫分離)、分表(水平分表、垂直分表)
  6. 采用集群 (多臺機器提供相同的服務)
  7. 7.CDN 加速 (將一些靜態資源比如圖片、視頻等等緩存到離用戶最近的網絡節點)
  8. 8.瀏覽器緩存
  9. 9.使用合適的連接池(數據庫連接池、線程池等等)
  10. 適當使用多線程進行開發。


2. 設計高可用系統的常用手段

  1. 降級: 服務降級是當服務器壓力劇增的情況下,根據當前業務情況及流量對一些服務和頁面有策略的降級,以此釋放服務器資源以保證核心任務的正常運行。降級往往會指定不同的級別,面臨不同的異常等級執行不同的處理。根據服務方式:可以拒接服務,可以延遲服務,也有時候可以隨機服務。根據服務範圍:可以砍掉某個功能,也可以砍掉某些模塊。總之服務降級需要根據不同的業務需求采用不同的降級策略。主要的目的就是服務雖然有損但是總比沒有好;
  2. 限流: 防止惡意請求流量、惡意攻擊,或者防止流量超出系統峰值;
  3. 緩存: 避免大量請求直接落到數據庫,將數據庫擊垮;
  4. 時和重試機制: 避免請求堆積造成雪崩;
  5. 回滾機制: 快速修復錯誤版本。


3. 現代互聯網應用系統通常具有哪些特點?

  1. 高並發,大流量;
  2. 高可用:系統7×24小時不間斷服務;
  3. 海量數據:需要存儲、管理海量數據,需要使用大量服務器;
  4. 用戶分布廣泛,網絡情況復雜:許多大型互聯網都是為全球用戶提供服務的,用戶分布範圍廣,各地網絡情況千差萬別;
  5. 安全環境惡劣:由於互聯網的開放性,使得互聯網更容易受到攻擊,大型網站幾乎每天都會被黑客攻擊;
  6. 需求快速變更,發布頻繁:和傳統軟件的版本發布頻率不同,互聯網產品為快速適應市場,滿足用戶需求,其產品發布頻率是極高的;
  7. 漸進式發展:與傳統軟件產品或企業應用系統一開始就規劃好全部的功能和非功能需求不同,幾乎所有的大型互聯網網站都是從一個小網站開始,漸進地發展起來。

4. 談談你對微服務領域的了解和認識
現在大公司都在用並且未來的趨勢都是 Spring Cloud,而阿裏開源的 Spring Cloud Alibaba 也是 Spring Cloud 規範的實現 。

我們通常把 Spring Cloud 理解為一系列開源組件的集合,但是 Spring Cloud並不是等同於 Spring Cloud Netflix 的 Ribbon、Feign、Eureka(停止更新)、Hystrix 這一套組件,而是抽象了一套通用的開發模式。它的目的是通過抽象出這套通用的模式,讓開發者更快更好地開發業務。但是這套開發模式運行時的實際載體,還是依賴於 RPC、網關、服務發現、配置管理、限流熔斷、分布式鏈路跟蹤等組件的具體實現。

Spring Cloud Alibaba 是官方認證的新一套 Spring Cloud 規範的實現,Spring Cloud Alibaba 是一套國產開源產品集合,後續還會有中文 reference 和一些原理分析文章,所以,這對於國內的開發者是非常棒的一件事。阿裏的這一舉動勢必會推動國內微服務技術的發展,因為在沒有 Spring Cloud Alibaba 之前,我們的第一選擇是 Spring Cloud Netflix,但是它們的文檔都是英文的,出問題後排查也比較困難, 在國內並不是有特別多的人精通。Spring Cloud Alibaba 由阿裏開源組件和阿裏雲產品組件兩部分組成,其致力於提供微服務一站式解決方案,方便開發者通過 Spring Cloud 編程模型輕松開發微服務應用。

另外,Apache Dubbo Ecosystem 是圍繞 Apache Dubbo 打造的微服務生態,是經過生產驗證的微服務的最佳實踐組合。在阿裏巴巴的微服務解決方案中,Dubbo、Nacos 和 Sentinel,以及後續將開源的微服務組件,都是 Dubbo EcoSystem 的一部分。阿裏後續也會將 Dubbo EcoSystem 集成到 Spring Cloud 的生態中。

5. 談談你對 Dubbo 和 Spring Cloud 的認識(兩者關系)
具體可以看公眾號-阿裏巴巴中間件的這篇文章:獨家解讀:Dubbo Ecosystem - 從微服務框架到微服務生態

Dubbo 與 Spring Cloud 並不是競爭關系,Dubbo 作為成熟的 RPC 框架,其易用性、擴展性和健壯性已得到業界的認可。未來 Dubbo 將會作為 Spring Cloud Alibaba 的 RPC 組件,並與 Spring Cloud 原生的 Feign 以及 RestTemplate 進行無縫整合,實現“零”成本遷移。

在阿裏巴巴的微服務解決方案中,Dubbo、Nacos 和 Sentinel,以及後續將開源的微服務組件,都是 Dubbo EcoSystem 的一部分。我們後續也會將 Dubbo EcoSystem 集成到 Spring Cloud 的生態中。

6. 性能測試了解嗎?說說你知道的性能測試工具?
性能測試指通過自動化的測試工具模擬多種正常、峰值以及異常負載條件來對系統的各項性能指標進行測試。性能測試是總稱,通常細分為:

  1. 基準測試: 在給系統施加較低壓力時,查看系統的運行狀況並記錄相關數做為基礎參考
  2. **負載測試:**是指對系統不斷地增加壓力或增加一定壓力下的持續時間,直到系統的某項或多項性能指標達到安全臨界值,例如某種資源已經達到飽和狀態等 。此時繼續加壓,系統處理能力會下降。
  3. 壓力測試: 超過安全負載情況下,不斷施加壓力(增加並發請求),直到系統崩潰或無法處理任何請求,依此獲得系統最大壓力承受能力。
  4. 穩定性測試: 被測試系統在特定硬件、軟件、網絡環境下,加載一定業務壓力(模擬生產環境不同時間點、不均勻請求,呈波浪特性)運行一段較長時間,以此檢測系統是否穩定。

後端程序員或者測試平常比較常用的測試工具是 JMeter(官網:https://jmeter.apache.org/)。Apache JMeter 是一款基於Java的壓力測試工具(100%純Java應用程序),旨在加載測試功能行為和測量性能。它最初被設計用於 Web 應用測試但後來擴展到其他測試領域。

7. 對於一個單體應用系統,隨著產品使用的用戶越來越多,網站的流量會增加,最終單臺服務器無法處理那麽大的流量怎麽辦?
這個時候就要考慮擴容了。《億級流量網站架構核心技術》這本書上面介紹到我們可以考慮下面幾步來解決這個問題:

  • 第一步,可以考慮簡單的擴容來解決問題。比如增加系統的服務器,提高硬件能力等等。
  • 第二步,如果簡單擴容搞不定,就需要水平拆分和垂直拆分數據/應用來提升系統的伸縮性,即通過擴容提升系統負載能力。
  • 第三步,如果通過水平拆分/垂直拆分還是搞不定,那就需要根據現有系統特性,架構層面進行重構甚至是重新設計,即推倒重來。


對於系統設計,理想的情況下應支持線性擴容和彈性擴容,即在系統瓶頸時,只需要增加機器就可以解決系統瓶頸,如降低延遲提升吞吐量,從而實現擴容需求。

如果你想擴容,則支持水平/垂直伸縮是前提。在進行拆分時,一定要清楚知道自己的目的是什麽,拆分後帶來的問題如何解決,拆分後如果沒有得到任何收益就不要為了
拆而拆,即不要過度拆分,要適合自己的業務。

8. 大表優化的常見手段
當MySQL單表記錄數過大時,數據庫的CRUD性能會明顯下降,一些常見的優化措施如下:

  1. 限定數據的範圍: 務必禁止不帶任何限制數據範圍條件的查詢語句。比如:我們當用戶在查詢訂單歷史的時候,我們可以控制在一個月的範圍內。;
  2. 讀/寫分離: 經典的數據庫拆分方案,主庫負責寫,從庫負責讀;
  3. 垂直分區: 根據數據庫裏面數據表的相關性進行拆分。 例如,用戶表中既有用戶的登錄信息又有用戶的基本信息,可以將用戶表拆分成兩個單獨的表,甚至放到單獨的庫做分庫。簡單來說垂直拆分是指數據表列的拆分,把一張列比較多的表拆分為多張表。 如下圖所示,這樣來說大家應該就更容易理解了。

技術分享圖片

垂直拆分的優點: 可以使得行數據變小,在查詢時減少讀取的Block數,減少I/O次數。此外,垂直分區可以簡化表的結構,易於維護。

垂直拆分的缺點: 主鍵會出現冗余,需要管理冗余列,並會引起Join操作,可以通過在應用層進行Join來解決。此外,垂直分區會讓事務變得更加復雜;

  1. 水平分區: 保持數據表結構不變,通過某種策略存儲數據分片。這樣每一片數據分散到不同的表或者庫中,達到了分布式的目的。 水平拆分可以支撐非常大的數據量。 水平拆分是指數據表行的拆分,表的行數超過200萬行時,就會變慢,這時可以把一張的表的數據拆成多張表來存放。舉個例子:我們可以將用戶信息表拆分成多個用戶信息表,這樣就可以避免單一表數據量過大對性能造成影響。

技術分享圖片

水平拆分可以支持非常大的數據量。需要註意的一點是:分表僅僅是解決了單一表數據過大的問題,但由於表的數據還是在同一臺機器上,其實對於提升MySQL並發能力沒有什麽意義,所以 水平拆分最好分庫 。水平拆分能夠 支持非常大的數據量存儲,應用端改造也少,但 分片事務難以解決 ,跨界點Join性能較差,邏輯復雜。《Java工程師修煉之道》的作者推薦 盡量不要對數據進行分片,因為拆分會帶來邏輯、部署、運維的各種復雜度 ,一般的數據表在優化得當的情況下支撐千萬以下的數據量是沒有太大問題的。如果實在要分片,盡量選擇客戶端分片架構,這樣可以減少一次和中間件的網絡I/O。

下面補充一下數據庫分片的兩種常見方案:

  • 客戶端代理: 分片邏輯在應用端,封裝在jar包中,通過修改或者封裝JDBC層來實現。 當當網的 Sharding-JDBC 、阿裏的TDDL是兩種比較常用的實現。
  • 中間件代理: 在應用和數據中間加了一個代理層。分片邏輯統一維護在中間件服務中。 我們現在談的 Mycat 、360的Atlas、網易的DDB等等都是這種架構的實現。

9. 在系統中使用消息隊列能帶來什麽好處?
《大型網站技術架構》第四章和第七章均有提到消息隊列對應用性能及擴展性的提升。

  1. 通過異步處理提高系統性能

技術分享圖片

如上圖,在不使用消息隊列服務器的時候,用戶的請求數據直接寫入數據庫,在高並發的情況下數據庫壓力劇增,使得響應速度變慢。但是在使用消息隊列之後,用戶的請求數據發送給消息隊列之後立即 返回,再由消息隊列的消費者進程從消息隊列中獲取數據,異步寫入數據庫。由於消息隊列服務器處理速度快於數據庫(消息隊列也比數據庫有更好的伸縮性),因此響應速度得到大幅改善。

通過以上分析我們可以得出消息隊列具有很好的削峰作用的功能——即通過異步處理,將短時間高並發產生的事務消息存儲在消息隊列中,從而削平高峰期的並發事務。 舉例:在電子商務一些秒殺、促銷活動中,合理使用消息隊列可以有效抵禦促銷活動剛開始大量訂單湧入對系統的沖擊。如下圖所示:

技術分享圖片

因為用戶請求數據寫入消息隊列之後就立即返回給用戶了,但是請求數據在後續的業務校驗、寫數據庫等操作中可能失敗。因此使用消息隊列進行異步處理之後,需要適當修改業務流程進行配合,比如用戶在提交訂單之後,訂單數據寫入消息隊列,不能立即返回用戶訂單提交成功,需要在消息隊列的訂單消費者進程真正處理完該訂單之後,甚至出庫後,再通過電子郵件或短信通知用戶訂單成功,以免交易糾紛。這就類似我們平時手機訂火車票和電影票。

2.降低系統耦合性

我們知道模塊分布式部署以後聚合方式通常有兩種:1.分布式消息隊列和2.分布式服務。

先來簡單說一下分布式服務:

目前使用比較多的用來構建SOA(Service Oriented Architecture面向服務體系結構)的分布式服務框架是阿裏巴巴開源的Dubbo.如果想深入了解Dubbo的可以看我寫的關於Dubbo的這一篇文章:《高性能優秀的服務框架-dubbo介紹》:https://juejin.im/post/5acadeb1f265da2375072f9c

再來談我們的分布式消息隊列:

我們知道如果模塊之間不存在直接調用,那麽新增模塊或者修改模塊就對其他模塊影響較小,這樣系統的可擴展性無疑更好一些。

我們最常見的事件驅動架構類似生產者消費者模式,在大型網站中通常用利用消息隊列實現事件驅動結構。如下圖所示:

技術分享圖片

消息隊列使利用發布-訂閱模式工作,消息發送者(生產者)發布消息,一個或多個消息接受者(消費者)訂閱消息。 從上圖可以看到消息發送者(生產者)和消息接受者(消費者)之間沒有直接耦合,消息發送者將消息發送至分布式消息隊列即結束對消息的處理,消息接受者從分布式消息隊列獲取該消息後進行後續處理,並不需要知道該消息從何而來。對新增業務,只要對該類消息感興趣,即可訂閱該消息,對原有系統和業務沒有任何影響,從而實現網站業務的可擴展性設計。

消息接受者對消息進行過濾、處理、包裝後,構造成一個新的消息類型,將消息繼續發送出去,等待其他消息接受者訂閱該消息。因此基於事件(消息對象)驅動的業務架構可以是一系列流程。

另外為了避免消息隊列服務器宕機造成消息丟失,會將成功發送到消息隊列的消息存儲在消息生產者服務器上,等消息真正被消費者服務器處理後才刪除消息。在消息隊列服務器宕機後,生產者服務器會選擇分布式消息隊列服務器集群中的其他服務器發布消息。

備註: 不要認為消息隊列只能利用發布-訂閱模式工作,只不過在解耦這個特定業務環境下是使用發布-訂閱模式的,比如在我們的ActiveMQ消息隊列中還有點對點工作模式,具體的會在後面的文章給大家詳細介紹,這一篇文章主要還是讓大家對消息隊列有一個更透徹的了解。

這個問題一般會在上一個問題問完之後,緊接著被問到。“使用消息隊列會帶來什麽問題?”這個問題要引起重視,一般我們都會考慮使用消息隊列會帶來的好處而忽略它帶來的問題!

10. 說說自己對 CAP 定理,BASE 理論的了解
CAP 定理

技術分享圖片

在理論計算機科學中,CAP定理(CAP theorem),又被稱作布魯爾定理(Brewer’s theorem),它指出對於一個分布式計算系統來說,不可能同時滿足以下三點:

  • 一致性(Consistence) :所有節點訪問同一份最新的數據副本
  • 可用性(Availability):每次請求都能獲取到非錯的響應——但是不保證獲取的數據為最新數據
  • 分區容錯性(Partition tolerance) : 分布式系統在遇到某節點或網絡分區故障的時候,仍然能夠對外提供滿足一致性和可用性的服務。

CAP僅適用於原子讀寫的NOSQL場景中,並不適合數據庫系統。現在的分布式系統具有更多特性比如擴展性、可用性等等,在進行系統設計和開發時,我們不應該僅僅局限在CAP問題上。

註意:不是所謂的3選2(不要被網上大多數文章誤導了):

大部分人解釋這一定律時,常常簡單的表述為:“一致性、可用性、分區容忍性三者你只能同時達到其中兩個,不可能同時達到”。實際上這是一個非常具有誤導性質的說法,而且在CAP理論誕生12年之後,CAP之父也在2012年重寫了之前的論文。

當發生網絡分區的時候,如果我們要繼續服務,那麽強一致性和可用性只能2選1。也就是說當網絡分區之後P是前提,決定了P之後才有C和A的選擇。也就是說分區容錯性(Partition tolerance)我們是必須要實現的。

我在網上找了很多文章想看一下有沒有文章提到這個不是所謂的3選2,用百度半天沒找到了一篇,用谷歌搜索找到一篇比較不錯的,如果想深入學習一下CAP就看這篇文章把,我這裏就不多BB了:《分布式系統之CAP理論》 : http://www.cnblogs.com/hxsyl/p/4381980.html

BASE 理論
BASE 是 Basically Available(基本可用) 、Soft-state(軟狀態) 和 Eventually Consistent(最終一致性) 三個短語的縮寫。BASE理論是對CAP中一致性和可用性權衡的結果,其來源於對大規模互聯網系統分布式實踐的總結,是基於CAP定理逐步演化而來的,它大大降低了我們對系統的要求。

BASE理論的核心思想: 即使無法做到強一致性,但每個應用都可以根據自身業務特點,采用適當的方式來使系統達到最終一致性。也就是犧牲數據的一致性來滿足系統的高可用性,系統中一部分數據不可用或者不一致時,仍需要保持系統整體“主要可用”。

BASE理論三要素:

技術分享圖片

  1. 基本可用: 基本可用是指分布式系統在出現不可預知故障的時候,允許損失部分可用性。但是,這絕不等價於系統不可用。 比如: ①響應時間上的損失:正常情況下,一個在線搜索引擎需要在0.5秒之內返回給用戶相應的查詢結果,但由於出現故障,查詢結果的響應時間增加了1~2秒;②系統功能上的損失:正常情況下,在一個電子商務網站上進行購物的時候,消費者幾乎能夠順利完成每一筆訂單,但是在一些節日大促購物高峰的時候,由於消費者的購物行為激增,為了保護購物系統的穩定性,部分消費者可能會被引導到一個降級頁面;
  2. 軟狀態: 軟狀態指允許系統中的數據存在中間狀態,並認為該中間狀態的存在不會影響系統的整體可用性,即允許系統在不同節點的數據副本之間進行數據同步的過程存在延時;
  3. 最終一致性: 最終一致性強調的是系統中所有的數據副本,在經過一段時間的同步後,最終能夠達到一個一致的狀態。因此,最終一致性的本質是需要系統保證最終數據能夠達到一致,而不需要實時保證系統數據的強一致性。

免費Java資料領取,涵蓋了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo/Kafka、Hadoop、Hbase、Flink等高並發分布式、大數據、機器學習等技術。
傳送門:https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q

Java面試題精選,大型網站系統架構你不得不懂的10個問題