Java面試題-互聯網中間件(持續更新)

Flume Agent三個組件:Source、Channel、Sink

  Source 專門用來收集數據,可以處理各種類型、各種格式的日誌數據,比如avro、exec、HTTP、Kafka、Spooling Directory等。
  Channel 是一個存儲Source已經接收到的數據的緩衝區,簡單來說就是對Source採集到數據進行緩存,可以緩存在memory、file、jdbc、Kafka等。
  Sink 用於把數據發送到目的地,目的地可以是:HDFS、Hive、HBase、ES、Kafka、Logger。

Flume 運行機制

  flume的核心就是一個agent,這個agent對外有兩個進行交互的地方,一個是接受數據的輸入——source,一個是數據的輸出sink,sink負責將數據發送到外部指定的目的地。source接收到數據之後,將數據發送給channel,chanel作爲一個數據緩衝區會臨時存放這些數據,隨後sink會將channel中的數據發送到指定的地方—-例如HDFS等,注意:只有在sink將channel中的數據成功發送出去之後,channel纔會將臨時數據進行刪除,這種機制保證了數據傳輸的可靠性與安全性

什麼是分佈式系統?

  分佈式系統是支持分佈式處理的軟件系統包括分佈式操作系統、分佈式程序設計語言及其編譯系統、分佈式文件系統分佈式數據庫系統等
  1.增大系統容量。我們的業務量越來越大,而要能應對越來越大的業務量,一臺機器的性能已經無法滿足了,我們需要多臺機器才能應對大規模的應用場景。所以,我們需要垂直或是水平拆分業務系統,讓其變成一個分佈式的架構。
  2.加強系統可用。我們的業務越來越關鍵,需要提高整個系統架構的可用性,這就意味着架構中不能存在單點故障。這樣,整個系統不會因爲一臺機器出故障而導致整體不可用。所以,需要通過分佈式架構來冗餘系統以消除單點故障,從而提高系統的可用性。
  3.因爲模塊化,所以系統模塊重用度更高。
  4.因爲軟件服務模塊被拆分,開發和發佈速度可以並行而變得更快。
  5.系統擴展性更高。
  6.團隊協作流程也會得到改善。

爲什麼使用消息隊列

  核心的有 3 個:解耦、異步、削峯。

ElasticSearch

  ElasticSearch 設計的理念就是分佈式搜索引擎,底層其實還是基於 lucene 的

ElasticSearch節點

候選主節點(Master-eligible node)

  集羣中會從候選主節點中選舉出一個主節點,主節點負責創建索引、刪除索引、分配分片、追蹤集羣中的節點狀態等工作。Elasticsearch中的主節點的工作量相對較輕,用戶的請求可以發往任何一個節點,由該節點負責分發和返回結果,而不需要經過主節點轉發。

數據節點(Data node)

  數據節點負責數據的存儲和相關具體操作,比如CRUD、搜索、聚合。所以,數據節點對機器配置要求比較高,首先需要有足夠的磁盤空間來存儲數據,其次數據操作對系統CPU、Memory和IO的性能消耗都很大。

客戶端節點(Client node)

  按照官方的介紹,客戶端節點就是既不做候選主節點也不做數據節點的節點,只負責請求的分發、彙總等等,也就是下面要說到的協調節點的角色。這樣的工作,其實任何一個節點都可以完成,單獨增加這樣的節點更多是爲了負載均衡。

協調節點(Coordinating node)

  協調節點,是一種角色,而不是真實的Elasticsearch的節點,你沒有辦法通過配置項來配置哪個節點爲協調節點。集羣中的任何節點,都可以充當協調節點的角色。

ES 寫數據過程

  客戶端選擇一個 node 發送請求過去,這個 node 就是 coordinating node(協調節點)。coordinating node 對 document 進行路由,將請求轉發給對應的 node(有 primary shard)。然後將數據同步到 replica node。coordinating node 如果發現 primary node 和所有 replica node 都搞定之後,就返回響應結果給客戶端。

