# Dubbo常见问题

写在前面,所以分析基于dubbo 2.7.7

# 1. 注册到注册中心的地址为127.0.0.1,不是你想要的地址

可以写死,但不推荐,ip变了怎么办,网络环境变更怎么办

  1. 通过ifconfig命令,查询你想要注册的ip所在的网卡名称 查询网卡名称
  2. 设置启动参数-Ddubbo.network.interface.preferred=en0

注意:

  1. dubbo.network.interface.preferred参数在dubbo2.7.6及之后的版本中支持
  2. 该参数只是指明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的日志填满

  1. 确认使用的注册中心,通过注册中心确认名称
  • 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
  1. 在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版本被修复

以下为官方解答

# 具体触发条件

  1. 启动一个普通consumer和一个provider,consumer可以正常调用。
  2. 关闭provider进程,观察注册中心,一直等到provider注册的url消失。
  3. 重启provider进程,consumer再次调用,报"safe guard client , should not be called ,must have a bug.",并且之后每5000次调用会触发一次。

# 问题根源

LazyConnectExchangeClient在两种情况下被使用,这两种情况需要表现的行为不一样,但是代码一样导致。

  1. consumer主动设置为延迟连接
  2. consumer和provider断开连接时进行防御式编程,如果在连接关闭后还有请求过来就用这个延迟初始化的client处理一下

# 具体到上面的这个例子

  1. 第一步consumer正常调用时,DubboProtocol里面referenceClientMap字段保存了consumer连接provider的ReferenceCountExchangeClient。
  2. 第二步关闭provider进程一直到provider注册url消失时,referenceClientMap字段里面的引用还在,但是ReferenceCountExchangeClient的replaceWithLazyClient方法被调用,内部的ExchangeClient换成了LazyConnectExchangeClient。
  3. 第三步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

# 问题解决

检查一下是否开了代理,如果是,关闭即可

Last Updated: 6/26/2022, 4:44:06 PM