1. 程式人生 > >Java相關知識點整理《三》

Java相關知識點整理《三》

19、6種常見的負載均衡演算法。

19.1..輪詢法。

請求按順序輪流分配到後端伺服器,而不關心伺服器連線數和負載能力。

19.2.隨機演算法。

19.3.源地址雜湊演算法。

獲取客戶端IP,雜湊計算後得到一個數值,用該數值對伺服器列表的大小進行取模運算,得到的結果便是客戶端要訪問的伺服器編號。

19.4.加權輪詢演算法。

19.5.加權隨機演算法。

19.6.最小連線數演算法。

請求總是轉發到連線數最小的伺服器上。

20、Zuul相關知識。

Zuul提供了一個框架,可以對過濾器進行動態的載入編譯執行

Zuul過濾器之間沒有直接的相互通訊,他們之間通過一個RequestContext的靜態類來進行資料的傳遞。RequestContext類中有ThreadLocal變數來記錄每個Request所需傳遞的資料。使用ThreadLocal達到執行緒安全目的。

20.1.Zuul四種過濾器型別。

(a)RRE:前置過濾器,這種過濾器在請求被路由之前呼叫。

(b)ROUTING:這種過濾器將請求路由到微服務,使用Apache HTTPClient或者Netflix Ribbon請求微服務。

(c)POST:這種過濾器在路由到微服務以後執行。

(d)ERROR:其他階段發生錯誤時執行該過濾器。

20.2.Zuul兩種內建特殊過濾器。

StaticResponseFilter:允許Zuul本身生成響應,而不是請求轉發到源。

SurgicalCycleFilter:允許將特定請求路由到分隔的除錯叢集和主機。

20.3.ContextLifeCycleFilter到RequestContext的生命週期管理。

ContextLifeCycleFilter的核心功能是為了清除RequestContext;請求上下文RequestContext通過ThreadLocal儲存,需要在請求完畢後刪除該物件。RequestContext提供了執行filter Pipeline所需的Context,因為Servlet是單列多執行緒,這就要求RequestContext既要執行緒安全又要Request安全。Context使用ThreadLocal儲存,這樣每個worker執行緒都有一個與其繫結的RequestContext,因為worker僅能同時處理一個Request,這就保證了RequestContext既是執行緒安全的又是Request安全的。

21、Eureka與Zookeeper的對比。

分散式CAP理論:

C一致性、A可用性、P分割槽容錯性

Zookeeper:基於CP,不保證高可用,如果Zookeeper正在選主,或者Zookeeper叢集中半數以上機器不可用,那麼將無法獲取資料。

Eureka:基於AP,能保證高可用,即使所有的機器掛了,也能拿到本地快取的資料。

22、Kafka學習記錄。

在一個可配置的時間段內,Kafka叢集內保留所有釋出的訊息,不管這些訊息有沒有被消費。比如,如果訊息的儲存策略被設定為兩天,那麼在一個訊息被髮布的兩天內,它都是可以被消費的。之後它將被丟棄以釋放空間。Kafka的效能是和資料量無關的常量級的,所以保留太多的資料並不是問題。

訊息釋出的兩種模式:

(1)佇列模式(queuing)。

Consumers可以同時從服務端讀取訊息,每個訊息只被其中的一個customer讀取到。

(2)釋出—訂閱模式(publish—subscribe)。

訊息被廣播到所有的consumer中。Consumers可以加入一個consumer組,共同競爭同一個topic,topic的訊息將被分發到組中的一個成員中。同一組的consumer可以在不同程式中,也可以在不同機器上。

注:如果所有的consumer都在一個組上,就成為了傳統的佇列模式,在各consumer中實現負載均衡。如果所有的consumer都在不同的組上,就成為了釋出—訂閱模式。

注:consumer組的消費數量不能多於分割槽的數量,也就是有多少分割槽就允許有多少併發消費。

Kafka只能保證一個分割槽之內的訊息的有序性,在不同的分割槽之間是不可以的,這已經可以滿足了大部分應用的需求,如果需要topic中所有訊息的有序性,那就只能讓這個topic只有一個分割槽,當然也就只有一個consumer組消費它。

Producer直接將資料傳送到broker的leader(主節點),不需要再多個節點進行分發。為了幫助producer做到這點,所有的kafka都可以及時的告知:哪些節點是活動的?目標topic、目標分割槽的leader在哪兒。這樣producer就可以直接將訊息傳送到目的地了。

Producer將訊息推送到broker,consumer從broker拉取訊息。

Kafka生產者不能從程式碼上生成topic,只有在伺服器上用命令生成。