ES 讀數據過程

  可以通過 doc id 來查詢,會根據 doc id 進行 hash,判斷出來當時把 doc id 分配到了哪個 shard 上面去,從那個 shard 去查詢。客戶端發送請求到任意一個 node,成爲 coordinate node。
coordinate node 對 doc id 進行哈希路由,將請求轉發到對應的 node,此時會使用 round-robin 隨機輪詢算法,在 primary shard 以及其所有 replica 中隨機選擇一個,讓讀請求負載均衡。接收請求的 node 返回 document 給 coordinate node,coordinate node 返回 document 給客戶端。

es 搜索數據過程

  客戶端發送請求到一個 coordinate node。協調節點將搜索請求轉發到所有的 shard 對應的 primary shard 或 replica shard。query phase:每個 shard 將自己的搜索結果(其實就是一些 doc id)返回給協調節點,由協調節點進行數據的合併、排序、分頁等操作,產出最終結果。fetch phase:接着由協調節點根據 doc id 去各個節點上拉取實際的 document 數據,最終返回給客戶端。

寫數據底層原理

  數據先寫入內存 buffer,然後每隔 1s,將數據 refresh 到 os cache,到了 os cache 數據就能被搜索到(所以我們才說 es 從寫入到能被搜索到,中間有 1s 的延遲)。每隔 5s,將數據寫入 translog 文件(這樣如果機器宕機,內存數據全沒,最多會有 5s 的數據丟失),translog 大到一定程度,或者默認每隔 30mins,會觸發 commit 操作,將緩衝區的數據都 flush 到 segment file 磁盤文件中。數據寫入 segment file 之後,同時就建立好了倒排索引。

dubbo

dubbo 工作原理

  service 層,接口層,給服務提供者和消費者來實現的
  config 層,配置層,主要是對 dubbo 進行各種配置的
  proxy 層,服務代理層,無論是 consumer 還是 provider,dubbo 都會給你生成代理,代理之間進行網絡通信
  registry 層,服務註冊層,負責服務的註冊與發現
  cluster 層,集羣層,封裝多個服務提供者的路由以及負載均衡,將多個實例組合成一個服務
  monitor 層,監控層,對 rpc 接口的調用次數和調用時間進行監控
  protocal 層,遠程調用層,封裝 rpc 調用
  exchange 層,信息交換層,封裝請求響應模式,同步轉異步
  transport 層,網絡傳輸層,抽象 mina 和 netty 爲統一接口
  serialize 層,數據序列化層

dubbo工作流程

  provider 向註冊中心去註冊
  consumer 從註冊中心訂閱服務,註冊中心會通知 consumer 註冊好的服務
  consumer 調用 provider
  consumer 和 provider 都異步通知監控中心

註冊中心掛了可以繼續通信嗎?

  可以,因爲剛開始初始化的時候,消費者會將提供者的地址等信息拉取到本地緩存,所以註冊中心掛了可以繼續通信。

dubbo 有哪些通信協議

dubbo 協議

  默認就是走 dubbo 協議,單一長連接,進行的是 NIO 異步通信,基於 hessian 作爲序列化協議。使用的場景是:傳輸數據量小(每次請求在 100kb 以內),但是併發量很高。

rmi 協議

  走 Java 二進制序列化,多個短連接,適合消費者和提供者數量差不多的情況,適用於文件的傳輸,一般較少用。

hessian 協議

  走 hessian 序列化協議,多個短連接,適用於提供者數量比消費者數量還多的情況,適用於文件的傳輸,一般較少用。

http 協議

  走 json 序列化。

webservice

  走 SOAP 文本序列化。

dubbo 支持哪些序列化協議

(注意通信協議、序列化協議區別)
dubbo 支持 hession、Java 二進制序列化、json、SOAP 文本序列化多種序列化協議。但是 hessian 是其默認的序列化協議。

Hessian 的數據結構

  Hessian 的對象序列化機制有 8 種原始類型:原始二進制數據、boolean、64-bit date(64 位毫秒值的日期)、64-bit double、32-bit int、64-bit long、null、UTF-8 編碼的 string
  另外還包括 3 種遞歸類型:list for lists and arrays、map for maps and dictionaries、object for objects
  還有一種特殊的類型:ref:用來表示對共享對象的引用。

