# Dubbo常见问题
写在前面,所以分析基于dubbo 2.7.7
# 1. 注册到注册中心的地址为127.0.0.1,不是你想要的地址
可以写死,但不推荐,ip变了怎么办,网络环境变更怎么办
- 通过
ifconfig
命令,查询你想要注册的ip所在的网卡名称 - 设置启动参数
-Ddubbo.network.interface.preferred=en0
注意:
- dubbo.network.interface.preferred参数在dubbo2.7.6及之后的版本中支持
- 该参数只是指明dubbo优先获取的网卡信息,若没有该网卡,则会按默认的逻辑去获取ip,既找不到指定网卡,也会有兜底的逻辑在。 查找逻辑参考下面这段代码, org.apache.dubbo.common.utils.NetUtils#findNetworkInterface
public static NetworkInterface findNetworkInterface() {
List<NetworkInterface> validNetworkInterfaces = emptyList();
try {
validNetworkInterfaces = getValidNetworkInterfaces();
} catch (Throwable e) {
logger.warn(e);
}
NetworkInterface result = null;
// Try to find the preferred one
for (NetworkInterface networkInterface : validNetworkInterfaces) {
if (isPreferredNetworkInterface(networkInterface)) {
result = networkInterface;
break;
}
}
if (result == null) { // If not found, try to get the first one
result = first(validNetworkInterfaces);
}
return result;
}
# 2. 日志文件被dubbo的日志填满
- 确认使用的注册中心,通过注册中心确认名称
- zookeeper: org.apache.dubbo.registry.zookeeper.ZookeeperRegistry
- nacos: org.apache.dubbo.registry.nacos.NacosRegistry
- redis: org.apache.dubbo.registry.redis.RedisRegistry
- sofa: org.apache.dubbo.registry.sofa.SofaRegistry
- multiple: org.apache.dubbo.registry.multiple.MultipleRegistry
- multicast: org.apache.dubbo.registry.multicast.MulticastRegistry
- etcd: org.apache.dubbo.registry.multicast.MulticastRegistry
- dubbo: org.apache.dubbo.registry.dubbo.DubboRegistry
- consul: org.apache.dubbo.registry.consul.ConsulRegistry
- 在logback.xml中新增配置
<logger name="通过上一步确认的名称" level="ERROR" />
# 3. Dubbo调用报错"safe guard client , should not be called ,must have a bug."
tips: 属于dubbo官方的bug,已在2.7.9版本被修复
以下为官方解答
# 具体触发条件
- 启动一个普通consumer和一个provider,consumer可以正常调用。
- 关闭provider进程,观察注册中心,一直等到provider注册的url消失。
- 重启provider进程,consumer再次调用,报"safe guard client , should not be called ,must have a bug.",并且之后每5000次调用会触发一次。
# 问题根源
LazyConnectExchangeClient在两种情况下被使用,这两种情况需要表现的行为不一样,但是代码一样导致。
- consumer主动设置为延迟连接
- consumer和provider断开连接时进行防御式编程,如果在连接关闭后还有请求过来就用这个延迟初始化的client处理一下
# 具体到上面的这个例子
- 第一步consumer正常调用时,DubboProtocol里面referenceClientMap字段保存了consumer连接provider的ReferenceCountExchangeClient。
- 第二步关闭provider进程一直到provider注册url消失时,referenceClientMap字段里面的引用还在,但是ReferenceCountExchangeClient的replaceWithLazyClient方法被调用,内部的ExchangeClient换成了LazyConnectExchangeClient。
- 第三步provider进程重启,consumer再次调用时,会重新获取到这个已经关闭的ReferenceCountExchangeClient。判断代码为
referenceCountExchangeClient == null || referenceCountExchangeClient.isClosed()
而referenceCountExchangeClient.isClosed()会调用到LazyConnectExchangeClient的isClosed方法
if (client != null) {
return client.isClosed();
} else {
return false;
}
此时还没有延迟初始化,会直接返回false,导致后续的调用都会使用这个client,每5000报告一次warning。
具体修复方式为模仿replaceWithLazyClient方法里的方式,在场景不同时添加参数。 通过增加一个LAZY_CLOSE_STATE_KEY,强制设置isClosed方法修改的返回值,isClosed()方法内容改为
if (closeState != null) {
return closeState;
}
if (client == null) {
return false;
} else {
return client.isClosed();
}
# 4. dubbo调用超时,并不是方法本身超时。报错如下
org.apache.dubbo.remoting.TimeoutException: Waiting server-side response timeout by scan timer.
start time: 2022-03-29 19:28:06.163, end time: 2022-03-29 19:28:07.179, client elapsed: 2 ms, server elapsed: 1014 ms, timeout: 1000 ms,
request: Request [id=2, version=2.0.2, twoway=true, event=false, broken=false, data=null],
channel: /127.0.0.1:61872 -> /127.0.0.1:7890
# 问题解决
检查一下是否开了代理,如果是,关闭即可