Connection.close () не закрывает соединение, оно заставляет его спать вечно? - PullRequest
0 голосов
/ 27 августа 2018

В моем веб-приложении, которое я пишу с использованием Java, и оно использует tomcat и sql server, я не могу закрыть соединения с базой данных, введя connection.close (). Когда я записываю sp_who в SSMS, я вижу, что количество спящих соединений, которое я открываю, увеличивается, пока мое приложение выполняет sql.

Пример кода приведен ниже:

BaseRepository baseRepository = new BaseRepository();
try{
    baseRepository.createStatement();

    baseRepository.stmt.executeUpdate("update AutoRunURLs set STATUS = 0");

}catch (SQLException e){
    e.printStackTrace();
}finally {
    baseRepository.cleanResources();
}

Вот другие функции, которые я использовал выше:

public void openConnection() {
    try {
        this.conn = ds.getConnection(); // ds is an instance of javax.sql.DataSource
        this.isOpen = true;
    } catch (Exception e) {
        e.printStackTrace();
    }
}

 public void createStatement() {
    try {
        if (!this.isOpen) this.openConnection();
        this.stmt = this.conn.createStatement();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public void cleanResources() {
    try {
        if (this.rs != null) {
            rs.close();
            this.rs = null;
        }
        if (this.stmt != null) {
            stmt.close();
            this.stmt = null;
        }
        if (this.conn != null) {
            this.closeConnection();
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (this.conn != null) this.closeConnection();
    }
}

 public void closeConnection() {
    try {
        if (this.conn != null){
            this.conn.close();
        }
        this.isOpen = false;
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Когда я запускаю первую часть выше, которая начинается с BaseRepository baseRepository ..., происходит одно спящее соединение, которое я вижу при наборе sp_who, и оно не закрывается (я ждал около дня). Это почему? Как я могу предотвратить это?

И у меня есть еще одна ситуация. В моих конфигурациях tomcat я установил значение «maxIdle» на 10, но даже это количество спящих соединений увеличивается до тысячи через неделю. Почему maxIdle не влияет? Вот как я это установил:

<Context>

<!-- Default set of monitored resources. If one of these changes, the    -->
<!-- web application will be reloaded.                                   -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<Resource auth="Container" driverClassName="net.sourceforge.jtds.jdbc.Driver" maxTotal="999999" maxIdle="10" "Database info here..." validationQuery="select 1"/>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->

Как я могу решить это? С уважением,


Редактировать: Я действительно справился с этим, создав запланированное задание, которое запускается каждые x минут и уничтожает спящие соединения, которые спят в течение y минут. Но это не так, как я хочу. Любое другое решение будет отличным.

1 Ответ

0 голосов
/ 27 августа 2018

Вы используете пул соединений, встроенный в Tomcat. Это означает, что он сохраняет соединения открытыми для повторного использования. Когда вы закрываете соединения в своем коде, они на самом деле не закрываются, а возвращаются в пул для повторного использования вашим приложением. Это повышает эффективность, потому что открытие новых соединений требует времени.

Другими словами, в этом нет ничего плохого, и при сохранении открытых соединений ожидается поведение.

Возможно, вы захотите уменьшить ваше maxTotal до более нормального значения, скажем, 10 - 20 вместо 999999.

Кроме того, то, как вы обрабатываете соединения, немного странно и позволяет очень легко пропускать соединения. Возможно, вы просто захотите получить соединение из источника данных, когда вам это действительно нужно, и узнать о попытке с ресурсами, чтобы закрыть его как можно скорее.

...