dubbo 負載均衡策略

random loadbalance

  默認情況下,dubbo 是 random load balance ,即隨機調用實現負載均衡,可以對 provider 不同實例設置不同的權重,會按照權重來負載均衡,權重越大分配流量越高,一般就用這個默認的就可以了。

roundrobin loadbalance

  這個的話默認就是均勻地將流量打到各個機器上去,但是如果各個機器的性能不一樣,容易導致性能差的機器負載過高。所以此時需要調整權重,讓性能差的機器承載權重小一些,流量少一些。

leastactive loadbalance

  這個就是自動感知一下,如果某個機器性能越差,那麼接收的請求越少,越不活躍,此時就會給不活躍的性能差的機器更少的請求。

dubbo 集羣容錯策略

failover cluster 模式

  失敗自動切換,自動重試其他機器,默認就是這個,常見於讀操作。(失敗重試其它機器)

failfast cluster 模式

  一次調用失敗就立即失敗,常見於非冪等性的寫操作,比如新增一條記錄(調用失敗就立即失敗)

failsafe cluster 模式

  出現異常時忽略掉,常用於不重要的接口調用,比如記錄日誌。失敗了後臺自動記錄請求,然後定時重發,比較適合於寫消息隊列這種。

forking cluster 模式

  並行調用多個 provider,只要一個成功就立即返回。常用於實時性要求比較高的讀操作,但是會浪費更多的服務資源,可通過 forks=“2” 來設置最大並行數。

broadcacst cluster

  逐個調用所有的 provider。任何一個 provider 出錯則報錯(從2.1.0 版本開始支持)。通常用於通知所有提供者更新緩存或日誌等本地資源信息。

dubbo動態代理策略

  默認使用 javassist 動態字節碼生成,創建代理類。但是可以通過 spi 擴展機制配置自己的動態代理策略。

dubbo的spi 是啥?

  spi,簡單來說,就是 service provider interface,說白了是什麼意思呢,比如你有個接口,現在這個接口有 3 個實現類,那麼在系統運行的時候對這個接口到底選擇哪個實現類呢?這就需要 spi 了,需要根據指定的配置或者是默認的配置,去找到對應的實現類加載進來,然後用這個實現類的實例對象。

zookeeper 的使用場景有哪些

1、分佈式協調
2、分佈式鎖
3、元數據/配置信息管理
4、HA高可用性
  Zookeeper 的核心是原子廣播,這個機制保證了各個Server之間的同步。實現這個機制的協議叫做Zab協議。
Zab協議有兩種模式,它們分別是恢復模式(選主)和廣播模式(同步)。當服務啓動或者在領導者崩潰後,Zab就進入了恢復模式。
  爲了保證事務的順序一致性,zookeeper採用了遞增的事務id號(zxid)來標識事務。所有的提議(proposal)都在被提出的時候加上了zxid。
  實現中zxid是一個64位的數字,它高32位是epoch用來標識leader關係是否改變,每次一個leader被選出來,它都會有一個新的epoch,標識當前屬於那個leader的統治時期。
低32位用於遞增計數。Zookeeper下每個Server在工作過程中有三種狀態,LEADING:當前Server即爲選舉出來的leader。
LOOKING:當前Server不知道leader是誰,正在搜尋;FOLLOWING:leader已經選舉出來,當前Server與之同步

ZooKeeper提供了什麼?

1、文件系統
2、通知機制

Zookeeper文件系統

  每個子目錄項如 NameService 都被稱作爲znode,和文件系統一樣,我們能夠自由的增加、刪除znode,在一個znode下增加、刪除子znode,唯一的不同在於znode是可以存儲數據的。
