Dubbo 服务 IP 注册错误踩坑经历
个人博客地址 studyidea.cn,点击查看更多原创文章
踩坑
公司最近新建一个机房,需要将现有系统同步部署到新机房,部署完成之后,两地机房同时对提供服务。系统架构如下图:

这个系统当前对外采用 Restful 接口,内部远程采用 Dubbo,服务注册中心使用 zookeeper。服务当前设定只会调用本机房内服务。
原先服务都在 A 机房,B 机房为新建机房。B 机房部署完成之后,需要测试 B 机房系统可用性。生产测试的发现 B 机房竟然调用 A 机房服务。
A/B 机房网络互相打通,可以互相访问
通过排查 B 机房服务日志,发现 Service B 一个服务节点注册 IP 解析错误,将 B 机房机器 IP 解析成 A 机房机器 IP。
于是当测试流量进入 B 机房时,openapi服务通过注册中心获取到错误的 Service B 服务地址,从而调用了 A 机房的服务。调用方式简化成如下图。

知识点:Dubbo 服务提供者启动时将会将服务地址(IP+端口)注册到注册中心,消费者启动时将会通过注册中心获取服务提供者地址(IP+端口),后续服务调用将会直接通过服务地址直接调用。
问题分析
Debug Dubbo 源码,定位到 IP 解析代码,位于 ServiceConfig#findConfigedHosts,源码如下:
Dubbo 版本为 2.6.7

这个方法源码比较长,看起来比较费劲,不过好在这个方法注释上已经写明白 IP 地址查找顺序。
Register & bind IP address for service provider, can be configured separately. Configuration priority: environment variables -> java system properties -> host property in config file -> /etc/hosts -> default network address -> first available network address
查找顺序如图所示:

解析过程,Dubbo 将会过滤无用 IP,过滤规则如下:

下面将结合图示讲解查找顺序,只要其中一步读取 IP 符合上述规则,方法就会返回。
第一步将会调用 ServiceConfig#getValueFromConfig 从 environment variables 或 java system properties 配置 IP 地址。
这种方式通过在 JVM 启动参数中显示指定 IP 。
-DDUBBO_IP_TO_BIND=1.2.3.4
第二步通过读取 Dubbo 配置文件配置变量获取 IP。
<!-- protocol 指定整个 Dubbo 应用服务默认 IP -->
<dubbo:protocol host="1.2.3.4"/>
<!-- provider 指定 Dubbo 应用具体某个服务默认 IP -->
<dubbo:provider host="1.2.3.4"/>
第三步通过调用 InetAddress.getLocalHost().getHostAddress() 获取本地 IP。该方法将会获取机器 hostname,然后再在 /etc/hosts 配置文件中查找 hostname 对应的配置 IP。

第四步通过 socket 连接注册中心从而获取本机 IP。
如果上述几步都不成功,Dubbo 将会轮询本机所有网卡,直到找到合适的 IP 地址。

问题原因
通过排查上述几个规则,最后发现本地 /etc/hosts 文件 IP 配置错误, hostname 配置成了 A 机房的 IP 。
总结
Dubbo 在 IP 解析上花费很大功夫,最大程度上帮我们自动获取正确 IP。但是现实还是很残酷,真实环境下机器可能存在多网卡,内外网 IP,VPN ,或者应用采用 Docker 部署,这些情况下Dubbo 有可能就会获取到错误 IP,从而导致消费者调用失败。如果真遇到这种情况,读者首先通过上面顺序排查 IP 读取来源,若最后确定 IP 读取自网卡 。这种情况下就只能根据下面几种方式显示指定 IP。
配置方式一:
在 JVM 启动参数中加入如下配置
-DDUBBO_IP_TO_BIND=1.2.3.4
配置方式二:
在 /etc/hosts 设置 hostname 对应的 IP。
配置方式三:
Dubbo 配置文件显示指定 IP。
<!-- protocol 指定整个 Dubbo 应用服务默认 IP -->
<dubbo:protocol host="1.2.3.4"/>
<!-- provider 指定 Dubbo 应用具体某个服务默认 IP -->
<dubbo:provider host="1.2.3.4"/>
随便聊聊
这次的问题其实不大,就是 hosts 文件配置错误,但是整个查找问题的过程还是值得学习的,深入到了源码层面,跟踪代码,最终发现问题。生产出现问题,如何第一时间定位到问题,这是一门学问。我们不仅要了解业务代码,也要清楚框架的原理。每一次的踩坑经历,都是一次考验,经历的多了,经验自然也会多了,这也许就是资深程序员与初级程序员差别。
帮助链接
https://dubbo.apache.org/zh-cn/blog/dubbo-network-interfaces.html
欢迎关注我的公众号:程序通事,获得日常干货推送。如果您对我的专题内容感兴趣,也可以关注我的博客:studyidea.cn

