集群服务器发现
为了加入正在运行的集群,任何新成员都必须知道集群中至少一些其他服务器的地址。此信息对于连接到服务器、运行发现协议以及获取有关集群的所有信息都是必需的。
Neo4j 提供了几种机制,用于集群成员相互发现并根据配置、集群运行的环境以及使用的 Neo4j 版本来形成集群。
在 Neo4j 5.23 中,引入了发现服务 v2。建议在新部署中使用新版本 v2。 当前版本 v1 已弃用,将在未来的版本中移除。因此,强烈建议从 v1 迁移到 v2。有关详细信息,请参阅 从发现服务 v1 迁移到 v2。 |
新版本 v2 引入了以下配置设置来控制发现服务
-
dbms.cluster.discovery.v2.endpoints
用于在使用 v2 版本时指定发现服务器地址列表。 -
dbms.cluster.discovery.version
用于指定发现服务的版本。可能的值为V1_ONLY
、V2_ONLY
、V1_OVER_V2
和V2_OVER_V1
。 -
dbms.kubernetes.discovery.v2.service_port_name
用于在使用 v2 版本时指定 Kubernetes API 中使用的服务端口名称。
以下部分描述了服务器发现的不同方法、配置设置以及从发现服务 v1 迁移到 v2 的示例。
服务器发现方法
根据当前使用的 dbms.cluster.discovery.resolver_type
类型,发现服务可以使用服务器地址列表、DNS 记录或 Kubernetes 服务来发现集群中的其他服务器。发现配置用于初始发现,并持续交换有关集群拓扑更改的信息。
使用服务器地址列表进行发现
如果事先知道其他集群成员的地址,则可以显式列出它们。但是,此方法存在一些限制,例如
-
如果替换服务器并且新成员具有不同的地址,则列表将过时。可以通过确保可以通过与旧成员相同的地址访问新成员来避免列表过时,但这并不总是可行的。
-
在某些情况下,配置集群时地址未知。例如,当使用容器编排部署集群时,可能会出现这种情况。
要使用此方法,请设置 dbms.cluster.discovery.resolver_type=LIST
并在每个服务器的配置中硬编码地址。例如
dbms.cluster.discovery.resolver_type=LIST
server.cluster.advertised_address=server01.example.com:6000
dbms.cluster.discovery.v2.endpoints=server01.example.com:6000,server02.example.com:6000,server03.example.com:6000
dbms.cluster.discovery.version=V2_ONLY
dbms.cluster.discovery.resolver_type=LIST
server.discovery.advertised_address=server01.example.com:5000
dbms.cluster.discovery.endpoints=server01.example.com:5000,server02.example.com:5000,server03.example.com:5000
dbms.cluster.discovery.version=V1_ONLY
使用发现服务 v1 的此方法的示例由 配置具有三个服务器的集群 说明。
使用具有多个记录的 DNS 进行发现
在无法或不方便显式列出要发现的集群成员的地址的情况下,可以使用基于 DNS 的机制。在这种情况下,服务器启动时会根据配置设置执行 DNS 记录查找。服务器加入集群后,集群中的服务器之间会进一步通信拓扑更改,作为发现服务的一部分。
可以使用以下基于 DNS 的机制来获取集群中其他服务器的地址以进行发现
dbms.cluster.discovery.resolver_type=DNS
-
使用此配置,初始发现成员将从DNS A 记录解析以查找要联系的 IP 地址。在版本 1 中,
dbms.cluster.discovery.endpoints
的值应设置为单个域名和发现服务的端口,而在版本 2 中,dbms.cluster.discovery.v2.endpoints
的值应设置为单个域名和集群公告端口。例如dbms.cluster.discovery.resolver_type=DNS server.cluster.advertised_address=server01.example.com:6000 dbms.cluster.discovery.v2.endpoints=cluster01.example.com:6000 dbms.cluster.discovery.version=V2_ONLY
dbms.cluster.discovery.resolver_type=DNS server.discovery.advertised_address=server01.example.com:5000 dbms.cluster.discovery.endpoints=cluster01.example.com:5000 dbms.cluster.discovery.version=V1_ONLY
执行 DNS 查找时,域名会为集群中的每个服务器返回一个 A 记录,其中每个 A 记录包含服务器的 IP 地址。配置的服务器使用来自 A 记录的所有 IP 地址加入或形成集群。
使用此配置时,所有服务器上的发现端口必须相同。如果无法做到这一点,请考虑使用发现类型
SRV
。 dbms.cluster.discovery.resolver_type=SRV
-
使用此配置,初始发现成员将从DNS SRV 记录解析以查找要联系的 IP 地址/主机名和发现服务端口 (v1) **或** 集群公告端口 (v2)。
dbms.cluster.discovery.endpoints
的值必须设置为单个域名,端口设置为0
。当执行 DNS 查找时,域名会返回单个 SRV 记录。例如dbms.cluster.discovery.resolver_type=SRV server.cluster.advertised_address=server01.example.com:6000 dbms.cluster.discovery.v2.endpoints=cluster01.example.com:0 dbms.cluster.discovery.version=V2_ONLY
DNS 返回的 SRV 记录应包含 IP 地址或主机名,以及要发现的服务器的**集群**端口。配置的服务器使用来自 SRV 记录的所有地址加入或形成集群。
dbms.cluster.discovery.resolver_type=SRV server.discovery.advertised_address=server01.example.com:5000 dbms.cluster.discovery.endpoints=cluster01.example.com:0 dbms.cluster.discovery.version=V1_ONLY
DNS 返回的 SRV 记录应包含 IP 地址或主机名,以及要发现的服务器的**发现**端口。配置的服务器使用来自 SRV 记录的所有地址加入或形成集群。
Kubernetes 中的发现
一个特殊情况是,当集群在 Kubernetes 中运行并且每个服务器都作为 Kubernetes 服务运行时。然后,可以使用列表服务 API 获取其他服务器的地址,如 Kubernetes API 文档 中所述。
以下设置用于配置此场景
-
设置
dbms.cluster.discovery.resolver_type=K8S
。 -
将
dbms.kubernetes.label_selector
设置为集群服务的标签选择器。有关更多信息,请参阅 Kubernetes 官方文档。 -
根据您的发现服务版本,设置
dbms.kubernetes.service_port_name
(v1) 或dbms.kubernetes.discovery.v2.service_port_name
(v2) 为 Kubernetes 服务定义中用于 Core 发现端口的服务端口名称。有关更多信息,请参阅 Kubernetes 官方文档。
使用此配置时,不会使用 dbms.cluster.discovery.endpoints
,并且分配给它的任何值都将被忽略。
发现配置用于初始发现,并持续交换有关集群拓扑更改的信息。
从发现服务 v1 迁移到 v2
从 Neo4j 5.23 开始,您可以从当前的发现服务 v1 迁移到新版本 v2。v1 和 v2 发现服务旨在能够并行运行。它们彼此完全独立,因此允许您在从 v1 切换到 v2 时保持集群正常运行。
根据环境和集群的要求,有三种方法可以从当前的发现服务 v1 迁移到新版本 v2。
准备工作
以下示例假设您有一个运行了三个服务器的集群,并且您希望从当前的发现服务 v1 迁移到新版本 v2。
在从当前的发现服务 v1 迁移到新版本 v2 之前,请确保根据使用的 dbms.cluster.discovery.resolver_type
类型将新设置添加到配置中
-
如果
dbms.cluster.discovery.resolver_type=LIST
,则将dbms.cluster.discovery.v2.endpoints
设置为server.cluster.advertised_address
的逗号分隔列表。在操作过程中,设置dbms.cluster.discovery.endpoints
和dbms.cluster.discovery.v2.endpoints
非常重要。有关更多信息,请参阅 使用服务器地址列表进行发现。 -
如果
dbms.cluster.discovery.resolver_type=DNS
,则将dbms.cluster.discovery.v2.endpoints
设置为单个域名和集群端口。或者,如果dbms.cluster.discovery.resolver_type=SRV
,则将dbms.cluster.discovery.v2.endpoints
设置为单个域名,并将端口设置为0
。在操作过程中,设置dbms.cluster.discovery.endpoints
和dbms.cluster.discovery.v2.endpoints
非常重要。有关更多信息,请参阅 使用具有多个记录的 DNS 进行发现。 -
如果
dbms.cluster.discovery.resolver_type=K8S
,则将dbms.kubernetes.discovery.v2.service_port_name
设置为 Kubernetes 服务定义中用于集群端口的服务端口名称。在操作过程中,设置dbms.kubernetes.service_port_name
和dbms.kubernetes.discovery.v2.service_port_name
非常重要。有关更多信息,请参阅 Kubernetes 中的发现。
就地滚动升级
就地滚动升级会暂时降低容错能力,因为您正在重新启动正在运行的服务器。为了保持容错能力,您可以暂时引入第四台服务器。 |
-
对于所有服务器,请确保根据 准备工作 部分中的详细信息将新设置添加到配置中。
例如,对于使用列表解析器的用户,所有服务器的设置应包括
dbms.cluster.discovery.resolver_type=LIST dbms.cluster.discovery.endpoints=server01.example.com:5000,server02.example.com:5000,server03.example.com:5000 dbms.cluster.discovery.v2.endpoints=server01.example.com:6000,server02.example.com:6000,server03.example.com:6000
-
使用新的设置
dbms.cluster.discovery.version=V1_OVER_V2
重新启动 server01。 -
运行
SHOW SERVERS
并确保所有三个成员都处于活动状态。 -
然后对 server02 和 server03 重复步骤 2 和 3。确保它们设置为
dbms.cluster.discovery.version=V1_OVER_V2
。按顺序重启它们,而不是并行重启。 -
使用
bolt://
连接到服务器1、2、3的系统数据库,并运行以下过程。例如,可以使用./cypher-shell -a bolt://localhost:7681 -d system
来完成此操作。CALL dbms.cluster.showParallelDiscoveryState();
它们应该在
stateComparison
列中显示“Matching”。预期结果+----------------------------------------------------------------+ | mode | stateComparison | v1ServerCount | v2ServerCount | +----------------------------------------------------------------+ | "V1_OVER_V2" | "Matching" | "3" | "3" | +----------------------------------------------------------------+
如果它们没有显示,请等待并重试。
-
使用新的设置
dbms.cluster.discovery.version=V2_OVER_V1
重新启动服务器01。 -
运行
SHOW SERVERS
并确保所有三个成员都处于活动状态。 -
然后对服务器2和3重复步骤6和7。确保它们设置为
dbms.cluster.discovery.version=V2_OVER_V1
。依次重启它们,不要并行重启。 -
类似于步骤5,验证
stateComparison
是否显示Matching
。 -
重复步骤6、7、8、9,依次重新启动服务器1、2和3,并使用新的设置
dbms.cluster.discovery.version=V2_ONLY
-
验证
CALL dbms.cluster.showParallelDiscoveryState()
现在是否显示正在运行的V2_ONLY
。请注意,stateComparison
为N/A
,因为您不再有v1来比较状态。
新服务器滚动
新服务器滚动需要三个正在运行的服务器和三个新的服务器。
-
使用设置
dbms.cluster.discovery.version=V1_OVER_V2
启动三个新的服务器。新服务器应该具有在准备部分中详细说明的更新设置。发现地址应包含新成员和先前成员的地址。
例如,对于使用列表解析器的用户,新服务器的设置应包含
dbms.cluster.discovery.resolver_type=LIST dbms.cluster.discovery.version=V1_OVER_V2 dbms.cluster.discovery.endpoints=server01.example.com:5000,server02.example.com:5000,server03.example.com:5000,server04.example.com:5000,server05.example.com:5000,server06.example.com:5000 dbms.cluster.discovery.v2.endpoints=server01.example.com:6000,server02.example.com:6000,server03.example.com:6000,server04.example.com:6000,server05.example.com:6000,server06.example.com:6000
-
使用
bolt://
连接到服务器4、5、6的系统数据库,并运行以下过程。例如,可以使用./cypher-shell -a bolt://localhost:7685 -d system
来完成此操作。CALL dbms.cluster.showParallelDiscoveryState();
预期结果应显示
v2ServerCount
为3。stateComparison
在此阶段预计不会匹配,因为原始服务器对V2发现服务不可见。预期结果+---------------------------------------------------------------------------------------------------------+ | mode | stateComparison | v1ServerCount | v2ServerCount | +---------------------------------------------------------------------------------------------------------+ | "V1_OVER_V2" | "States are not matching after PT55M36.693S: (score:29)" | "6" | "3" | +---------------------------------------------------------------------------------------------------------+
-
释放、删除并关闭服务器1、2、3。
-
启动服务器7、8、9,这次使用设置
dbms.cluster.discovery.version=V2_OVER_V1
。设置中的发现地址应包含新成员和先前成员的地址。
例如,对于使用列表解析器的用户,新服务器的设置应包含
dbms.cluster.discovery.resolver_type=LIST dbms.cluster.discovery.version=V2_OVER_V1 dbms.cluster.discovery.endpoints=server04.example.com:5000,server05.example.com:5000,server06.example.com:5000,server07.example.com:5000,server08.example.com:5000,server09.example.com:5000 dbms.cluster.discovery.v2.endpoints=server04.example.com:6000,server05.example.com:6000,server06.example.com:6000,server07.example.com:6000,server08.example.com:6000,server09.example.com:6000
-
使用
bolt://
连接到服务器7、8、9的系统数据库并运行以下过程CALL dbms.cluster.showParallelDiscoveryState();
输出应在
stateComparison
列中显示Matching
。如果它们没有显示,请等待并重试,直到匹配。预期结果+----------------------------------------------------------------+ | mode | stateComparison | v1ServerCount | v2ServerCount | +----------------------------------------------------------------+ | "V2_OVER_V1" | "Matching" | "6" | "6" | +----------------------------------------------------------------+
-
释放、删除并关闭服务器4、5和6。
-
启动服务器10、11、12,这次使用设置
dbms.cluster.discovery.version=V2_ONLY
。设置中的发现地址应包含新成员和先前成员的地址。请注意,只需要v2设置。
例如,对于使用列表解析器的用户,新服务器的设置应包含
dbms.cluster.discovery.resolver_type=LIST dbms.cluster.discovery.version=V2_ONLY dbms.cluster.discovery.v2.endpoints=server07.example.com:6000,server08.example.com:6000,server09.example.com:6000,server10.example.com:6000,server11.example.com:6000,server12.example.com:6000
-
释放、删除并关闭服务器7、8、9。
-
最后,使用
bolt://
连接到服务器10、11、12的系统数据库,并运行以下过程以检查发现服务的版本CALL dbms.cluster.showParallelDiscoveryState();
预期结果+-------------------------------------------------------------+ | mode | stateComparison | v1ServerCount | v2ServerCount | +-------------------------------------------------------------+ | "V2_ONLY" | "N/A" | "N/A" | "3" | +-------------------------------------------------------------+
使用过程
-
对于所有服务器,请确保新设置已更新到准备部分中详述的配置。
例如,对于使用列表解析器的用户,所有服务器的设置应包括
dbms.cluster.discovery.resolver_type=LIST dbms.cluster.discovery.endpoints=server01.example.com:5000,server02.example.com:5000,server03.example.com:5000 dbms.cluster.discovery.v2.endpoints=server01.example.com:6000,server02.example.com:6000,server03.example.com:6000
-
在Cypher Shell中,使用
bolt://
连接到服务器01的system
数据库。通过bolt://
连接非常重要,因为否则过程可能会被路由并在非目标服务器上执行。./cypher-shell -a bolt://localhost:7681 -d system
-
运行过程
CALL dbms.cluster.showParallelDiscoveryState();
输出指示模式
V1_ONLY
,即只有v1在此服务器上运行。预期结果+-------------------------------------------------------------+ | mode | stateComparison | v1ServerCount | v2ServerCount | +-------------------------------------------------------------+ | "V1_ONLY" | "N/A" | "3" | "N/A" | +-------------------------------------------------------------+
-
运行以下过程以在后台打开v2,但保持v1在前台运行
CALL dbms.cluster.switchDiscoveryServiceVersion("V1_OVER_V2");
-
再次检查状态
CALL dbms.cluster.showParallelDiscoveryState();
现在此服务器的返回模式必须为
V1_OVER_V2
,并且stateComparison
必须显示状态尚未匹配。预期结果+-------------------------------------------------------------------------------------------------------+ | mode | stateComparison | v1ServerCount | v2ServerCount | +-------------------------------------------------------------------------------------------------------+ | "V1_OVER_V2" | "States are not matching after PT1M9.518S: (score:18)" | "3" | "1" | +-------------------------------------------------------------------------------------------------------+
分数是衡量状态差异程度的指标。
serverCounts
分别显示v1和v2发现服务可以找到多少个服务器。当状态匹配时,分数为0。当某些成员仅运行一个发现服务(v1或v2),而其他成员运行两个服务时,分数将永久保持较高。这无需担心。 -
为了实现此收敛,在不同的终端中,通过
bolt://
连接到服务器02和服务器03,并在两个服务器上重复步骤3和4。 -
再次检查所有服务器上的状态。它应该显示状态为
Matching
。两个serverCounts
都应为3。预期结果+----------------------------------------------------------------+ | mode | stateComparison | v1ServerCount | v2ServerCount | +----------------------------------------------------------------+ | "V1_OVER_V2" | "Matching" | "3" | "3" | +----------------------------------------------------------------+
-
在所有三个服务器上,运行
CALL dbms.cluster.switchDiscoveryServiceVersion("V2_OVER_V1");
此时,v2是运行集群的服务,v1在后台运行。
预期结果+----------------------------------------------------------------+ | mode | stateComparison | v1ServerCount | v2ServerCount | +----------------------------------------------------------------+ | "V2_OVER_V1" | "Matching" | "3" | "3" | +----------------------------------------------------------------+
-
最后,通过在所有三个服务器上运行以下过程来关闭v1
CALL dbms.cluster.switchDiscoveryServiceVersion("V2_ONLY");
-
验证
CALL dbms.cluster.showParallelDiscoveryState();
现在是否显示正在运行的V2_ONLY
。请注意,stateComparison
为N/A
,因为您不再有v1来比较状态。预期结果+-------------------------------------------------------------+ | mode | stateComparison | v1ServerCount | v2ServerCount | +-------------------------------------------------------------+ | "V2_ONLY" | "N/A" | "N/A" | "3" | +-------------------------------------------------------------+
重要请记住更新所有服务器的neo4j.conf文件。使用过程进行切换不会将任何内容持久化到磁盘。因此,当服务器重新启动时,它会立即重新启动,并且仅运行v1。因此,请确保
dbms.cluster.discovery.version=V2_ONLY
,并且dbms.cluster.discovery.v2.endpoints
或dbms.kubernetes.discovery.v2.service_port_name
根据需要设置,以便服务器在下次重新启动时以v2运行。
监控进度和指标
从当前发现服务v1迁移到新版本v2时,可以使用过程CALL dbms.cluster.showParallelDiscoveryState()
监控进度。此过程显示服务器上发现服务的当前状态以及v1和v2发现服务状态之间的差异分数。差异分数是衡量状态差异程度的指标。过程报告的差异分数并不总是保持为0。以下是一些需要考虑的场景
-
在集群的情况下,当某些成员仅运行一个发现服务(v1或v2),而其他成员运行两个服务时,分数将永久保持较高。这无需担心。
-
当集群中发生更改(例如数据库/服务器的启动/停止或领导者切换)时,差异分数将暂时大于0。它应该很快再次达到0。
-
如果差异分数在较长时间内大于0,则实际差异将打印在debug.log中。
您还可以使用以下指标来监控发现服务