有四種類型的znode:
1、PERSISTENT-持久化目錄節點
客戶端與zookeeper斷開連接後,該節點依舊存在
2、PERSISTENT_SEQUENTIAL-持久化順序編號目錄節點
客戶端與zookeeper斷開連接後,該節點依舊存在,只是Zookeeper給該節點名稱進行順序編號
3、EPHEMERAL-臨時目錄節點
客戶端與zookeeper斷開連接後,該節點被刪除
4、EPHEMERAL_SEQUENTIAL-臨時順序編號目錄節點
客戶端與zookeeper斷開連接後,該節點被刪除,只是Zookeeper給該節點名稱進行順序編號

ZK服務器角色

Leader
  事務請求的唯一調度和處理者,保證集羣事務處理的順序性,集羣內部各服務的調度者。
Follower
  處理客戶端的非事務請求,轉發事務請求給Leader服務器,參與事務請求Proposal的投票,參與Leader選舉投票。
Observer
  3.3.0版本以後引入的一個服務器角色,在不影響集羣事務處理能力的基礎上提升集羣的非事務處理能力,處理客戶端的非事務請求,轉發事務請求給Leader服務器,不參與任何形式的投票。

Zookeeper 下 Server工作狀態

  服務器具有四種狀態,分別是LOOKING、FOLLOWING、LEADING、OBSERVING。
  LOOKING:尋找Leader狀態。當服務器處於該狀態時,它會認爲當前集羣中沒有Leader,因此需要進入Leader選舉狀態。
  FOLLOWING:跟隨者狀態。表明當前服務器角色是Follower。
  LEADING:領導者狀態。表明當前服務器角色是Leader。
  OBSERVING:觀察者狀態。表明當前服務器角色是Observer。

ZK節點宕機如何處理?

  Zookeeper本身也是集羣,推薦配置不少於3個服務器。Zookeeper自身也要保證當一個節點宕機時,其他節點會繼續提供服務。
  如果是一個Follower宕機,還有2臺服務器提供訪問,因爲Zookeeper上的數據是有多個副本的,數據並不會丟失;
  如果是一個Leader宕機,Zookeeper會選舉出新的Leader。
  ZK集羣的機制是隻要超過半數的節點正常,集羣就能正常提供服務。只有在ZK節點掛得太多,只剩一半或不到一半節點能工作,集羣才失效。所以3個節點的cluster可以掛掉1個節點(leader可以得到2票>1.5),2個節點的cluster就不能掛掉任何1個節點了(leader可以得到1票<=1)。

Zookeeper集羣支持動態添加機器嗎?

  其實就是水平擴容了,Zookeeper在這方面不太好。兩種方式:全部重啓:關閉所有Zookeeper服務,修改配置之後啓動。不影響之前客戶端的會話。逐個重啓:在過半存活即可用的原則下,一臺機器重啓不影響整個集羣對外提供服務。這是比較常用的方式。3.5版本開始支持動態擴容。

chubby是什麼,和zookeeper比你怎麼看?

  chubby是google的,完全實現paxos算法,不開源。zookeeper是chubby的開源實現,使用zab協議,paxos算法的變種。

說幾個zookeeper常用的命令。

常用命令:ls get set create delete等。

ZAB和Paxos算法的聯繫與區別?

相同點:
兩者都存在一個類似於Leader進程的角色,由其負責協調多個Follower進程的運行
Leader進程都會等待超過半數的Follower做出正確的反饋後,纔會將一個提案進行提交
ZAB協議中,每個Proposal中都包含一個 epoch 值來代表當前的Leader週期,Paxos中名字爲Ballot
不同點:
ZAB用來構建高可用的分佈式數據主備系統(Zookeeper),Paxos是用來構建分佈式一致性狀態機系統。

zookeeper選舉

Leader選舉是保證分佈式數據一致性的關鍵所在。當Zookeeper集羣中的一臺服務器出現以下兩種情況之一時,需要進入Leader選舉。
  (1) 服務器初始化啓動。
  (2) 服務器運行期間無法和Leader保持連接。

