fastDFS服务挂掉重启后客户端无法连接异常

客户端版本

<dependency>
    <groupId>com.github.tobato</groupId>
    <artifactId>fastdfs-client</artifactId>
    <version>1.27.2</version>
</dependency>

异常信息

ERROR o.a.c.c.C.[.[localhost].[/].[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: Unable to borrow buffer from pool] with root cause 
com.github.tobato.fastdfs.exception.FdfsUnavailableException: 无法获取服务端连接资源:找不到可用的tracker /192.168.0.127:22122,

这个异常会在tricker挂掉之后出现,但是重启后依然会报这个异常,并且持续10分钟。

具体原因是:
TrackerConnectionManager中的executeFdfsTrackerCmd()方法中的address = trackerLocator.getTrackerAddress();出现异常。

public <T> T executeFdfsTrackerCmd(FdfsCommand<T> command) {
    Connection conn = null;
    InetSocketAddress address = null;
    // 获取连接
    try {
        address = trackerLocator.getTrackerAddress();
        LOGGER.debug("获取到Tracker连接地址{}", address);
        conn = getConnection(address);
        trackerLocator.setActive(address);
    } catch (FdfsConnectException e) {
        trackerLocator.setInActive(address);
        throw e;
    } catch (Exception e) {
        LOGGER.error("Unable to borrow buffer from pool", e);
        throw new RuntimeException("Unable to borrow buffer from pool", e);
    }
    // 执行交易
    return execute(address, conn, command);
}

继续向下追踪发现是holder的canTryToConnect()方法问题

public InetSocketAddress getTrackerAddress() {
    TrackerAddressHolder holder;
    // 遍历连接地址,抓取当前有效的地址
    for (int i = 0; i < trackerAddressCircular.size(); i++) {
        holder = trackerAddressCircular.next();
        if (holder.canTryToConnect(retryAfterSecond)) {
            return holder.getAddress();
        }
    }
    throw new FdfsUnavailableException("找不到可用的tracker " + getTrackerAddressConfigString());
}

进入canTryToConnect()方法,结果很明了了,如果上次失败了,就一直得等到超过重试时间才会继续尝试。

public boolean canTryToConnect(int retryAfterSecend) {
    // 如果是有效连接
    if (this.available) {
        return true;
        // 如果连接无效,并且达到重试时间
    } else if ((System.currentTimeMillis() - lastUnavailableTime) > retryAfterSecend * 1000) {
        return true;
    }
    return false;
}

查询重试时间配置发现这个值无法配置。主要配置代码如下(来自多个类)。

	/**
     * 10分钟以后重试连接
     */
    private static final int DEFAULT_RETRY_AFTER_SECOND = 10 * 60;
	/**
     * 连接中断以后经过N秒重试
     */
    private int retryAfterSecond = DEFAULT_RETRY_AFTER_SECOND;

	/**
     * 初始化方法
     */
    @PostConstruct
    public void initTracker() {
        LOGGER.debug("init trackerLocator {}", trackerList);
        trackerLocator = new TrackerLocator(trackerList);
    }
	
	/**
     * 初始化Tracker服务器地址
     * 配置方式为 ip:port 如 192.168.1.2:21000
     *
     * @param trackerList
     */
    public TrackerLocator(List<String> trackerList) {
        super();
        this.trackerList = trackerList;
        buildTrackerAddresses();
    }

解决方法:
1. 改源码。
2. 获取相关对象修改值
3. 接受10分钟不能用。

我使用第二种

import com.github.tobato.fastdfs.domain.conn.TrackerConnectionManager;
import com.github.tobato.fastdfs.domain.fdfs.TrackerLocator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;

/**
 * 项目启动监听器
 */
@Component
public class ApplicationStartedEventListener implements ApplicationListener<ApplicationReadyEvent> {
    private Logger logger = LoggerFactory.getLogger(ApplicationStartedEventListener.class);

    @Resource
    private TrackerConnectionManager trackerConnectionManager;
    @Value("${fdfs.retry-after-second}")
    private Integer retryAfterSecond;

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        logger.info("spring启动成功!");

        try {
            logger.info("修改fastDFS重连时间为" + retryAfterSecond + "秒");
            Field field = trackerConnectionManager.getClass().getDeclaredField("trackerLocator");
            field.setAccessible(true);
            TrackerLocator trackerLocator = (TrackerLocator) field.get(trackerConnectionManager);
            trackerLocator.setRetryAfterSecond(retryAfterSecond);
            field.set(trackerConnectionManager, trackerLocator);
            logger.info("修改fastDFS重连时间成功");
        } catch (Exception e) {
            logger.error("修改fastDFS重连时间异常:", e);
        }

    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!关于FastDFS公网无法连接客户端的问题,可能有以下几个原因导致: 1. 防火墙设置:请确保您的公网服务器上的防火墙设置正确,允许FastDFS使用的端口通过。默认情况下,FastDFS使用的端口是23000(Tracker Server)和8888(Storage Server),您可以根据您的配置进行相应的调整。 2. 网络配置:请确保您的公网服务器的网络配置正确,包括IP地址、子网掩码、网关等。尤其要确保公网IP地址是正确的,并且可以从外部网络访问。 3. Tracker Server配置:请检查您的Tracker Server配置文件(通常是tracker.conf),确保绑定的IP地址是您公网服务器的IP地址,而不是内部网络的IP地址。您可以通过修改配置文件中的`bind_addr`参数来指定要绑定的IP地址。 4. Storage Server配置:如果您使用了Storage Server,请确保Storage Server的配置文件(通常是storage.conf)中的`tracker_server`参数正确地指向您的Tracker Server的公网地址。如果您有多个Tracker Server,确保配置文件中指定了所有Tracker Server的公网地址。 5. NAT转发:如果您的公网服务器位于NAT后面(例如在局域网中),请确保正确设置了NAT转发规则,将FastDFS使用的端口映射到公网IP地址上。 希望以上信息对您有所帮助!如果问题仍然存在,请提供更多详细的错误信息和配置细节,以便我能够更好地帮助您解决问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值