Исключить резко закрытые сокеты из пула, Java

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

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

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

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

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

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

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

Как очистить внезапно закрытые сокеты в моем пуле?


person Kana    schedule 15.08.2014    source источник


Ответы (2)


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

person zigot    schedule 15.08.2014
comment
@Сурья Мусор. Ответ заключается в том, что это невозможно сделать иначе, как предложено здесь. - person user207421; 15.08.2014

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

  • нет потока демона для проверки.
  • It will check passive as trying to get a connection
    • connection.isClosed will check the socket status, of course it is not reliable
    • чтобы проверить, не истек ли срок действия соединения
  • И он будет проверять, как возвращается соединение. вы должны пометить соединение закрытым, пока существует исключение, использующее его.

/** * @автор:xingchaowang * @дата: 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;
}

}

person kino lucky    schedule 15.08.2014
comment
Если сокет закрыт, его не следует помещать в пул в первую очередь. - person user207421; 15.08.2014
comment
Соединение нельзя закрывать сразу после создания, это всего лишь оболочка. Это не настоящее сокетное соединение. Он пытается создать сокет только при первом использовании. И создание и подключение сокета может потребовать некоторого времени, поэтому постарайтесь уменьшить стоимость этого места. - person kino lucky; 16.08.2014
comment
Если это ответ на мой комментарий, то нет. - person user207421; 16.08.2014