ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Hazelcast 主机名(Hostname)网络寻址问题修复设计解析:多地址管理与 LocalAddressRegistry 原理

Hazelcast 主机名(Hostname)网络寻址问题修复设计解析:多地址管理与 LocalAddressRegistry 原理 缓存KV存储消息队列流处理后端【免费下载链接】hazelcastHazelcast is a unified real-time data platform combining stream processing with a fast data store, allowing customers to act instantly on>项目地址https://gitcode.com/gh_mirrors/ha/hazelcast点击查看免费下载在 Hazelcast 集群网络中一个成员节点往往可以通过多个网络地址被访问如主机名与其解析出的 IP、公网/内网地址、代理地址等而代码库中大量逻辑却默认一个成员只有一个地址导致使用主机名配置网络member join/bind、WAN 目标、云环境发现插件时出现各种错误与异常行为。本篇技术指南以 Hazelcast 官方设计文档 docs/design/networking/01-fix-hostname-usage-related-issues.md 为骨架结合当前仓库源码深入讲解多地址统一管理的设计方案、LocalAddressRegistry地址注册表的工作原理、主地址Primary Address的选择规则以及完整的测试验收标准帮助你理解 Hazelcast 如何做到IP 能用的配置换成主机名一样能用。背景与问题描述问题的根源一个成员可以有多个网络地址设计文档开篇就点明了问题的根源The source of the problems is the fact that multiple network addresses can point to the same member, and we ignore this fact while dealing with network addresses in our codebase.代码库中很大一部分逻辑都假设一个成员只会拥有一个网络地址Address但这个假设在使用主机名时立刻失效。原因在于当成员使用主机名进行网络配置时这个成员既知道主机名解析出的IP 地址又保留着原始的主机名字符串地址——同一个成员天然就拥有了两个地址。成员之间没有妥善管理这些多地址关系于是产生了错误或不符合预期的行为。相关已知问题包括Jira: HZOLD-528GitHub issues: hazelcast#15722、hazelcast#16651成员 join/bind 使用主机名企业版 issues: hazelcast-enterprise#3627、hazelcast-enterprise#4342WAN 配置使用主机名动机云原生与动态 IP 环境下的刚需虽然简单的网络拓扑可以用 IP 替代主机名但在复杂网络环境中主机名是必须的能力云环境AWS、Azure、GCP、Kubernetes中机器 IP 经常是动态分配的需要通过 DNS 主机名解析机制来标识成员相比本地部署云端部署的网络拓扑更复杂IP 可能随时变化而主机名保持稳定大量用户与客户已在使用主机名配置时遇到问题需要一个无缝的主机名使用体验。目标设计文档明确了三个目标成员间通信member-to-member支持基于主机名的寻址WAN 配置支持基于主机名的寻址WAN 目标地址使用主机名相关发现插件支持主机名寻址如 AWS、Azure、GCP、Kubernetes 上的成员发现。总结成一句话就是任何用 IP 地址能够正常工作的集群配置换成主机名之后也必须能正常工作any cluster setup that works properly when IP addresses are used, to operate when hostnames are used。术语约定术语定义Hostname主机名分配给网络上某台主机的便于使用的名称被映射到一个或多个 IP 地址Hazelcast 不考虑一个主机名映射到多个 IP 的情况因为项目中不存在这种用例Hostname resolution主机名解析将主机名转换为对应 IP 地址的过程使得 socket bind 与 connect 可以基于该 IP 执行典型场景Actors and Scenarios场景 1成员服务器 bind(publicAddress) 与 join 配置使用主机名用户在成员 join 与 bind 配置中使用主机名并启动成员这些成员必须能够互相 join 并组成集群所有依赖网络的 Hazelcast 功能必须继续正常工作Hazelcast 是分布式系统网络层变更影响面极广。场景 2WAN 目标地址配置使用主机名用户在成员的 WAN 目标target配置中使用主机名并启动成员WAN 两端的成员必须能够互相连接其他依赖网络的功能继续正常工作。功能设计与用户交互无功能变更但需暴露地址管理能力功能设计零功能变更设计文档明确There will be no functional changes.整个修复不改变 Hazelcast 对外暴露的功能行为而是修正底层地址管理逻辑让既有功能在主机名下与 IP 下表现一致。API 层面向用户暴露 UUID-地址映射用户如果此前在自定义代码中使用成员地址做成员识别当配置包含主机名时仍会遇到地址管理问题。为此设计文档提出将内部管理的UUID - SetAddress及其反向映射Address - UUID暴露给用户让用户能按成员 UUID 管理地址。一个典型的内部用户是 Jet 连接器connector。例如Elasticsearch 连接器使用成员地址判断 Hazelcast 集群与 Elasticsearch 是否运行在同一批机器上若同机则在作业规划时读取本机分片、避免走网络Hadoop 连接器逻辑相同。这类同机本地读取优化在成员拥有多个地址时可能出错暴露 UUID-地址映射后即可修正。日志兼容主地址继续打印用户在成员日志中主要使用被选中的 public address进行成员识别。设计文档强调We should store the address configured by the user as the primary address and continue to print it in the member logs.即使成员识别改为基于 UUID 的逻辑也要在日志相关位置保留并打印成员地址主地址不对成员日志做大改动避免用户困惑。技术设计在网络层统一管理多地址核心思路只对高层暴露单一主地址解决方案分两层高层high-level只看到单一地址在各上层模块中只暴露一个唯一的地址表示称为成员的主地址Primary Address从而避免在大量高层代码中处理多地址网络/连接管理器层管理多地址连接管理器内部用成员唯一 UUID 管理多个成员地址及其连接。主地址的选取规则成员协议连接以及使用统一连接管理器 Unified Connection Manager 的其他连接选择com.hazelcast.instance.ProtocolType#MEMBER对应的成员协议public address作为主地址其他协议连接启用 Advanced Networking 时选择对应协议的 public address 作为主地址。例如对于只管理 WAN 连接的连接管理器选择com.hazelcast.instance.ProtocolType#WAN对应的 public address。虽然每个EndpointQualifier只对应一个被选中的 public address但通过这些 endpoint 还可以用其他地址非 public address访问——这正是问题的复杂性所在。为什么只看地址内容无法判断同属一个成员设计文档列出了若干地址内容完全不同但指向同一成员的情形仅使用 IP 时多个不同 IP 也可能指向同一台主机Hazelcast server socket 可以绑定主机的多个网络接口如多个私网/公网地址在成员前面加网络代理时代理地址在连接发起方视角上就是成员地址DNS 中可配置多个主机名指向同一台机器它们解析到的 IP 不一定相同且何时解析也不确定。因此仅靠比较地址内容无法判断归属。要真正确认某个连接到的地址属于哪个成员必须连接到远端成员并处理其MemberHandshake在 MemberHandshake 中本端成员获得远端成员的UUID从而确定该连接地址归属哪个成员处理握手时把该连接地址注册为对应成员 UUID 的地址远端成员还会在 MemberHandshake 中共享自己的 public addresses这些地址连同连接地址一起作为该成员 UUID 下的**别名aliases**互相注册。Address RegistryUUID - SetAddress与反向映射为管理地址别名设计文档定义了一个地址注册表存储两类映射UUID - SetAddress一个实例 UUID 对应的所有地址Address - UUID每个地址归属的实例 UUID。映射条目在连接注册connection registration时创建——该时机正好是在握手处理过程中拿到远端 UUID 之后。条目的移除时机是所有指向该成员的连接全部关闭。关于移除时机设计文档特别考量了以下容易产生**陈旧条目stale entries**的动作Hot Restart热重启在另一台机器上以相同 UUID 重启成员重启脑裂合并split-brain merge。如果让映射条目生命周期比连接更长就会在相同 UUID 的 Hot Restart场景下出问题因此设计上坚持把注册条目的生命周期绑定到连接的生命周期。为什么不能把所有Address用法从代码库中移除设计团队曾考虑彻底移除代码库中的Address用法但发现不可行地址改动涉及面太广addresses 被用在大量不同位置有些位置移除会破坏向后兼容socket bind 与 socket connect 在本质上强依赖 Address这些位置无法移除操作服务operation service的重试机制当没有到某地址的活动连接时一次操作会触发 socket channel 重连。大多数操作已有已建立连接但join、WAN 以及部分 clusterheartbeat操作依赖 connect 语义这阻止了从操作调用服务中轻易移除 Address部分 cluster service 方法在成员间进行字典序地址比较以决定成员顺序例如决定谁认领 master 席位同样无法在不破坏向后兼容的前提下移除。设计文档给出了两个无法移除 Address 的典型代码示例// 决定首次 join 后哪个成员认领 mastershipmaster candidate private boolean isThisNodeMasterCandidate(CollectionAddress addresses) { int thisHashCode node.getThisAddress().hashCode(); for (Address address : addresses) { if (isBlacklisted(address)) { continue; } if (node.getServer().getConnectionManager(MEMBER).get(address) ! null) { if (thisHashCode address.hashCode()) { return false; } } } return true; }// 决定脑裂后合并到哪个目标成员 private boolean shouldMergeTo(Address thisAddress, Address targetAddress) { String thisAddressStr [ thisAddress.getHost() ]: thisAddress.getPort(); String targetAddressStr [ targetAddress.getHost() ]: targetAddress.getPort(); if (thisAddressStr.equals(targetAddressStr)) { throw new IllegalArgumentException(Addresses must be different! This: thisAddress , Target: targetAddress); } // 由于字符串必然不同结果恒非零 int result thisAddressStr.compareTo(targetAddressStr); return result 0; }这类逻辑用 UUID 替换地址会导致序列化格式变化、需要 RUrolling upgrade兼容路径代价过高因此保留。源码实现LocalAddressRegistry与LinkedAddresses设计文档中定义的LocalAddressRegistry抽象已在当前仓库落地位于 hazelcast/src/main/java/com/hazelcast/internal/server/tcp/LocalAddressRegistry.java持有两个并发映射ConcurrentMapAddress, UUID addressToUuid与ConcurrentMapUUID, Pair uuidToAddressesPair内含LinkedAddresses与注册计数AtomicInteger本地成员与远端成员分开管理localUuid/localAddresses用volatile字段单独维护因为本地成员 UUID 与地址的生命周期和远端略有不同构造时通过AddressPicker注册本地地址registerLocalAddresses把EndpointQualifier.MEMBER的 public address、绑定地址、以及绑定到anyLocalAddress0.0.0.0时枚举出的各网络接口地址一并加入本地地址集合。地址集合的载体是 hazelcast/src/main/java/com/hazelcast/internal/server/tcp/LinkedAddresses.java它把指向同一 Hazelcast 实例的所有网络地址聚合在一起并明确记录哪一个是最主地址primary addressgetResolvedAddresses(...)在注册时即尝试把主机名解析为 IP 并一同加入地址集合ip inetAddress.getHostAddress()这样主机名地址 其解析 IP天然成为一对别名intersects(...)判断两组地址是否有交集用于注册合并决策getPrimaryAddress()供上层取得唯一主地址。注册与注销的关键调用链注册register成员连接建立后由 hazelcast/src/main/java/com/hazelcast/internal/server/tcp/TcpServerConnectionManager.java 的register(...)完成对应设计文档中引用的 #L197 区域校验连接存活设置remoteAddress即主地址与remoteUuid调用registerAddresses(remoteUuid, primaryAddress, targetAddress, remoteAddressAliases)注册地址映射处理自连接remoteUuid 等于本端 UUID 则关闭连接、放入 plane、触发connectionAdded事件。其中registerAddresses定义在 hazelcast/src/main/java/com/hazelcast/internal/server/tcp/TcpServerConnectionManagerBase.java把主地址、目标地址、远端声明的别名地址统一用LinkedAddresses.getResolvedAddresses处理后提交给addressRegistry.register(remoteUuid, ...)。LocalAddressRegistry.register(...)的合并逻辑对应设计文档中的设计要点若同一 UUID 已注册且新旧地址集合有交集把新地址并入旧集合视为补充别名并将注册计数 1——因为成员间可能存在多条连接如多 plane必须等所有连接都关闭才能删除条目若完全无交集视为旧注册已陈旧stale整体覆盖为新地址集合并重置计数为 1同时把旧地址从反向映射中移除。该情况典型的触发场景正是设计文档提到的启用 Persistence 后新成员以相同 UUID 重启但拾取了不同地址而旧成员同 UUID的陈旧连接尚未关闭反向映射addressToUuid逐地址写入若某地址此前已注册给别的 UUID 会打印 warning常见于两个私网集群做 WAN 时地址重叠建议使用 Advanced Networking 并分别配置 WAN server socket 与 publisher。注销deregister连接关闭时hazelcast/src/main/java/com/hazelcast/internal/server/tcp/TcpServerConnectionManagerBase.java 的ConnectionLifecycleListenerImpl.onConnectionClose回调调用addressRegistry.tryRemoveRegistration(remoteUuid, connection.getRemoteAddress())。tryRemoveRegistration会校验UUID 与主地址Connection#remoteAddress同时匹配防止同 UUID 的新成员重连后被陈旧连接的关闭事件误删仅当注册计数递减到 0即所有连接都已关闭才真正删除条目。设计文档中引用的客户端连接注销点位于 hazelcast/src/main/java/com/hazelcast/client/impl/ClientEngineImpl.java#L443 区域成员与客户端共用同一注册表。查询lookupget(Address)、getAllConnections(Address)、send(...)等路径均通过addressRegistry.uuidOf(address)先把地址解析为成员 UUID再按 UUID 查连接。例如TcpServerConnectionManagerBase.send(...)中UUID targetUuid addressRegistry.uuidOf(target);随后Connection connection get(targetUuid, streamId);。这意味着上层只需持有任一别名地址主机名或 IP即可找到正确的成员连接——这正是修复主机名问题的核心机制。由于这些查询不在热路径上下文性能部分说明引入注册表不会带来明显开销。设计过程中的遗留问题Notes/Questions/Issues设计文档记录了实现过程中尚待确认或已做出取舍的问题理解它们有助于把握设计边界UUID - SetAddress查询时地址优先级IP 还是主机名优先答案取决于上下文——例如成员日志中倾向用户配置的地址而 TLS 场景更偏好主机名hostname 校验。bind/connect 语义的强依赖无论怎样在高层隔离地址join 与 WAN 操作仍依赖 bind/connect无法把 Address 从这些操作中剥离。向后兼容强制用 UUID 做成员识别可能引发兼容问题替换 Address 需要逐包package评估序列化对象由 Address 改为 UUID 时需增加 RU 兼容路径。别名集合的抽象曾考虑用新类表示SetAddress别名集合但尚未找到足够好的抽象最终采用了LinkedAddresses。设计文档还回顾了相关历史此前有一个被回滚的 PRhazelcast#18591其中含相关 TDD以及 hazelcast#19684说明该问题此前已尝试修复过。性能与稳定性考量性能设计文档明确变更没有在热路径上执行并发UUID - SetAddress及其反向映射的查询并做了简单基准测试5.1 Hostname Fix 性能测试未发现与变更前版本的性能差异稳定性注册条目生命周期与连接绑定刻意避免 Hot Restart 同 UUID、成员重启、脑裂合并场景下的陈旧数据地址注册失败不会阻断后续连接先注册地址、后处理错误场景的设计顺序也保证了这一点。测试标准Testing Criteria单元与集成测试设计文档要求单元与集成测试验证以下内容TCP-IP成员配置中的主机名可用TCP-IP客户端配置中的主机名可用WAN 目标配置中的主机名可用成员启动之后才可解析的主机名可用于其他成员建立连接可用多个主机名引用同一个成员Persistence 开启时UUID-地址管理仍正常考虑以相同 UUID 重启TLS 保持可用主机名校验启用时不同环境本地部署、Kubernetes、GKE、AWS 等下性能无显著下降应用setPublicAddress后集群能正确组建Persistence 与 WAN 正常工作外部网络的客户端能连接集群。文档同时建议这些场景最好也用 Hazelcast test containers 覆盖。当前仓库中已有对应实现级测试hazelcast/src/test/java/com/hazelcast/internal/server/tcp/LocalAddressRegistryTest.java 与 hazelcast/src/test/java/com/hazelcast/internal/server/tcp/LocalAddressRegistryIntegrationTest.java分别覆盖注册表合并/注销逻辑与真实成员网络场景。压力测试Stress Test压力测试必须验证以下故障场景下 Hazelcast 正常工作集群中成员优雅关闭graceful shutdown成员强制关闭forceful shutdown脑裂发生并最终合并split-brain集群 A 与集群 B 之间配置了 WAN 复制时B 集群发生全集群崩溃。以上场景在启用 Hazelcast Persistence时也必须复测。云环境测试该修复必须覆盖不同云环境因为云端网络拓扑灵活多变包含本地部署不易遇到的结构例如 Operator 的expose externally功能。必须验证主机名在这些云端网络结构中可用并尽可能实现自动化测试。总结Hazelcast 主机名相关问题的修复本质上是把一个成员 一个地址的错误假设升级为一个成员 一个 UUID 一组别名地址的模型网络层通过MemberHandshake拿到远端 UUID 后用LocalAddressRegistry维护UUID ↔ SetAddress双向映射以注册计数确保条目生命周期与连接严格一致再向高层只暴露单一主地址。这套设计在不改变任何用户可见功能、不破坏向后兼容的前提下让成员 join/bind、WAN 目标、云发现插件中的主机名配置与 IP 配置表现一致并配套了完整的单元、集成、压力与云环境测试矩阵来保障稳定性。若需深入了解实现细节可继续阅读 LocalAddressRegistry.java、LinkedAddresses.java 及其测试用例。赞分享缓存KV存储消息队列流处理后端【免费下载链接】hazelcastHazelcast is a unified real-time data platform combining stream processing with a fast data store, allowing customers to act instantly on>项目地址https://gitcode.com/gh_mirrors/ha/hazelcast点击查看免费下载相关推荐网络工具集IP地址与MAC地址处理网络工具集IP地址与MAC地址处理 it tools项目提供了一系列专业的网络工具包括IPv4子网计算器、IP地址转换与范围扩展工具、MAC地址生成与查询工开发工具前端金融时序预测革命Kronos金融大模型的技术架构与量化交易实战金融时序预测革命Kronos金融大模型的技术架构与量化交易实战 Kronos作为首个专为金融市场语言设计的开源基座模型通过创新的Transformer架构和人工智能大模型基础模型预训练金融科技Claude Code 沙箱网络出口控制解析deniedResolvedAddresses 设置与主机名解析地址封锁机制Claude Code 沙箱网络出口控制解析deniedResolvedAddresses 设置与主机名解析地址封锁机制 本文围绕 Claude Code 系文档提示工程人工智能上一篇明日方舟全自动助手MAA三分钟学会解放双手的智能挂机方案下一篇Angular 安全防护实战深入理解 Sanitization净化机制与安全上下文创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表