Устранить резко закрытые сокеты из пула Java

Предположим, что есть реализация Java Object Object на Java, и объекты успешно подключены к сокетам TCP.

Я держу поток "Очистки" на уровне пула (ConnectionFactory), который проверяет каждые N минут, что пул простаивает в течение нескольких минут (т.е. последний доступ перед M минутами, здесь M>N).

А если это так, то закройте все дополнительные сокеты, пока в пуле не останется только число основных сокетов.

Теперь мне нужно отследить и устранить также резко закрытые сокеты. Это кажется необходимым, потому что я могу закрыть все рабочие и просто получить пул с резко закрытыми сокетами (закрытыми на другом конце).

Без сомнения, теперь я должен изучить уровень Socket, а не уровень фабрики соединений.

Я провел исследование по "отслеживанию внезапно закрытых сокетов в Java", "очистке пулов соединений", и в API сокетов Java ничего нет, если только мы не отправили ACK или KeepAliveChecks (для каждого сокета). Что означает, что мне нужно выполнять это на каждом сокете в обычном режиме.

Каков наилучший способ (то есть: есть ли другой способ), чтобы я мог в конечном итоге держать хороших парней (хорошо подключенные сокеты) в моем пуле?

Как убрать резко закрытые сокеты в моем бассейне?

2 ответа

Я не знаю других способов проверить, жив ли сокет. Вы можете использовать TimerTask для отправки рутинных KeepAliveChecks и удаления сокетов, которые не проходят проверку.

Интересно, я только вчера написал пул соединений с сокетами.

  • нет потока демона для проверки.
  • Он будет проверять пассивность при попытке установить соединение
    • connection.isClosed будет проверять состояние сокета, конечно, это не надежно
    • проверить, не истекло ли соединение
  • И это проверит как возвращение соединения. Вы должны пометить соединение как закрытое, пока есть исключение, использующее его.

/ ** * @author: xingchaowang * @date: 14.08.2014. */

открытый класс ConnectionPoolImpl реализует ConnectionPool {

private volatile int minConnections;
private volatile int maxConnections;
private volatile long connectionTTL;
private volatile long leaseTimeout = 1000;

private AtomicInteger pending = new AtomicInteger(0);

private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();

private LinkedList<Connection> free = new LinkedList<Connection>();
private Set<Connection> leased = new HashSet<Connection>();

private ConnectionFactory connectionFactory;

public ConnectionPoolImpl(int minConnections, int maxConnections, long connectionTTL, long leaseTimeout, ConnectionFactory connectionFactory) {

    this.minConnections = minConnections;
    this.maxConnections = maxConnections;
    this.connectionTTL = connectionTTL;
    this.leaseTimeout = leaseTimeout;
    this.connectionFactory = connectionFactory;
}

@Override
public Connection lease() throws Exception {
    return lease(1000);
}

@Override
public Connection lease(long timeout) throws Exception {
    pending.incrementAndGet();
    lock.lock();
    try {
        Connection connection = null;
        Date deadLine = new Date(System.currentTimeMillis() + timeout);

        while (true) {
            long now = System.currentTimeMillis();

            //If the count of existing connections is less than minConnections, create new one and return.
            if (_connectionCount() < minConnections) {
                return _createAndLease();
            }

            //Try to get a connection from the free list.
            while ((connection = free.pollFirst()) != null) {
                if (connection.isClosed()) {
                    continue;
                } else if (connection.getCreatedTime() + connectionTTL < now) {
                    connection.close();
                }else{
                    leased.add(connection);
                    return connection;
                }
            }

            //Free list is empty, try to create new one if doesn't reach the upper limit maxConnections.
            if (_connectionCount() < maxConnections) {
                return _createAndLease();
            }

            condition.awaitUntil(deadLine);

            //Try to get again if doesn't reach the deadLine, or return by throwing a TimeoutException.
            if (deadLine.getTime() >= System.currentTimeMillis()) {
                throw new TimeoutException("Timeout waiting for connection");
            }
        }
    } finally {
        lock.unlock();
        pending.decrementAndGet();
    }
}

@Override
public void release(Connection connection) {
    lock.lock();
    try{
        long now = System.currentTimeMillis();

        leased.remove(connection);

        if (connection.isClosed()) {
            return;
        } else if (connection.getCreatedTime() + connectionTTL < now) {
            connection.close();
        }else{
            free.add(connection);
        }
    }finally {
        condition.signal();
        lock.unlock();
    }
}

@Override
public PoolStats poolStats() {
    return new PoolStats(leased.size(),free.size(),pending.get(),minConnections,maxConnections);
}

private int _connectionCount() {
    return free.size() + leased.size();
}

private Connection _createAndLease() throws Exception {
    Connection connection;
    connection = connectionFactory.create();
    leased.add(connection);
    return connection;
}

public int getMinConnections() {
    return minConnections;
}

public void setMinConnections(int minConnections) {
    this.minConnections = minConnections;
}

public int getMaxConnections() {
    return maxConnections;
}

public void setMaxConnections(int maxConnections) {
    this.maxConnections = maxConnections;
}

public long getConnectionTTL() {
    return connectionTTL;
}

public void setConnectionTTL(long connectionTTL) {
    this.connectionTTL = connectionTTL;
}

public long getLeaseTimeout() {
    return leaseTimeout;
}

public void setLeaseTimeout(long leaseTimeout) {
    this.leaseTimeout = leaseTimeout;
}

}

Другие вопросы по тегам