23、分散式Session解決方案。

23.1.Session複製。

Tomcat、Jetty伺服器等自帶,配置即可。

使用場景:機器較少,網路流量較少。

缺點:廣播式複製到其餘機器有一定延時,帶來一定的網路開銷。

23.2.客戶端Cookie儲存Session。

缺點:每次那個請求都攜帶Session,佔網絡頻寬;儲存大小收到cookie大小限制;網路傳輸存在安全隱患。

23.3.反向代理Nginx。

外載一層Nginx,反向代理使用使用者IP做hash,以保證每一個IP的請求落在同一臺web-server上。

23.4.集中式快取處理。

Redis叢集儲存,Spring Session儲存Redis。

使用場景:叢集中機器數量較多,網路環境複雜。

缺點:實現複雜,穩定性依賴於快取的穩定性,Session資訊放入快取時要有合理的策略寫入。

24.分散式事務解決方案。

24.1.兩階段提交(2PC)。

增設事務協調器(TC)處理控制事務節點事務。

缺點:多次節點之間的網路通訊,通訊時間較長。

鎖定資源時間長。

不適宜高併發場景。

24.2.補償機制(TCC)。

事務鏈中的任一操作。都對應一個符合回滾規則的逆向操作;若事務鏈的任何操作失敗,則分別呼叫各已被正向操作的回滾操作,進行事務回滾。

24.3.本地訊息表(MQ非同步確保)。

本地訊息表這種實現方式應該是業界使用最多的,其核心思想是將分散式事務拆分成本地事務進行處理。

訊息生產方:需要額外新建一個訊息表,並記錄訊息傳送狀態。訊息表和業務資料要在同一個事務裡提交,也就是說他們要儲存在同一個資料庫裡面。然後訊息會經過MQ傳送到消費方。如果訊息傳送失敗,進行訊息重試機制。

訊息消費方:需要處理這個訊息,完成自己的業務邏輯。此時如果本地事務處理成功,表明已經處理成功了,如果處理失敗,那麼會進行重試機制。如果業務上處理失敗,可以給生產方傳送一個業務補償訊息,通知生產方進行業務回滾。

生產方和消費方定時掃描本地訊息表,把還沒有處理完成的訊息或者傳送失敗的訊息再發送一遍。

25.分散式鎖解決方案。

分散式鎖:保證一個方法在同一時間內只能被同一個執行緒執行。

25.1.基於資料庫實現分散式鎖。

直接建立一張鎖表,然後通過操作該表中的資料來實現。當我們要鎖住某個方法和資源時,就在該表中增加一條記錄,想要釋放鎖是刪除此記錄即可。

基於資料庫的排他鎖來實現分散式鎖(在查詢語句後加上“for update”,資料庫儲存method_name需要建立唯一索引)。

25.2.基於快取實現分散式鎖。

String result=jedis.set(lockKey,requestId,SET_IF_NOT_EXIST,SET_WITH_EXPIRE_TIME,expireTime);

lockKey:獲取鎖的唯一key。

requestId:呼叫客戶端通過UUID.randomUUID().toString()生成requestId並傳遞給被呼叫資源,這就把資源和客戶端繫結,在解鎖的時候就有對應依據。

expireTime:過期時間,過期自動釋放鎖。

實現思想:

(a)獲取鎖的時候,使用setnx加鎖,並使用expire命令為鎖新增一個超時時間,超過該時間則自動解鎖。鎖的value值為一個隨機生成的UUID,通過此在解鎖的時候進行判斷。

(b)獲取鎖的時候還設定一個獲取的超時時間,若超過這個時間則自動放棄獲取鎖。

(c)釋放鎖的時候,通過UUID判斷是不是該鎖,若是該鎖則執行delete進行鎖釋放。

25.3.基於Zookeeper實現分散式鎖。

當每個客戶端對某個資源加鎖時,在Zookeeper上的與該方法對應的指定節點目錄下,生成一個唯一的瞬時有序節點。判斷是否獲取鎖的方式很簡單,只要判斷當前客戶端建立的子節點是否為當前子節點列表中序號最小的子節點,如果是則認為獲得鎖,否則監聽子節點變更訊息,獲得子節點變更通知後重復此步驟直至獲得鎖。完成業務流程後,刪除對應的子節點釋放鎖。

26.Ribbon負載均衡相關知識。

Ribbon是Netflix公司開源的一個負載均衡專案,它屬於客戶端負載均衡器,Feign已經預設使用了Ribbon(Zuul使用Ribbon做負載均衡器,預設採用輪詢演算法)。