ZK服務啓動時期的Leader選舉

  若進行Leader選舉,則至少需要兩臺機器,這裏選取3臺機器組成的服務器集羣爲例。在集羣初始化階段,當有一臺服務器Server1啓動時,其單獨無法進行和完成Leader選舉,當第二臺服務器Server2啓動時,此時兩臺機器可以相互通信,每臺機器都試圖找到Leader,於是進入Leader選舉過程。選舉過程如下
  (1) 每個Server發出一個投票,Server1和Server2都會將自己作爲Leader服務器來進行投票,每次投票會包含所推舉的服務器的myid(SID)和ZXID,使用(myid, ZXID)來表示,此時Server1的投票爲(1, 0),Server2的投票爲(2, 0),然後各自將這個投票發給集羣中其他機器。
  (2) 接受來自各個服務器的投票。集羣的每個服務器收到投票後,首先判斷該投票的有效性,如檢查是否是本輪投票、是否來自LOOKING狀態的服務器。
  (3) 處理投票。針對每一個投票,服務器都需要將別人的投票和自己的投票進行PK,PK規則如下
優先檢查ZXID。ZXID比較大的服務器優先作爲Leader。
如果ZXID相同,那麼就比較myid。myid較大的服務器作爲Leader服務器。
  (4) 統計投票。每次投票後,服務器都會統計投票信息,判斷是否已經有過半機器接受到相同的投票信息,對於Server1、Server2而言,都統計出集羣中已經有兩臺機器接受了(2, 0)的投票信息,此時便認爲已經選出了Leader。
  (5) 改變服務器狀態。一旦確定了Leader,每個服務器就會更新自己的狀態,如果是Follower,那麼就變更爲FOLLOWING,如果是Leader,就變更爲LEADING。

服務器運行時期的Leader選舉

  在Zookeeper運行期間,Leader與非Leader服務器各司其職,一旦Leader服務器掛了,那麼整個集羣將暫停對外服務,進入新一輪Leader選舉,其過程和啓動時期的Leader選舉過程基本一致。假設當前Leader是Server2,若某一時刻Leader掛了,此時便開始Leader選舉。選舉過程如下
  (1) 變更狀態。Leader掛後,餘下的非Observer服務器都會講自己的服務器狀態變更爲LOOKING,然後開始進入Leader選舉過程。
  (2) 每個Server會發出一個投票。在運行期間,每個服務器上的ZXID可能不同,此時假定Server1的ZXID爲123,Server3的ZXID爲122;在第一輪投票中,Server1和Server3都會投自己,產生投票(1, 123),(3, 122),然後各自將投票發送給集羣中所有機器。
  (3) 接收來自各個服務器的投票。與啓動時過程相同。
  (4) 處理投票。與啓動時過程相同,此時,Server1將會成爲Leader。
  (5) 統計投票。與啓動時過程相同。
  (6) 改變服務器的狀態。與啓動時過程相同。

Leader選舉算法分析

  在3.4.0後的Zookeeper的版本只保留了TCP版本的FastLeaderElection選舉算法(之前有LeaderElection和UDP版本的FastLeaderElection)。當一臺機器進入Leader選舉時,當前集羣可能會處於以下兩種狀態

集羣中已經存在Leader。

  對於集羣中已經存在Leader而言,此種情況一般都是某臺機器啓動得較晚,在其啓動之前,集羣已經在正常工作,對這種情況,該機器試圖去選舉Leader時,會被告知當前服務器的Leader信息,對於該機器而言,僅僅需要和Leader機器建立起連接,並進行狀態同步即可。

