T5、常见问题
T5.1、mysql5.7 内存异常
社区讨论
mysql5.7 bug
containerd bug
mysql5.7 通过 docker v25.0.5 或 containerd v1.5.10 启动,会出现内存被异常占用 16G,导致操作系统 OOM 问题,docker v28.0 这个问题已解决。
社区虽然给出了解决方案,但是很少有人关注源码层面是由于什么场景导致的 bug,参考官方的 bug 报告bugs.mysql.com。
结合官方 bug 报告,ChatGPT 给出如下分析(仅供参考):
根本原因不是 MySQL 随机“吃内存”,而是 mysqld 在启动时把进程的 RLIMIT_NOFILE(ulimit -n)的“当前值”当作可用文件数返回/使用——如果该值异常大(不是 RLIM_INFINITY),就会被直接采纳并用于后续的内存/数组分配,导致巨量分配并耗尽宿主机内存。
1、mysqld 先计算需要的文件数(max_open_files),然后调用 my_set_max_open_files() 去设置/获取 OS 层的限制。
源码表达式:
max_open_files = max( wanted_files, max_connections*5, open_files_limit );
files = my_set_max_open_files(max_open_files);
这是 mysqld 的启动逻辑,计算想要的文件数然后交给 my_set_max_open_files 去尝试设置/获取实际可用值。
2、my_set_max_open_files / set_max_open_files 会读 getrlimit(RLIMIT_NOFILE) 并在某些条件下直接返回当前 rlimit.rlim_cur。
源码(mysys/my_file.c)逻辑的关键点是:
- 调用
getrlimit(RLIMIT_NOFILE, &rlimit),把rlimit.rlim_cur存在old_cur。 - 如果
rlimit.rlim_cur == RLIM_INFINITY则把它设为 max_file_limit(合理); - 如果
rlimit.rlim_cur >= max_file_limit,函数会直接 return rlimit.rlim_cur(也就是把当前很大的 rlimit 值当作最终值返回)。 - 返回的这个 files 值会影响 mysqld 的内部数据结构分配(比如 my_file_info / my_file_limit 等),因此如果 files 很大就会触发巨量 malloc/分配。
- mysys 的 my_set_max_open_files / my_file.c 内部维护 my_file_limit / my_file_info 等结构,启动时会基于 files 大小(返回值)做内存分配/扩容。若 files 是上面那个异常大的 rlimit 值,分配就会按这个数去做,进而可能申请数十 GB。
- 这是 bug 报告里直接指出的行为:set_max_open_files(max_file_limit) ... can return the current limit ... and later used in a malloc which can become huge。也有实测日志(启动时报 Out of memory / 需要几 GB)。bugs.mysql.com
- 这是一个已知的 bug(触发条件:OS 给出一个非常大的 but ≠ RLIM_INFINITY 的 rlimit),MySQL 在后续版本里修了(8.0.19/8.0.20 提到修复)。
MySQL 的 bug 报告里开发者说明:这个问题已在 8.0.19/8.0.20 中修复(修补方式是对返回值做上限/限制等处理,避免直接用超大 rlimit 导致 OOM)。bugs.mysql.com
在很多现代 Linux/distributions(或 systemd 的某些改动)下,进程启动时内核/父进程可能给进程一个非常大的 RLIMIT_NOFILE(比如 1073741816),因为 mysqld 的启动流程把“当前 rlimit”当成可用文件数并直接返回/使用,最终用于按文件数预分配/扩容某些内部数组(my_file_info / 相关缓存),因此会申请非常大的内存 —— 就会把宿主机内存吃光或触发 swap / OOM。这个正是 bug 报告中复现与分析的核心。
bugs.mysql.com
www.percona.com
解决方案:
社区给的解决办法(在 Docker 启动时加 --ulimit nofile=...)是合理且常用的临时/部署层解决方案;长期方案可以是升级到包含修补的 MySQL 版本(8.0.19+ 的修补)或者在宿主/服务管理层(systemd)显式把 LimitNOFILE 设置到合适值。
docker-compose.yml
version: "3.8"
services:
mysql:
image: mysql:5.7
container_name: mysql57
restart: always
environment:
MYSQL_ROOT_PASSWORD: StrongPassw0rd! # 建议使用安全密码
MYSQL_DATABASE: appdb # 可选:初始化数据库
MYSQL_USER: appuser # 可选:初始化用户
MYSQL_PASSWORD: AppUserPass123! # 可选:初始化用户密码
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql # 数据持久化
- ./my.cnf:/etc/mysql/conf.d/my.cnf:ro # 自定义 MySQL 配置
command:
--default-authentication-plugin=mysql_native_password
ulimits: # 关键!限制文件句柄,防止内存暴涨
nofile:
soft: 262144
hard: 262144
deploy:
resources:
limits:
cpus: "2.0" # 限制 CPU
memory: 4G # 限制最大内存
reservations:
memory: 1G
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 30s
timeout: 10s
retries: 3
volumes:
mysql_data:
my.cnf
[mysqld]
# 基本
user = mysql
port = 3306
bind-address = 0.0.0.0
sql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
# InnoDB 性能
innodb_buffer_pool_size = 2G # 占总内存 50%-70%
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 1 # 事务安全
innodb_file_per_table = 1
innodb_flush_method = O_DIRECT
# 连接和缓存
max_connections = 300
table_open_cache = 4096
open_files_limit = 262144 # 与 ulimit 对齐
thread_cache_size = 100
query_cache_type = 0 # MySQL 5.7 默认关闭
tmp_table_size = 64M
max_heap_table_size = 64M
# 日志
log_error = /var/log/mysql/error.log
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
# 字符集
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
[client]
default-character-set = utf8mb4
T5.2、etcd 健康问题
给 etcd 配置完数据目录和wal目录后,启动服务出现如下问题:
etcd crashes on startup when wal-dir is bind-mounted to host directory, fails with unlinkat /var/lib/etcd/wal: device or resource busy
社区也遇到了,https://github.com/etcd-io/etcd/issues/20218
根本原因是磁盘的挂载目录名和 etcd 服务配置的目录同名,而 etcd 进程会强制创建指定的目录,如果存在会先删除,但是这个目录又是个挂载点,所以会有 device or resource busy 的异常,如下:
# 专门给 etcd 配置的磁盘,避免数据争用,etcd 对磁盘延迟要求很高
[root@master-01 ~]# df -h | grep "/dev/vdc"
/dev/vdc2 50G 756M 50G 2% /etcd/etcd_wal
/dev/vdc1 50G 399M 50G 1% /etcd/etcd_data
# 设置不同的wal目录,可以避免磁盘io竞争,提高性能
ETCD_DATA_DIR: "/etcd/etcd_data"
ETCD_WAL_DIR: "/etcd/etcd_wal"
这么配置,etcd 会强制创建这两个目录,但是这两个目录又是挂载点,必然会出现这种问题。
可以在挂载点下指定一个子目录,就可以解决问题:
# 设置不同的wal目录,可以避免磁盘io竞争,提高性能
ETCD_DATA_DIR: "/etcd/etcd_data/data"
ETCD_WAL_DIR: "/etcd/etcd_wal/data"
T5.3、minio 生产上传失败
我们的生产环境,由于历史原因,上传文件到 minio 分成了两步,首先通过 getObjUrl() 连接 minio 拿到文件上传地址,传给另一个组件,然后通过 uploadFile(url) 上传文件。
这个过程经常遇到一些问题,拿不到上传地址,上传失败,找不到桶等,不想深入研究了,按下面步骤重来一遍就行。
1、进入 minio 控制台,Administrator -> Buckets -> Create Bucket
创建两个 bucket ebd-mdm、ebd-collect
2、给创建的 bucket 设置访问策略
点击创建的 bucket,然后点击 Summary -> Access Policy,选择 Custom,设置如下,注意,其中桶名(Resource 块中的 ebd-mdm)需根据实际情况修改为当前设置的桶名
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"AWS": ["*"]},"Action": ["s3?GetObject"],"Resource": ["arn:aws:s3:::ebd-mdm/*"]}]}
两个桶都需要进行同样配置操作
3、创建普通上传账户
点击 Administrator -> Identity -> Users -> Createt User
输入账户名和密码,如 bigdata/Takweb@bigdata123
Policy 选择 readwrite
4、为账户创建 AccessKey
Administrator -> Identity -> Users,点击创建的用户 -> Service Accounts -> Create Access Key -> create,然后复制保存创建的 Access Key 和 Secret Key
5、设置 nacos
#上传地址,注意非控制台地址,两个端口不一致
MINIO_ENDPOINT=http://192.168.212.9:9000
#保存的Access Key
MINIO_AK=c6NqOka6NNG8ebhrRaGS
#保存的Secret Key
MINIO_SK=I0evYO4V4nuY2hLl3yYlo9vIX8WFAy7hbeUiyr8j
minio配置
#上传链接超时时间,单位分钟
MINIO_URL_EXPIRE=60
6、验证
先通过控制台上传一个测试图片,如测试图片 1.png
然后通过地址直接访问,如 http://192.168.212.9:9000/ebd-mdm/1.png
删除文件名,直接访问桶,若出现 Access Deny 则表名,桶权限配置成功,如果列出桶下所有的文件,则权限设置失败
T5.4、mysqldump 经 ProxySQL 导入报 ERROR 2013
T5.4.1、问题现象
- 从 MySQL 8.0.33(源) 导出,向 8.0.30(目标) 用
mysql < xxx.sql导入时,出现ERROR 2013 (HY000): Lost connection to MySQL server during query。 - 报错行号常落在 视图
class_view的CREATE VIEW前面,或 第一个触发器CREATE TRIGGER前面;容易误以为是视图 SQL 或缺表。 --skip-triggers --ignore-views --skip-routines整库导出再导入 可以成功;单独带上视图 或 单独带上触发器 会 2013。- 连接目标时,客户端欢迎语为
Server version: 8.0.30 (ProxySQL)(或曾出现ProxySQL Error: Access denied),说明流量经 ProxySQL,不是直连 mysqld。 - 复现后可能出现
ERROR 2003 (HY000): ... (111)(端口短暂连不上),与 代理崩溃重启 相符。
T5.4.2、复现问题
(1)与线上一致的导入(会失败)
# 示例:含视图(不 ignore-views)
mysql -h<目标> -uroot -p base_platform < step1_with_views.sql
# 示例:含触发器(不 skip-triggers)
mysql -h<目标> -uroot -p base_platform < step3_with_triggers_only.sql
(2)成功基线(对照:不执行视图/触发器/routine 段)
mysqldump -h<源> -uroot -p \
--skip-triggers --ignore-views --skip-routines \
--databases base_platform > structure_ok.sql
mysql -h<目标> -uroot -p base_platform < structure_ok.sql
(3)单句复现(经同一 ProxySQL 入口登录后执行)
SET character_set_client = utf8mb3; -- 一般可过
SET character_set_results = utf8mb3; -- 触发 ERROR 2013,随后可能出现 2003(111)
与 dump 中一致时,视图段为 /*!50001 SET character_set_results = utf8mb3 */,触发器段为 /*!50003 SET character_set_results = utf8mb3 */,效果相同:尚未执行 CREATE VIEW / CREATE TRIGGER 正文即可断连。
实际测试如下:
[root@distributor ~]# mysql -h 10.148.129.240 -u root -p --max_allowed_packet=268435456 base_platform
Enter password:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.30 (ProxySQL)
Copyright (c) 2000, 2026, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
mysql> SET character_set_client=utf8mb3;
No connection. Trying to reconnect...
Connection id: 3
Current database: base_platform
Query OK, 0 rows affected (0.00 sec)
mysql>
mysql> SET character_set_client=utf8mb3;
Query OK, 0 rows affected (0.00 sec)
mysql> SET character_set_results=utf8mb3;
ERROR 2013 (HY000): Lost connection to MySQL server during query
No connection. Trying to reconnect...
ERROR 2003 (HY000): Can't connect to MySQL server on '10.148.129.240:3306' (111)
ERROR:
Can't connect to the server
mysql>
mysql> SET character_set_client=utf8mb3;
No connection. Trying to reconnect...
Connection id: 3
Current database: base_platform
Query OK, 0 rows affected (0.01 sec)
mysql>
mysql>
mysql>
mysql> /*!50001 SET character_set_client = utf8mb3 */;
Query OK, 0 rows affected (0.00 sec)
mysql> /*!50001 SET character_set_results = utf8mb3 */;
ERROR 2013 (HY000): Lost connection to MySQL server during query
No connection. Trying to reconnect...
ERROR 2003 (HY000): Can't connect to MySQL server on '10.148.129.240:3306' (111)
ERROR:
Can't connect to the server
mysql>
mysql> /*!50001 SET character_set_client = utf8mb3 */;
No connection. Trying to reconnect...
Connection id: 3
Current database: base_platform
Query OK, 0 rows affected (0.00 sec)
mysql> /*!50001 SET character_set_client = utf8mb3 */;
Query OK, 0 rows affected (0.00 sec)
mysql>
(4)说明
仅加 --routines 且 dump 内 CREATE PROCEDURE / CREATE FUNCTION 为 0 条 时导入成功,不能证明「存储过程一定无问题」,只能说明 本次文件没执行到同类带 utf8mb3 的视图/触发器包装段。
T5.4.3、问题分析和解决
T5.4.3.1、分析
- mysqldump 在 视图(
/*!50001)、触发器(/*!50003) 等块里会写SET character_set_client/character_set_results/collation_connection为utf8mb3,用于贴近对象定义时的连接字符集。 - MySQL 8.0 中
utf8mb3是合法字符集名(直连 mysqld 执行上述SET通常正常)。依据:MySQL 手册 — utf8mb3。 - 旧版 ProxySQL 对
SET character_set_results = utf8mb3处理有缺陷,可导致 断言失败 / 进程崩溃,客户端表现为 2013(查询过程中断连),与 MySQL 手册 — 2013 / CR_SERVER_LOST 及 B.3.2.7 MySQL server has gone away 中对「断连、未收齐应答」的描述一致。 - 与社区报告一致时可查
proxysql.log:Cannot find charset/collation [utf8mb3]、断言、signal 6、ProxySQL crashed. Restarting!- ProxySQL #4269
- 修复 PR:ProxySQL #4270(将
utf8mb3按utf8别名处理;2023-06-28 合并入v2.x)
- 官方写明带上该修复的发行版(2.x):ProxySQL 2.5.4(发布日 2023-07-19)Release notes 中列为 Major bug fix:「Fixed crashes when trying to set character set to
utf8mb3」#4269。即 PR #4270 对应问题在 2.5 系列里从 2.5.4 起有正式发行说明;2.5.3 与 issue 中复现版本同类,仍会触发崩溃。- 依据:GitHub — ProxySQL v2.5.4 Release notes
- 3.x:未在本文逐条核对每个 3.0.x 的 release note;实际升级请以
proxysql --version为准,并务必用SET character_set_results = utf8mb3;做冒烟(或走直连导入)。
T5.4.3.2、解决
| 做法 | 说明 |
|---|---|
| 升级 ProxySQL | 2.x:至少升级到 2.5.4(见上条官方 release);其它大版本以 SET character_set_results = utf8mb3 冒烟为准。 |
| 大导入直连 mysqld | 迁移窗口用 后端真实 IP、端口(非代理端口)执行 mysql < xxx.sql。 |
| 应急改 SQL | 将 utf8mb3 / utf8mb3_general_ci 批量改为 utf8mb4 / 对应 utf8mb4 collation` 后再经代理导入;必须在测试库验证,避免误伤。 |
| 导出参数 | mysqldump --default-character-set=utf8mb4 可作辅助,不保证去掉视图/触发器块内已写死的 utf8mb3,不能替代升级或直连。 |
T5.4.4、结论
- 根因:经 ProxySQL 时,
SET character_set_results = utf8mb3(及同段utf8mb3会话 SET) 触发 ProxySQL 已知缺陷,代理崩或断连 → 客户端 2013(及可能的 2003(111))。 - 表象:报错行「挨着」视图或触发器,实为 mysqldump 在这些对象前的字符集 SET;与视图 SELECT、触发器业务逻辑、基表是否存在无直接关系。
- 处置:优先 升级 ProxySQL 或 导入绕开代理;临时可对 dump 做
utf8mb3→utf8mb4类替换并充分验证。
T5.5、Nacos 通过 Kubernetes NodePort 访问与服务注册故障处理
适用场景:集群外 Spring Boot 应用通过 NodePort 访问 Nacos 2.x,并使用 Nacos 2.x Java 客户端。端口计算逻辑以官方 Nacos 2.3.2 源码为依据;其他版本应核对对应实现。
5.5.1. 问题与处理结论
Kubernetes 集群内应用可以通过 Nacos Service 的 8848 端口访问服务;集群外应用配置 192.168.141.14:31152 后,无法正常连接及注册服务。
在外部网络正常的前提下,本次故障由 NodePort 映射未保持 Nacos 客户端默认的端口偏移关系引起。将客户端 gRPC 对应的 NodePort 从 31387 改为 32152 后,现场验证应用连接和服务注册成功。
| 通信用途 | Nacos 默认内部端口 | 修复前 NodePort | 修复后 NodePort |
|---|---|---|---|
| HTTP/API | 8848 | 31152 | 31152 |
| 客户端 gRPC | 9848 | 31387 | 32152 |
| 服务端间 gRPC | 9849 | 32214 | 32214 |
| 服务端间 Raft 通信 | 7848 | 30872 | 30872 |
后两项仅记录现场已有映射,不是外部应用连接所需的端口。此次修复仅调整客户端 gRPC 的 NodePort。
5.5.2. 现场配置与根因
修复前 Service 位于 talkweb 命名空间,名称为 nacos2:
NAME TYPE CLUSTER-IP PORT(S)
nacos2 NodePort 10.68.125.151 8848:31152/TCP,9848:31387/TCP,9849:32214/TCP,7848:30872/TCP
8848:31152/TCP 表示 Service 端口为 8848,节点对外端口为 31152。实际转发到哪个 Pod 端口,还应通过 Service YAML 中的 targetPort 核实。
Nacos Java 客户端只需配置主地址,再按以下规则计算客户端 gRPC 地址:
客户端 gRPC 目标端口 = 配置的主端口 + 偏移量
默认偏移量 = 1000
因此,两条访问路径的结果不同:
| 访问路径 | 应用配置的主端口 | 默认计算的 gRPC 端口 | 实际可用的 gRPC 端口 | 结果 |
|---|---|---|---|---|
| 集群内 Service | 8848 | 9848 | 9848 | 匹配 |
| 集群外 NodePort,修复前 | 31152 | 32152 | 31387 | 不匹配 |
| 集群外 NodePort,修复后 | 31152 | 32152 | 32152 | 匹配 |
加 1000 是 Nacos 的默认约定,并非 gRPC 协议要求。 Kubernetes 按 Service 配置转发端口,不会把 9848 → 31387 的映射关系通知 Nacos 客户端。仅 HTTP 端口可访问,也不能证明服务注册所依赖的 gRPC 连接正常。
现场最初使用的集群内地址为 nacos.talkweb:8848,而本次列出的 Service 名为 nacos2;两者可能涉及不同 Service 或别名。复用配置时,应以实际 Service 名称为准,例如 nacos2.talkweb:8848。
5.5.3. 官方源码依据
以下代码摘自 Nacos 2.3.2。
5.5.3.1 默认偏移量
Constants.java 定义客户端 gRPC 的默认端口偏移量:
public static final Integer SDK_GRPC_PORT_DEFAULT_OFFSET = 1000;
5.5.3.2 服务端计算监听端口
BaseRpcServer.java 根据主端口和偏移量计算 RPC 服务端口:
public int getServicePort() {
return EnvUtil.getPort() + rpcPortOffset();
}
GrpcSdkServer.java 的 rpcPortOffset() 返回上述默认值 1000,所以主端口为 8848 时,客户端 gRPC 服务监听 9848。
5.5.3.3 客户端计算连接端口
GrpcSdkClient.java 读取 JVM 系统属性,未指定时使用默认值:
public int rpcPortOffset() {
return Integer.parseInt(System.getProperty(
GrpcConstants.NACOS_SERVER_GRPC_PORT_OFFSET_KEY,
String.valueOf(Constants.SDK_GRPC_PORT_DEFAULT_OFFSET)));
}
其中 NACOS_SERVER_GRPC_PORT_OFFSET_KEY 的值为 nacos.server.grpc.port.offset。
GrpcClient.java 使用计算结果创建 gRPC 连接:
int port = serverInfo.getServerPort() + rpcPortOffset();
ManagedChannel managedChannel =
createNewManagedChannel(serverInfo.getServerIp(), port);
客户端配置 31152 且未覆盖偏移量时,目标端口必然为 32152。
5.5.4. 已验证修复:调整 NodePort
保留 HTTP 的 31152 → 8848 映射,将客户端 gRPC 映射调整为 32152 → 9848,应用使用默认偏移量。
5.5.4.1 检查与备份
# 确认 32152 未被其他 Service 占用
kubectl get svc -A -o wide
# 核实 8848、9848 的 targetPort,以及 externalTrafficPolicy
kubectl get svc nacos2 -n talkweb -o yaml
# 备份变更前配置;使用独立文件名,避免覆盖既有备份
kubectl get svc nacos2 -n talkweb -o yaml > nacos2-service-before.yaml
以下补丁适用于现场已有的 port: 9848、protocol: TCP 配置,仅修改其 NodePort:
kubectl patch service nacos2 -n talkweb --type=strategic \
-p '{"spec":{"ports":[{"port":9848,"protocol":"TCP","nodePort":32152}]}}'
变更后核实:
kubectl get service nacos2 -n talkweb
预期包含:
8848:31152/TCP,9848:32152/TCP
若由 Helm 或 GitOps 管理,应同步修改配置源,避免控制器恢复旧映射。已有客户端若显式使用 31387,也需同步调整。
5.5.4.2 Spring Boot 应用配置
项目需引入 com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery,并使用与具体 Spring Boot、Spring Cloud 版本匹配的 Spring Cloud Alibaba BOM。仅凭“Spring Boot 3.x”无法确定兼容的依赖版本。
application.yml:
spring:
application:
name: your-service
cloud:
nacos:
discovery:
server-addr: 192.168.141.14:31152
应用仍填写主端口 31152,无需将 32152 填入 server-addr,也无需增加偏移量参数。若之前设置过自定义偏移量,应移除该覆盖或恢复为 1000。
如启用鉴权,按部署要求提供有效凭据。如使用非默认 Nacos 命名空间,填写其命名空间 ID;Kubernetes 的 talkweb 命名空间与 Nacos 命名空间是两个独立概念。
如果应用同时使用 Nacos 配置中心,还需将 spring.cloud.nacos.config.server-addr 设置为相同主地址,并保留项目对应版本要求的配置导入设置。
5.5.4.3 验证与回退
在集群外应用所在主机验证两条 TCP 链路:
nc -vz -w 3 192.168.141.14 31152
nc -vz -w 3 192.168.141.14 32152
Windows 可使用 Test-NetConnection 192.168.141.14 -Port <端口>。
启动或重启应用后,确认客户端建立连接、注册成功,并在 Nacos 对应命名空间和分组中查看服务实例。端口测试通过只是连通性验证,最终以应用注册结果为准。
本次现场结果:调整为 32152 后,应用已成功连接并注册服务。
如需恢复原映射,可执行以下回退命令;回退也会恢复原有的端口偏移不匹配问题:
kubectl patch service nacos2 -n talkweb --type=strategic \
-p '{"spec":{"ports":[{"port":9848,"protocol":"TCP","nodePort":31387}]}}'
5.5.5. 备选方案:保留映射,调整客户端偏移量
若必须保留原来的 31152 → 8848、31387 → 9848 映射,可按外部端口差值设置客户端:
31387 - 31152 = 235
java -Dnacos.server.grpc.port.offset=235 -jar your-app.jar
主地址仍为 192.168.141.14:31152,客户端计算得到的 gRPC 端口变为 31387。
-D参数必须放在-jar前;IDE 启动时填写在 VM options。- 源码读取的是 JVM 系统属性,单独在
application.yml中添加同名键不会替代-D参数。 - 该参数只改变客户端计算目标端口的方式,不修改服务端监听端口,也不修改 Kubernetes 映射。
- 该属性作用于同一 JVM 内使用此逻辑的 Nacos SDK 连接;若同时连接不同端口映射的 Nacos 环境,应检查是否冲突。
此方案有上述版本源码依据,未作为本次现场最终验证方案。已采用 32152 的环境不应再设置偏移量 235。
5.5.6. 同类问题复查顺序
| 检查项 | 判断与下一步 |
|---|---|
| 主端口 TCP 不通 | 检查节点地址、路由、防火墙、NodePort、Service 后端与转发组件 |
externalTrafficPolicy: Local |
访问节点必须存在该 Service 对应的就绪本地后端;否则不转发 |
| 主端口可达,但应用连接失败 | 核对客户端版本、实际偏移量,以及计算出的 gRPC 端口是否正确映射和放行 |
| 两条 TCP 链路均可达,仍注册失败 | 依据客户端日志检查 gRPC 握手、鉴权、依赖兼容性及服务端状态 |
| 注册成功,但查不到实例 | 核对所查看的 Nacos 集群、命名空间、分组和服务名 |
