У моего приложения с поддержкой RMI, похоже, утечка сокетов. У меня есть приложение Java, предоставляющее сервис через RMI. Он использует реализацию Java SE 1.6 RMI, работающую в Linux. Проблема, которую я наблюдаю, состоит в том, что, если клиент получает ссылку на мой удаленный объект, используя реестр, а затем соединение прерывается внезапно (потеря питания, отключение кабеля и т. Д.), Сервер сохраняет сокет открытым. Я ожидаю, что реализация RMI будет очищена после истечения срока аренды клиента, но этого не происходит. На сервере метод unreferenced()
моего удаленного объекта вызывается по истечении срока аренды, но сокет остается видимым в netstat в состоянии «ESTABLISHED» в течение неопределенного времени.
Поскольку мы не можем принудить клиентов к каким-либо особым действиям, через несколько дней мы достигаем предела по умолчанию 1024 в нашем дистрибутиве Linux для дескрипторов открытых файлов, из-за чего сервер не может открыть какие-либо новые сокеты или файлы. Я думал о TCP keepalive, но поскольку RMI абстрагируется от сетевого уровня, у меня нет доступа к фактическому сокету сервера после того, как соединение установлено.
Есть ли способ заставить уровень RMI очистить сокеты, связанные с клиентскими соединениями с истекшим сроком аренды?
Обновление: Решение, которое я использовал, похоже на выбранный ответ, но использует другой подход. Я использовал настраиваемую фабрику сокетов, а затем обернул экземпляр ServerSocket, возвращаемый createServerSocket (), в прозрачную оболочку, которая пропускала все методы, кроме accept (). В методе accpet keepalive активируются до возвращения сокета.
public class KeepaliveSocketWrapper extends ServerSocket
{
private ServerSocket _delegate = null;
public KeepaliveSocketWrapper(ServerSocket delegate)
{
this._delegate = delegate;
}
public Socket accept() throws IOException
{
Socket s = _delegate.accept();
s.setKeepAlive(true);
return s;
}
.
.
.
}