热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

keycloak集群化的思考

简介单体服务如果想要突破到高并发服务就需要升级为集群服务。同时集群化也为高可用打下了坚实的基础。纵观现在比较流行的服务或者中间件,不管是RabbitMQ还是redis都提供了集群的

目录
  • 简介
  • 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具体是用的集群相关的组件:


...

                
                    
                        
                    
                



...



                
                    
                
                
                    
                       ...
                    
                    
                       ...
                    
                
            
...

主要用的是modcluster,infinispan和jgroups。

除此之外,keycloak还介绍了一种叫做跨数据中心的集群

这种模式主要用在服务是跨数据中心的情况,比如说异地机房这样的容灾性特别强的情况。

看完keycloak的基本集群搭建之后,我们来讲一下keycloak集群中一些比较关键的概念和使用。

load balancing负载均衡

因为是集群结构,所以我们后端是有多台服务器的,那么用户通过客户端来访问我们服务的时候,究竟应该定位到哪一台服务器呢?

这时就要用到负载均衡软件了,也就是load balancing。

一般来说三种负载均衡的方式:

第一种,就是客户端负载均衡,客户端已经知道了服务端的多个服务地址,在发送请求的时候由客户端自行选择要请求的服务地址。

这种模式一般都要配置一个强力的客户端API,通过这个客户端API来进行路由功能,比如说Memcached。

Memcached的神奇来自两阶段哈希(two-stagehash)。Memcached就像一 个巨大的、存储了很多对的哈希表。通过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,则可以这样配置:


   
   
      
      
      ...
   
   ...

如果是AJP forward, 比如使用的是Apache HTTPD + mod-cluster, 则这样配置:


     
     
         
         
         
             ...
             
         
     
        ...
     
         ...
         
     
 

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的博客

欢迎关注我的公众号:「程序那些事」最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!


推荐阅读
  • 2019年后蚂蚁集团与拼多多面试经验详述与深度剖析
    2019年后蚂蚁集团与拼多多面试经验详述与深度剖析 ... [详细]
  • 本文详细介绍了如何在Linux系统中搭建51单片机的开发与编程环境,重点讲解了使用Makefile进行项目管理的方法。首先,文章指导读者安装SDCC(Small Device C Compiler),这是一个专为小型设备设计的C语言编译器,适合用于51单片机的开发。随后,通过具体的实例演示了如何配置Makefile文件,以实现代码的自动化编译与链接过程,从而提高开发效率。此外,还提供了常见问题的解决方案及优化建议,帮助开发者快速上手并解决实际开发中可能遇到的技术难题。 ... [详细]
  • 深入RTOS实践,面对原子操作提问竟感困惑
    在实时操作系统(RTOS)的实践中,尽管已经积累了丰富的经验,但在面对原子操作的具体问题时,仍感到困惑。本文将深入探讨RTOS中的原子操作机制,分析其在多任务环境下的重要性和实现方式,并结合实际案例解析常见的问题及解决方案,帮助读者更好地理解和应用这一关键技术。 ... [详细]
  • 长期以来,关于临时表与表变量的优劣之争一直存在,部分技术社区甚至认为表变量几乎毫无用武之地,如缺乏统计信息、不支持事务处理等。然而,实际情况并非如此绝对。本文将从多个角度对比分析临时表与表变量,探讨它们在不同场景下的应用优势及其潜在局限性,帮助开发者更好地选择合适的数据结构。 ... [详细]
  • Node.js 教程第五讲:深入解析 EventEmitter(事件监听与发射机制)
    本文将深入探讨 Node.js 中的 EventEmitter 模块,详细介绍其在事件监听与发射机制中的应用。内容涵盖事件驱动的基本概念、如何在 Node.js 中注册和触发自定义事件,以及 EventEmitter 的核心 API 和使用方法。通过本教程,读者将能够全面理解并熟练运用 EventEmitter 进行高效的事件处理。 ... [详细]
  • 深入解析 Django 中用户模型的自定义方法与技巧 ... [详细]
  • 在CentOS上部署和配置FreeSWITCH
    在CentOS系统上部署和配置FreeSWITCH的过程涉及多个步骤。本文详细介绍了从源代码安装FreeSWITCH的方法,包括必要的依赖项安装、编译和配置过程。此外,还提供了常见的配置选项和故障排除技巧,帮助用户顺利完成部署并确保系统的稳定运行。 ... [详细]
  • 作为140字符的开创者,Twitter看似简单却异常复杂。其简洁之处在于仅用140个字符就能实现信息的高效传播,甚至在多次全球性事件中超越传统媒体的速度。然而,为了支持2亿用户的高效使用,其背后的技术架构和系统设计则极为复杂,涉及高并发处理、数据存储和实时传输等多个技术挑战。 ... [详细]
  • 当前,众多初创企业对全栈工程师的需求日益增长,但市场中却存在大量所谓的“伪全栈工程师”,尤其是那些仅掌握了Node.js技能的前端开发人员。本文旨在深入探讨全栈工程师在现代技术生态中的真实角色与价值,澄清对这一角色的误解,并强调真正的全栈工程师应具备全面的技术栈和综合解决问题的能力。 ... [详细]
  • 全面解析Java虚拟机:内存模型深度剖析 ... [详细]
  • 深入解析Tomcat:开发者的实用指南
    深入解析Tomcat:开发者的实用指南 ... [详细]
  • 修复一个 Bug 竟耗时两天?真的有那么复杂吗?
    修复一个 Bug 竟然耗费了两天时间?这背后究竟隐藏着怎样的复杂性?本文将深入探讨这个看似简单的 Bug 为何会如此棘手,从代码层面剖析问题根源,并分享解决过程中遇到的技术挑战和心得。 ... [详细]
  • DHCP三层交换机设置方式全局模式和接口模式设置方式和命令resetsave回车输入yreboot输入n输入y重启后就恢复默认设置了默认用户名密码adminAdmin@huawei ... [详细]
  • Android目录遍历工具 | AppCrawler自动化测试进阶(第二部分):个性化配置详解
    终于迎来了“足不出户也能为社会贡献力量”的时刻,但有追求的测试工程师绝不会让自己的生活变得乏味。与其在家消磨时光,不如利用这段时间深入研究和提升自己的技术能力,特别是对AppCrawler自动化测试工具的个性化配置进行详细探索。这不仅能够提高测试效率,还能为项目带来更多的价值。 ... [详细]
  • 初次接触AJAX是在去年,当时主要是通过手动编写客户端代码来实现,还需处理被请求的页面,过程相当繁琐。尽管之前就听说过AJAX.NET,但一直没有机会深入了解。本文将作为初学者的指南,详细介绍AJAX.NET的基本概念、核心功能及其在实际项目中的应用技巧,帮助读者快速上手并掌握这一强大的开发工具。 ... [详细]
author-avatar
孙誉嘉两_365
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有