Dubbo 服务 IP 注册错误踩坑经历的更多相关文章
- nginx搭建网站踩坑经历
为了更好的阅读体验,请访问我的个人博客 前言 早上刷抖音刷到一个只需要三步的nginx搭建教程(视频地址),觉得有些离谱,跟着复现了一遍,果然很多地方不严谨并且省略了大量步骤,对于很多不了解linux ...
- 『审慎』.Net4.6 Task 异步函数 比 同步函数 慢5倍 踩坑经历
异步Task简单介绍 本标题有点 哗众取宠,各位都别介意(不排除个人技术能力问题) —— 接下来:我将会用一个小Demo 把 本文思想阐述清楚. .Net 4.0 就有了 Task 函数 —— 异步编 ...
- TiDB 深度实践之旅--真实“踩坑”经历
美团点评 TiDB 深度实践之旅(9000 字长文 / 真实“踩坑”经历) 4 PingCAP · 154 天前 · 3956 次点击 这是一个创建于 154 天前的主题,其中的信息可能已经有所发 ...
- Net4.6 Task 异步函数 比 同步函数 慢5倍 踩坑经历
Net4.6 Task 异步函数 比 同步函数 慢5倍 踩坑经历 https://www.cnblogs.com/shuxiaolong/p/DotNet_Task_BUG.html 异步Task简单 ...
- Dubbo入门到精通学习笔记(十二):Dubbo消费端直连提供者(开发调试)、Dubbo服务只订阅(开发调试)、Dubbo服务只注册
文章目录 Dubbo消费端直连提供者(开发调试) Dubbo服务只订阅(开发调试) Dubbo服务只注册 Dubbo消费端直连提供者(开发调试) Dubbo 官方文档: 用户指南 >> 示 ...
- myeclipse使用db-brower连接到sqlserver2012踩坑经历
myeclipse使用db-brower连接到sqlserver踩坑经历 首先得建立个角色 右键->创建登录名 权限开大点 连接设置 Driver template选择我选这个,格式按照我的写 ...
- sqlserver安装和踩坑经历
sqlserver安装和踩坑经历 下载 下载 安装 大致是按照这个来的 安装教程 出错 windows系统安装软件弹出"Windows installer service could not ...
- 使用BeanUtils.copyProperties踩坑经历
1. 原始转换 提起对象转换,每个程序员都不陌生,比如项目中经常涉及到的DO.DTO.VO之间的转换,举个例子,假设现在有个OrderDTO,定义如下所示: public class OrderDTO ...
- 【踩坑经历】一次Asp.NET小网站部署踩坑和解决经历
2013年给1个大学的小客户部署过一个小型的Asp.NET网站,非常小,用的sqlite数据库,今年人家说要换台服务器,要重新部署一下,好吧,虽然早就过了服务时间,但无奈谁叫人家是客户了,二话不说,上 ...
随机推荐
- Spring 框架学习(1)--Spring、Spring MVC扫盲
纸上得来终觉浅,绝知此事要躬行 文章大纲 什么是spring 传统Java web应用架构 更强的Java Web应用架构--MVC框架 Spring--粘合式框架 spring的内涵 spring核 ...
- 深入理解es6中的Promise
https://www.jianshu.com/p/9e4af5b77253 https://zhuanlan.zhihu.com/p/30797777 https://segmentfault.co ...
- java学生管理系统(增、删、改、查功能)
package mm; import java.util.Scanner;import java.util.ArrayList; class Student1 { private String stu ...
- python shutil 文件(夹)的复制、删除、移动、压缩和解压
高级的 文件.文件夹.压缩包 处理模块 shutil.copyfileobj(fsrc, fdst[, length])将文件内容拷贝到另一个文件中 import shutil shutil.copy ...
- windows下远程访问Linux系统中mysql
1,查询MySQL数据库是否允许远程ip访问,命令如下: sql语句: use mysql; select host, user from user; 查询结果为127.0.0.1或者localhos ...
- 关于github显示不出来图片的问题
今天打开github,突然发现图标图片等都显示不出来了. 控制台看了一下 百度查找了Failed to load resource: net::ERR_CERT_COMMON_NAME_INVALID ...
- Hystrix 监控数据聚合 Turbine【Finchley 版】
原文地址:https://windmt.com/2018/04/17/spring-cloud-6-turbine/ 上一篇我们介绍了使用 Hystrix Dashboard 来展示 Hystrix ...
- sense8影评摘抄
“卡尔维诺在<为什么读经典>中<西诺拉在月球>一章里如是记述: 月球上的贵族光着身子四处走,仿佛这样还够,他们还在腰间悬挂阳具造型的铜饰.“我觉得这个习俗真是奇特.在我们的世界 ...
- 投入OJ的怀抱~~~~~~~~~~
OpenJudge C20182024 信箱(1) 账号 修改设定 退出小组 管理员 frank 林舒 Dzx someone 李文新 公告 11-05 程序设计与算法(大学先修课) 成员(61910 ...
- Windows玩转Kubernetes系列2-Centos安装Docker
接上一章,Windows玩转Kubernetes系列1-VirtualBox安装Centos,我们开始学习如何在Centos中安装Docker 准备 关闭防火墙 防火墙一定要提前关闭,否则在后续安装K ...