9.4. 粘性会话
典型的集群部署由负载均衡器(代理)以及 2 个或更多专用网络上的 Red Hat Single Sign-On 服务器组成。出于性能目的,如果负载均衡器将与特定浏览器会话相关的所有请求转发到同一红帽单点登录后端节点,则可能会很有用。
其原因在于,Red Hat Single Sign-On 正在使用在覆盖下的 Infinispan 分布式缓存来保存与当前身份验证会话和用户会话相关的数据。Infinispan 分布式缓存默认使用一个所有者进行配置。这意味着特定的会话只保存在一个集群节点中,如果其他节点想要访问会话,则其他节点需要远程查找会话。
例如,如果 ID 为 123 的身份验证会话保存在 node1 上的 Infinispan 缓存中,而 node2 需要通过网络将请求发送到 node1,才能返回特定的会话实体。
如果特定会话实体总是在本地可用,可以使用粘性会话的帮助来完成。集群环境中的工作流带有公共前端负载均衡器,两个后端 Red Hat Single Sign-On 节点都可以如下:
- 用户发送初始请求以查看 Red Hat Single Sign-On 登录屏幕
- 此请求由 frontend 负载均衡器提供,它转发到一些随机节点(如 node1)。严格说,节点不需要是随机的,但可以根据其他条件(客户端 IP 地址等)选择。它们都取决于底层负载均衡器(逆向代理)的实施和配置。
- Red Hat Single Sign-On 使用随机 ID (如 123)创建身份验证会话,并将它保存到 Infinispan 缓存。
-
Infinispan 分布式缓存根据会话 ID 的哈希来分配会话的主所有者。有关此问题的详情,请参阅 Infinispan 文档。假设 Infinispan 分配
node2为此会话的所有者。 -
Red Hat Single Sign-On 创建了 Cookie
AUTH_SESSION_ID,其格式类似于 <session-id>.<owner-node-id>。在我们的示例中,它将是123.node2。 - 使用 Red Hat Single Sign-On 登录屏幕和浏览器中的 AUTH_SESSION_ID Cookie 返回响应
此时,如果负载均衡器将所有下一请求转发到 node2,这是节点,其所有者为 ID 为 123,因此 Infinispan 可以在本地查找此会话。身份验证完成后,身份验证会话将转换为用户会话,因此也会保存在 node2 上,因为它具有相同的 ID 123。
在集群设置中不强制使用粘性会话,但出于上述原因,最好是性能。您需要通过 AUTH_SESSION_ID Cookie 将负载平衡器配置为粘性。它如何取决于您的负载均衡器。
建议在 Red Hat Single Sign-On 一侧使用系统属性 jboss.node.name,其值与路由名称对应。例如,-Djboss.node.name=node1 将使用 node1 来识别路由。此路由将由 Infinispan 缓存使用,并在节点是特定密钥的所有者时附加到 AUTH_SESSION_ID Cookie。以下是使用这个系统属性启动命令的示例:
cd $RHSSO_NODE1
./standalone.sh -c standalone-ha.xml -Djboss.socket.binding.port-offset=100 -Djboss.node.name=node1
通常在生产环境中,路由名称应使用与后端主机相同的名称,但这不是必须的。您可以使用不同的路由名称。例如,如果您要隐藏您的专用网络内 Red Hat Single Sign-On 服务器的主机名。
9.4.1. 禁用添加路由 复制链接链接已复制到粘贴板!
某些负载均衡器可以配置为自行添加路由信息,而不依赖于后端 Red Hat Sign-On 节点。但是,如上文所述,建议添加 Red Hat Single Sign-On 路由。这是因为,在这种提升性能时,Red Hat Single Sign-On 知道属于特定会话的实体,并可路由到该节点,这不一定是本地节点。
如果您愿意,可以在 Red Hat Single Sign-On 子系统配置中的 RHSSO_HOME/standalone/configuration/standalone-ha.xml 文件中禁用路由信息到 AUTH_SESSION_ID cookie:
<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
...
<spi name="stickySessionEncoder">
<provider name="infinispan" enabled="true">
<properties>
<property name="shouldAttachRoute" value="false"/>
</properties>
</provider>
</spi>
</subsystem>