LoadBalancerClient的實現類為RibbonLoadBalancerClient,它是最終的負載均衡處理執行器。

IRule用做負載均衡的策略,它有三個方法,其中choose()是根據key來獲取Server,setLoadBalancer()和getLoadBanlancer()是用來設定和獲取ILoadBalance的。

Ribbon提供瞭如下七種負載均衡策略:

(a)BestAvailableRule:選擇一個最小併發請求的Server。

(b)AvailabilityFilteringRule:過濾掉那些高併發的後端Server(active connections超過配置的閥值)。

(c)WeightedResponseTimerRule:根據響應時間分配一個weight,響應時間越長,weight越小,被選中的可能性越低。

(d)RetryRule:對選定的負載均衡策略機上重試機制。

(e)RoundRobinRule:輪詢式選擇Server(預設機制)。

(f)RandomRule:隨機選擇一個Server響應。

(g)ZoneAvoidancdRule:符合判斷server所在區域的效能和server的可用性選擇server。

application.properties配置隨機訪問的示例:

service-B.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadBalancer.RandomRule

27.Spring Security相關知識。

Spring Security就是引入一系列的SecurityFilter,將其新增到Spring中去了;在有請求時,根據URL是否符合每個Filter的規則來判斷是否需要該Filter來進行處理。

幾個核心元件:

(a)SecurityContextHolder。

用於儲存Security Context,主要是當前回話的Principal,預設是使用ThreadLocal來存放這些資訊(執行緒安全);常用於獲取當前使用者的相關資訊,Spring Security使用Authentication來封裝這些資訊。

(b)UserDetails、Principal、Authentication。

Spring Security中使用Authentication儲存當前使用者的主要資訊。Authentication中儲存的是Principal,與UserDetails直接可以強制轉換。UserDetails主要用於儲存使用者名稱、密碼、許可權列表等資訊。Spring Security提供了一個UserDetailService介面,該介面用於查詢並返回一個UserDetails,實現該介面的loadByUsername方法,查詢當前使用者及使用者對許可權列表儲存返回。

(c)GrantedAuthority。

Authentication物件除了getPrincipal()方法呼叫返回使用者基本資訊外,還有getAuthorities()方法可以返回List<GrantedAuthority>。即為使用者的許可權相關資訊,通常都是一些角色資訊。

Spring Security的認證授權實現:

(1)首先需要一個認證管理器AuthenticationManager,他將註冊一個ProviderManager示例;

(2)其次要註冊一個或多個認證provider,即相關的認證邏輯,認證管理器會依次執行這些provider。

(3)這些provider執行之後認證管理器將返回一個完整的Authentication物件或者認證失敗的異常。

(4)假設(3)中的認證成功之後,Authentication將會儲存到Spring Context中,之後該使用者的訪問,都會根據Authentication中的List<GrantedAuthority>判斷是否有訪問許可權。

28.Oauth2的相關知識。

Oauth在“客戶端”與“伺服器提供商”之間,設定了一個授權層。“客戶端”不能直接登入“伺服器提供商”,只能登入授權層,以此將使用者與客戶端區分開來。“客戶端”登入授權層所用的令牌(token),與使用者的密碼不同。使用者可以在登入的時候,指定授權層令牌的授權範圍和有效期。

Oauth2有如下四種授權模式:

(1)授權碼模式。

(a)使用者訪問客戶端,後者將前者導向認證伺服器。

(b)使用者選擇是否給予客戶端授權。

(c)假設使用者給予授權,授權伺服器將使用者導向客戶端事先指定的“重定向URI”,同時附上一個授權碼。

(d)客戶端收到授權碼,附上早先的“重定向URI”,向認證伺服器申請令牌。這一步是在客戶端的後臺伺服器上完成的,對使用者不可見。

(e)認證伺服器核對了授權碼和重定向URI,確認無誤後,向客戶端傳送訪問令牌(access_token)和更新令牌(refresh_token)。

(2)簡化模式。

簡化模式不通過第三方應用程式的伺服器,直接在瀏覽器中向認證伺服器申請令牌,跳過了授權碼這個步驟。

(3)密碼模式。

使用者向客戶端提供自己的使用者名稱和密碼,客戶端使用這些資訊,向“服務提供商”索要授權。

在這種模式下,使用者必須把自己的密碼給客戶端,但是客戶端不得儲存密碼。這種場景通常在對客戶端高度信任的情況下。

(4)客戶端模式。

客戶端以自己的名義,而不是以使用者的名義,向“服務提供商”進行認證。(直接通過傳遞client_id和client_secret向認證伺服器獲取token)。