日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

keycloak集群化的思考

發布時間:2024/2/28 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 keycloak集群化的思考 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 簡介
  • keycloak中的集群
  • load balancing負載均衡
    • 暴露客戶端IP地址
    • sticky sessions 和 非sticky sessions
  • shared databases
  • multicasting
  • 總結

簡介

單體服務如果想要突破到高并發服務就需要升級為集群服務。同時集群化也為高可用打下了堅實的基礎。縱觀現在比較流行的服務或者中間件,不管是RabbitMQ還是redis都提供了集群的功能。

作為硬核工業代表的wildfly也不例外,最近研究了一下keycloak的集群,發現它的底層服務器用的也是wildfly,本文將會和大家探討一下keycloak的集群的架構思路。

keycloak中的集群

我們知道,keycloak中有兩種模式,一種叫做Standalone,一種叫做domain。

這兩種模式的區別只是在于部署文件是否被集中管理,如果部署文件需要一個一個的手動拷貝,那么就是standalone模式。如果是一鍵化的自動安裝,那么就是domain模式。

standalone模式下有一個配置文件叫做 /standalone/configuration/standalone-ha.xml,這個就是在standalone模式下配置集群的xml文件了。

而domain模式下,配置文件都是在domain controller這個機子上進行配置的,具體的文件是 domain/configuration/domain.xml 。

我們看下ha具體是用的集群相關的組件:

<profile name="full-ha"> ... <subsystem xmlns="urn:jboss:domain:modcluster:5.0"><proxy name="default" advertise-socket="modcluster" listener="ajp"><dynamic-load-provider><load-metric type="cpu"/></dynamic-load-provider></proxy> </subsystem><subsystem xmlns="urn:jboss:domain:infinispan:11.0"> ... </subsystem><subsystem xmlns="urn:jboss:domain:jgroups:8.0"><channels default="ee"><channel name="ee" stack="udp" cluster="ejb"/></channels><stacks><stack name="udp">...</stack><stack name="tcp">...</stack></stacks></subsystem> ... </profile>

主要用的是modcluster,infinispan和jgroups。

除此之外,keycloak還介紹了一種叫做跨數據中心的集群

這種模式主要用在服務是跨數據中心的情況,比如說異地機房這樣的容災性特別強的情況。

看完keycloak的基本集群搭建之后,我們來講一下keycloak集群中一些比較關鍵的概念和使用。

load balancing負載均衡

因為是集群結構,所以我們后端是有多臺服務器的,那么用戶通過客戶端來訪問我們服務的時候,究竟應該定位到哪一臺服務器呢?

這時就要用到負載均衡軟件了,也就是load balancing。

一般來說三種負載均衡的方式:

第一種,就是客戶端負載均衡,客戶端已經知道了服務端的多個服務地址,在發送請求的時候由客戶端自行選擇要請求的服務地址。

這種模式一般都要配置一個強力的客戶端API,通過這個客戶端API來進行路由功能,比如說Memcached。

Memcached的神奇來自兩階段哈希(two-stagehash)。Memcached就像一 個巨大的、存儲了很多<key,value>對的哈希表。通過key,可以存儲或查詢任意的數據。

客戶端可以把數據存儲在多臺memcached上。當查詢數據時,客戶端首 先參考節點列表計算出key的哈希值(階段一哈希),進而選中一個節點;客戶端將請求發送給選中的節點,然后memcached節點通過一個內部的哈希算法(階段二哈希),查找真正的數據(item)。

第二種,就是代理服務負載均衡,這種模式下,會有一個代理服務器和后端的多個服務進行連接,客戶端是和這個代理服務器進行交互,由代理服務器來代替客戶端選擇到底要路由到哪個服務。

這種代理的路由的軟件就多了,比如我們熟悉的nginx和HTTPD,還有ildFly with mod_cluster, HA Proxy, 或者其他的硬件負載均衡。

第三種,是路由負載均衡,在這種模式下,用戶隨機選擇一個后端服務器進行請求連接,然后在服務器內部進行路由,將這個請求發送到其他的服務器中。

這種模式下,一般需要在服務器內部實現特定的負載均衡功能。

暴露客戶端IP地址

不管使用的是什么模式的負載均衡,我們都有可能在業務中需要使用到客戶訪問的IP地址。

我們在特定的業務中需要獲取到用戶的ip地址來進行一些操作,比如記錄用戶的操作日志,如果不能夠獲取到真實的ip地址的話,則可能使用錯誤的ip地址。還有就是根據ip地址進行的認證或者防刷工作。

如果我們在服務之前使用了反向代理服務器的話,就會有問題。所以需要我們配置反向代理服務器,保證X-Forwarded-For和X-Forwarded-Proto這兩個HTTP header的值是有效的。

然后服務器端就可以從X-Forwarded-For獲取到客戶的真實ip地址了。

在keycloak中,如果是http forwarding,則可以這樣配置:

