Устранить резко закрытые сокеты из пула 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;
}
}