欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-15 17:51:07
客户端版本 com.github.tobato fastdfs-client 1.27.2异常信息ERROR o.a.c.c.C.[.[localhost].[/].[dispatcherServlet]...

客户端版本

<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);
        }

    }
}

本文地址:https://blog.csdn.net/sly1311220942/article/details/109847771

相关标签: 异常错误 java