14.7. 对客户端连接进行分区
分区客户端连接涉及每次客户端发起连接时单个客户端到同一代理的路由连接。
分区客户端连接的两个用例是:
- 持久订阅的分区客户端,以确保订阅者始终连接到持久订阅者队列所在的代理。
- 尽量减少将数据移至源自的数据(也称为数据获取)来移动数据的需求。
持久化订阅
持久订阅表示为代理上的队列,在持久订阅者首次连接到代理时创建。此队列保留在代理中,并接收信息,直到客户端取消订阅为止。因此,您希望客户端重复连接到同一代理,以使用订阅者队列中的消息。
要为持久订阅队列对客户端进行分区,您可以在客户端连接中过滤客户端 ID。
Data gravity
如果您在不考虑数据获取的情况下扩展环境中的代理数量,一些性能优势会因为需要在代理之间移动消息而丢失。为了支持日期获取,您应该对客户端连接进行分区,以便客户端消费者连接到生成需要使用消息的代理。
要对客户端连接进行分区,您可以过滤客户端连接的以下任何属性:
- 分配给连接用户(ROLE_NAME)的角色
- 用户的用户名(USER_NAME)
- 客户端的主机名(SNI_HOST)
- 客户端的 IP 地址(SOURCE_IP)
14.7.1. 对客户端连接进行分区以支持持久订阅
要为持久订阅分区客户端,您可以使用一致的哈希算法或正则表达式过滤传入连接中的客户端 ID。
先决条件
客户端被配置为可以连接到集群中的所有代理,例如,通过使用负载均衡器,或连接 URL 中配置的所有代理实例。如果代理拒绝连接,因为客户端详情与该代理的分区配置不匹配,客户端必须能够连接到集群中的其他代理,以查找接受连接的代理。
14.7.1.1. 使用一致的哈希算法过滤客户端 ID
您可以配置集群中的每个代理,以使用一致的哈希算法来为每个客户端连接中的客户端 ID 进行哈希处理。在代理对客户端 ID 进行哈希后,它会在散列值上执行 modulo 操作,以返回整数值,用于标识客户端连接的目标代理。代理将返回的整数值与代理上配置的唯一值进行比较。如果存在匹配项,代理会接受连接。如果值不匹配,代理会拒绝连接。此过程会在集群中的每个代理上重复,直到找到匹配项并接受连接。
流程
-
为第一个代理打开 <
broker_instance_dir> /etc/broker.xml
配置文件。 创建
connection-routers
元素,创建一个connection-route
来使用一致的哈希算法过滤客户端 ID。例如:<configuration> <core> ... <connection-routers> <connection-route name=”consistent-hash-routing”> <key>CLIENT_ID</target-key> <local-target-filter>NULL|0</local-target-filter> <policy name="CONSISTENT_HASH_MODULO"> <property key="modulo" value="<number_of_brokers_in_cluster>"> </property> </policy> </connection-route> </connection-routers> ... </core> </configuration>
connection-route
-
对于
connection-route 名称
,请为此连接路由配置指定一个识别字符串。您必须将此名称添加到您要应用一致的散列过滤器的每个代理接受者。 key
-
将过滤器应用到的密钥类型。要过滤客户端 ID,请在
key
字段中指定CLIENT_ID
。 local-target-filter
-
代理与 modulo 操作返回的整数值进行比较,以确定是否存在匹配项,代理是否可以接受连接。示例中的
NULL|0
值为没有客户端 ID(NULL)的连接提供了匹配的连接,其中 modulo 操作返回的数量为0
。 policy
接受
modulo
属性键,它对散列客户端 ID 执行 modulo 操作,以识别目标代理。modulo
属性键的值必须等于集群中的代理数量。重要策略名称必须是
CONSISTENT_HASH_MODULO
。
-
为第二个代理打开 <
broker_instance_dir> /etc/broker.xml
配置文件。 创建
connection-routers
元素,并使用一致的哈希算法创建一个连接路由
来过滤客户端 ID。在以下示例中,
NULL|1
的local-target-filter
值为没有客户端 ID (NULL)的连接提供匹配,以及 modulo 操作返回的值为1
的连接。<configuration> <core> ... <connection-routers> <connection-route name=”consistent-hash-routing”> <key>CLIENT_ID</target-key> <local-target-filter>NULL|1</local-target-filter> <policy name="CONSISTENT_HASH_MODULO"> <property key="modulo" value="<number_of_brokers_in_cluster>"> </property> </policy> </connection-route> </connection-routers> ... </core> </configuration>
- 重复这个过程,为集群中的每个额外代理创建一个一致的哈希过滤器。
14.7.1.2. 使用正则表达式过滤客户端 ID
您可以通过将代理配置为将正则表达式过滤器应用到客户端连接中的客户端 ID 的一部分来对客户端连接中的客户端连接进行分区。只有在正则表达式过滤器的结果与为代理配置的本地目标过滤器匹配时,代理才会接受连接。如果没有找到匹配项,代理会拒绝连接。此过程会在集群中的每个代理上重复,直到找到匹配项并接受连接。
先决条件
- 每个客户端 ID 中可以通过正则表达式过滤的通用字符串。
流程
-
为第一个代理打开 <
broker_instance_dir> /etc/broker.xml
配置文件。 创建
connection-routers
元素,再创建一个connection-route
来过滤客户端 ID 的一部分。例如:<configuration> <core> ... <connection-routers> <connection-route name=”regex-routing”> <key>CLIENT_ID</target-key> <key-filter>^.{3}</key-filter> <local-target-filter>NULL|CL1</local-target-filter> </connection-route> </connection-routers> ... </core> </configuration>
connection-route
-
对于
connection-route 名称
,请指定此路由配置的标识字符串。您必须将此名称添加到您要应用正则表达式过滤器的每个代理接受者。 key
-
将过滤器应用到的键。要过滤客户端 ID,请在
key
字段中指定CLIENT_ID
。 key-filter
将正则表达式应用到的客户端 ID 字符串的一部分,以提取键值。在上面的第一个代理示例中,代理提取一个键值,它是客户端 ID 的前 3 个字符。例如,如果客户端 ID 字符串为
CL100.consumer
,则代理提取键值CL1
。在代理提取键值后,它会将其与local-target-filter
的值进行比较。如果传入的连接没有客户端 ID,或者代理无法使用为
key-filter
指定的正则表达式提取键值,则键值将设置为 NULL。local-target-filter
-
代理与键值相比的值,以确定是否存在匹配项,代理是否可以接受连接。上面的第一个代理示例中所示
NULL|CL1
的值匹配,匹配客户端 ID (NULL)或客户端 ID 中有 3 个字符前缀CL1
的连接。
-
为第二个代理打开 <
broker_instance_dir> /etc/broker.xml
配置文件。 创建
connection-routers
元素,创建一个连接路由
,以根据客户端 ID 的一部分过滤连接。在以下过滤器示例中,代理使用正则表达式来提取键值,这是客户端 ID 的前 3 个字符。代理将
NULL
和CL2
的值与键值进行比较,以确定是否存在匹配项,代理是否可以接受连接。<configuration> <core> ... <connection-routers> <connection-route name=”regex-routing”> <key>CLIENT_ID</target-key> <key-filter>^.{3}</key-filter> <local-target-filter>NULL|CL2</local-target-filter> </connection-route> </connection-routers> ... </core> </configuration>
- 重复此步骤,并为集群中的每个额外代理创建适当的连接路由过滤器。
14.7.2. 对客户端连接进行分区以支持数据获取
要支持日期的获取,您可以对客户端连接进行分区,以便客户端消费者连接到生成需要使用消息的代理。例如,如果您有一组由制作者和消费者应用程序使用的地址,您可以在特定代理上配置地址。然后,您可以为使用这些地址的生成者和消费者对客户端连接进行分区,以便它们只能连接到该代理。
您可以根据分配给连接用户、用户的用户名或客户端的主机名或 IP 地址等属性对客户端连接进行分区。本节演示了如何通过过滤分配给客户端用户的用户角色来对客户端连接进行分区。如果需要客户端验证连接到代理,您可以将角色分配给客户端用户并过滤连接,以便只有符合角色条件的用户才能连接到代理。
先决条件
- 客户端被配置为可以连接到集群中的所有代理,例如,通过使用负载均衡器,或连接 URL 中配置的所有代理实例。如果代理拒绝连接,因为客户端与为那个代理配置的分区过滤器条件不匹配,客户端必须能够连接到集群中的其他代理,以查找接受连接的代理。
流程
-
为第一个代理打开 <
broker_instance_dir> /etc/artemis-roles.properties
文件。添加broker1users
角色,并将用户添加到角色中。 -
为第一个代理打开 <
broker_instance_dir> /etc/broker.xml
配置文件。 创建一个
connection-routers
元素,创建一个connection-route
,以根据分配给用户的角色过滤连接。例如:<configuration> <core> ... <connection-routers> <connection-route name=”role-based-routing”> <key>ROLE_NAME</target-key> <key-filter>broker1users</key-filter> <local-target-filter>broker1users</local-target-filter> </connection-route> </connection-routers> ... </core> </configuration>
connection-route
-
对于
connection-route 名称
,请指定此路由配置的标识字符串。您必须将此名称添加到您要应用角色过滤器的每个代理接受者。 key
-
将过滤器应用到的键。要配置基于角色的过滤,在
key
字段中指定ROLE_NAME
。 key-filter
-
代理用来过滤用户角色并提取键值的字符串或正则表达式。如果代理找到匹配的角色,它会将 key 值设置为该角色。如果没有找到匹配的角色,代理会将 key 值设置为 NULL。在上例中,代理将
broker1users
的过滤器应用到客户端用户的角色。在代理提取键值后,它会将其与local-target-filter
的值进行比较。 local-target-filter
-
代理与键值相比的值,以确定是否存在匹配项,代理是否可以接受连接。在示例中,代理将
broker1users
的值与键值进行比较。它有一个匹配项,这意味着用户具有broker1users
角色,代理接受连接。
- 重复此步骤并在过滤器中指定适当的角色,以在集群中的其他代理上对客户端进行分区。
14.7.3. 将连接路由添加到接收器
在代理上配置连接路由后,您必须将路由添加到一个或多个代理的 acceptors 来分区客户端连接。将连接路由添加到 acceptor 后,代理会将连接路由中配置的过滤器应用到接受者接收的连接。
流程
-
为第一个代理打开 <
broker_instance_dir> /etc/broker.xml
配置文件。 对于您要启用分区的每个接受者,附加
路由器
密钥并指定connection-route 名称
。在以下示例中,将具有consistent-hash-routing
的connection-route name
添加到artemis
acceptor 中。<configuration> <core> ... <acceptors> ... <!-- Acceptor for every supported protocol --> <acceptor name="artemis">tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;router="consistent-hash-routing" </acceptor> </acceptors> ... </core> </configuration>
- 重复此步骤,为集群中的每个代理指定适当的连接路由过滤器。