<subsystem xmlns="urn:jboss:domain:undertow:10.0"><buffer-cache name="default"/><server name="default-server"><ajp-listener name="ajp" socket-binding="ajp"/><http-listener name="default" socket-binding="http" redirect-socket="https"proxy-address-forwarding="true"/>...</server>... </subsystem>

如果是AJP forward, 比如使用的是Apache HTTPD + mod-cluster, 則這樣配置:

<subsystem xmlns="urn:jboss:domain:undertow:10.0"><buffer-cache name="default"/><server name="default-server"><ajp-listener name="ajp" socket-binding="ajp"/><http-listener name="default" socket-binding="http" redirect-socket="https"/><host name="default-host" alias="localhost">...<filter-ref name="proxy-peer"/></host></server>...<filters>...<filter name="proxy-peer"class-name="io.undertow.server.handlers.ProxyPeerAddressHandler"module="io.undertow.core" /></filters></subsystem>

sticky sessions 和 非sticky sessions

如果是在存在session的環境中,比如說web應用程序中,如果后端服務器是cluster的情況下還需要考慮session共享的問題。

因為對于每個服務器來說,它的session都是本地維護的,如果是多臺服務器想要session共享該怎么辦呢?

一種辦法就是所有的服務器都將session存放在同一個外部緩存系統中,比如說redis。這樣不管用戶訪問到哪個server,都可以讀取到同一份session數據。

當然,這個緩存系統可以是單點也可以是集群,如果是不同的數據中心的話,緩存集群甚至還需要跨數據中心進行同步。

緩存同步當然是一個很好的辦法,但是同步行動自然是有開銷的。有沒有更加簡單方便的處理方式呢? 比如固定一個用戶只訪問同一個服務器這樣是不是就能解決緩存同步的問題呢?

這種固定用戶訪問特定某個服務器的模式,我們叫做sticky sessions模式。在這種模式下,可以不用考慮session同步的問題。當然,這種模式下,如果某個服務器down機了,用戶的session就會丟失。所以還是要做一些session同步的工作,只不過不需要實時的同步而已。

另外,sticky session還有一個缺點:如果是后臺的請求,則獲取不到session的信息,也就無法實現sticky session,這個時候就需要進行后臺數據的拷貝,這樣才能保證不管請求發送到哪里都能夠表現一致。

shared databases

所有的應用都需要保存數據。通常來說,我們會有兩種數據:

一種是數據庫數據,這種數據將會永久存儲用戶信息。

一種是cache,用作數據庫和應用程序的緩沖。

不管是哪種數據,都可以有集群模式,也就是多臺服務器同時讀寫數據。這樣對于共享的數據就涉及到了集群數據更新的問題。

集群數據的更新有兩種更新模式:

一種是可靠優先,Active/Active mode,一個節點更新的數據會立馬同步到另外一個節點。

一種是性能優先,Active/Passive mode,一個節點更新的數據不會立馬同步到另外一個節點中。

可靠優先的運行邏輯是,一個更新請求需要等待所有的集群服務返回更新成功才算成功。而性能優先的運行邏輯就是更新完主數據就算成功了,其他的節點會去異步和主數據節點進行同步。

keycloak中使用的緩存是infinispan,并且構建了多種session緩存,不同的緩存使用的是不同的同步策略:

  • authenticationSessions:這個緩存保存的是登錄用戶的信息,如果在sticky sessions模式下,是不需要進行數據同步的。

  • Action tokens:如果用戶需要異步的進行郵件驗證,比如說忘記密碼等操作,則需要用到這種類型的緩存。因為這種操作中的token只能夠被使用一次,所以需要數據的同步。

  • 非認證的session信息:因為不能保證sticky session模式的使用,所以需要復制。

  • loginFailures: 統計用戶的登錄異常情況,不需要被復制。

在緩存保存數據,需要注意數據更新后的失效問題。

在keycloak中,使用了一個單獨的work緩存,這個緩存是所有數據中心同步的,它不存儲實際的數據,只存儲要無效的數據通知。各個數據的服務從work緩存中讀取無效的數據列表,進行相應的數據緩存無效化處理。

multicasting

最后,如果集群需要動態發現和管理節點的功能的話,還需要進行IP廣播。比如說可以使用JGroups來實現這個功能。

總結

keycloak的底層是wildfly,本身已經支持很多強大的工業組件,它的設計理念是讓程序業務邏輯和其他的通用的生產級特性(高可用,負載均衡,緩存集群,消息隊列等)區分開,只用專注于業務邏輯的實現和編寫,其他的事情交給服務器去做即可。

大家可以多研究下這些優秀的服務器框架,可以得到一些不同的體會。

本文作者:flydean程序那些事

本文鏈接:http://www.flydean.com/keycloak-cluster-in-depth/

本文來源:flydean的博客

歡迎關注我的公眾號:「程序那些事」最通俗的解讀,最深刻的干貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

總結

以上是生活随笔為你收集整理的keycloak集群化的思考的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。