集羣中不存在Leader。

  (1) 第一次投票。無論哪種導致進行Leader選舉,集羣的所有機器都處於試圖選舉出一個Leader的狀態,即LOOKING狀態,LOOKING機器會向所有其他機器發送消息,該消息稱爲投票。投票中包含了SID(服務器的唯一標識)和ZXID(事務ID),(SID, ZXID)形式來標識一次投票信息。假定Zookeeper由5臺機器組成,SID分別爲1、2、3、4、5,ZXID分別爲9、9、9、8、8,並且此時SID爲2的機器是Leader機器,某一時刻,1、2所在機器出現故障,因此集羣開始進行Leader選舉。在第一次投票時,每臺機器都會將自己作爲投票對象,於是SID爲3、4、5的機器投票情況分別爲(3, 9),(4, 8), (5, 8)。
  (2) 變更投票。每臺機器發出投票後,也會收到其他機器的投票,每臺機器會根據一定規則來處理收到的其他機器的投票,並以此來決定是否需要變更自己的投票,這個規則也是整個Leader選舉算法的核心所在,其中術語描述如下
    · vote_sid:接收到的投票中所推舉Leader服務器的SID。
    · vote_zxid:接收到的投票中所推舉Leader服務器的ZXID。
    · self_sid:當前服務器自己的SID。
    · self_zxid:當前服務器自己的ZXID。
  (3) 確定Leader。經過第二輪投票後,集羣中的每臺機器都會再次接收到其他機器的投票,然後開始統計投票,如果一臺機器收到了超過半數的相同投票,那麼這個投票對應的SID機器即爲Leader。此時Server3將成爲Leader。
  由上面規則可知,通常那臺服務器上的數據越新(ZXID會越大),其成爲Leader的可能性越大,也就越能夠保證數據的恢復。如果ZXID相同,則SID越大機會越大。

ZK Leader選舉四種狀態

  服務器具有四種狀態,分別是LOOKING、FOLLOWING、LEADING、OBSERVING。
  LOOKING:尋找Leader狀態。當服務器處於該狀態時,它會認爲當前集羣中沒有Leader,因此需要進入Leader選舉狀態。
  FOLLOWING:跟隨者狀態。表明當前服務器角色是Follower。
  LEADING:領導者狀態。表明當前服務器角色是Leader。
  OBSERVING:觀察者狀態。表明當前服務器角色是Observer。

Kafka 使用 Zookeeper 做什麼?

  kafka使用ZooKeeper用於管理、協調代理。每個Kafka代理通過Zookeeper協調其他Kafka代理。當Kafka系統中新增了代理或某個代理失效時,Zookeeper服務將通知生產者和消費者。生產者與消費者據此開始與其他代理協調工作。
  Zookeeper在Kakfa中扮演的角色:Kafka將元數據信息保存在Zookeeper中,但是發送給Topic本身的數據是不會發到Zk上的kafka使用zookeeper來實現動態的集羣擴展,不需要更改客戶端(producer和consumer)的配置。broker會在zookeeper註冊並保持相關的元數據(topic,partition信息等)更新。
  而客戶端會在zookeeper上註冊相關的watcher。一旦zookeeper發生變化,客戶端能及時感知並作出相應調整。這樣就保證了添加或去除broker時,各broker間仍能自動實現負載均衡。這裏的客戶端指的是Kafka的消息生產端(Producer)和消息消費端(Consumer)。
  Broker端使用zookeeper來註冊broker信息,以及監測partitionleader存活性。
  Consumer端使用zookeeper用來註冊consumer信息,其中包括consumer消費的partition列表等,同時也用來發現broker列表,並和partitionleader建立socket連接,並獲取消息。
  Zookeer和Producer沒有建立關係,只和Brokers、Consumers建立關係以實現負載均衡,即同一個ConsumerGroup中的Consumers可以實現負載均衡(因爲Producer是瞬態的,可以發送後關閉,無需直接等待

Eureka和ZooKeeper的區別

  Eureka和Zookeeper就是CAP定理中的實現,Eureka(保證AP),Zookeeper(保證CP)。
  RDBMS==>(MySql,Oracle,SqlServer等關係型數據庫)遵循的原則是:ACID原則(A:原子性。C:一致性。I:獨立性。D:持久性。)。
  NoSql==> (redis,Mogodb等非關係型數據庫)遵循的原則是:CAP原則(C:強一致性。A:可用性。P:分區容錯性)。在分佈式領域有一個很著名的CAP定理:C:數據一致性。A:服務可用性。P:分區容錯性(服務對網絡分區故障的容錯性)。Consistency(一致性)、 Availability(可用性)、Partition tolerance(分區容錯性)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章