Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Пул коннектов, чтоб его... 
V
    Опции темы
koroplysov
Дата 8.4.2011, 08:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 29.8.2009

Репутация: нет
Всего: нет



Описание проблемы:
Для написания приложения использую NetBeans+Tomcat+DB2, версия языка 1.4. На боевом сервере WebSphere(x86)+DB2. Коннект происходит через мост jdbc-odbc.
Далее в исторической последовательности. Все построено на сервлетах. Приложение использует небольшое количество людей(около 50 чел), но они активно вносят данные. Эти данные записываются в базу. В базе все нормализовано и поэтому достаточно много связей. Как следствие при внесения записи в одну таблицу то заносятся и вдругие(в среднем 1 к 5). В день около 500 а всего в итоге в среднем 2500(500*5) записей вносится. Ночью делается бекап базы.  
Вначале делал просто: на каждый insert, update,delete и select открывался отдельный коннект и после использования закрывал. Но через некоторое время(в зависимости от активности, бывало и каждый час) на боевом сервере WebSphere зависала и приходилось перезапускать, хотя сервер(железка) очень быстрый(16 ядер 8Гб).
Второй вариант хранить один глобальный коннект который создавался и запускался(в ServletContextListener) так:
Код

        public static Connection con = null;
        public static void OpenConnectionBD()
        {
            if (con == null)
            {
                try {
                    try {
                        Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
                    } catch (ClassNotFoundException eс) {
                        return ;
                    }
                    con= DriverManager.getConnection("jdbc:odbc:база","логин","пароль");
                } catch (SQLException e1) {
                    return ;
                }
            }else{
                try {
                    if (con.isClosed()) {
                        try {
                            try {
                                Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
                            } catch (ClassNotFoundException eс) {
                                return;
                            }
                        con= DriverManager.getConnection("jdbc:odbc:база","логин","пароль");
                        } catch (SQLException e1) {
                            return;
                        }
                    }
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
            }
        }
        public static void CloseConnectionDB()
        {
            try {
                if (con!= null && !con.isClosed()) {
                    try {
                        con.close();
                    } catch (SQLException e3) {
                    }
                }
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }

Это работает замечально, но каждое утро коннект теряется и не восстанавливается. Подозреваю что после ночного резервирования(при этом коннекты отрубаются). Прочитал про пул соединений. Скачал commons-dbcp. Толком поэтапного объяснения не нашел, но нашел одну статейку откуда целиком все и содрал:
Код

import java.io.*;
 import java.sql.*;
 import java.util.*;

import org.apache.commons.dbcp.*;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.*;


public class ConnectionPool {
    protected GenericObjectPool connectionPool=null;

   public void initConnectionPool( String driver, String dbURL, String dbUser, String dbPswd )
   {
     try
     {
       Class.forName( driver ).newInstance();//создаем новый объект класса драйвера,
       //тем самым инициализируя его

       connectionPool = new GenericObjectPool( null );//создаем GenericObjectPool
       //создаем connection factory ("фабрика соединений" - объект который будет создавать соединения)
       ConnectionFactory connectionFactory = new DriverManagerConnectionFactory( dbURL, dbUser, dbPswd );

       //создаем PoolableConnectionFactory
       PoolableConnectionFactory pcf=new PoolableConnectionFactory( connectionFactory, connectionPool, null, "SELECT 1", false, true );

       PoolingDataSource pds=new PoolingDataSource( connectionPool);
       connectionPool.setMaxIdle( 20 );//устанавливаем максимальное кол-во простаивающих соединений
       connectionPool.setMaxActive( 200 );//устанавилваем макс. кол-во активных соединений
     }
     catch( Exception ex )
     {
        ex.printStackTrace();
     }
   }
   public final Connection getConnection()
   {
     try
     {
       if( connectionPool.getMaxActive() <= connectionPool.getNumActive() )
       {
          //System.err.println( "Connections limit is over!!!" );
           int y=0;
       }

       Connection con = (Connection)connectionPool.borrowObject();
       return con;
     }
     catch( Exception ex )
     {
       ex.printStackTrace();
       return null;
     }
   }

   /**
    * Функция возвращения connection в пул
    */
   public final void returnConnection( Connection con )
   {
     if( con == null )
     {
       return;
     }

     try
     {
       connectionPool.returnObject( con );
     }
     catch( Exception ex )
     {
     }
   }

   public static void mainm()
   {
     //создаем наш объект ConnectionPool
     ConnectionPool pool = new ConnectionPool();
     //единожды инициализируем его указав класс драйвера, URL базы данных, а также логин и пароль к базе данных
     pool.initConnectionPool( "sun.jdbc.odbc.JdbcOdbcDriver", "jdbc:odbc:база", "логин", "пароль" );

     //получаем connection
     Connection con = pool.getConnection();

     //что нибудь делаем
     PreparedStatement ps = null;
        try {
            ps = con.prepareStatement("SELECT * FROM USERS");
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
        String s="";
        ResultSet rs = null;
        try {
            rs = ps.executeQuery();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
        try {
            while (rs.next()) {
                s+=rs.getString("ID_US")+"***";
            }
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
        try {
            ps.close();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }

     //возвращаем соединение в пул
     pool.returnConnection( con );
     s="";
   }
}

Храню глобальный ConnectionPool где и беру коннект, а создаю в ServletContextListener. В mainm пример использования. Каюсь коннект не возвращал после использования(вот при написании увидел), но как-то все слишком сложно. Результат: Через пол часа или меньше(работал я один) на боевом сервере приложение безнадежно виснет.

Собственно вопросы и просьбы:
Объясните как этим пулом пользоваться.
Не повлияет ночной бекап на соединения(они же рвутся)?
Обязательно ли возвращать коннекты?
Можно ли зарезервировать минимальное количество активных коннектов?
Большая просьба привести подробный пример, вы сделаете большое дела для таких как я.
Зависит ли commons-dbcp от Tomcat и будет ли нормально работать на WebSphere?
Спасибо!!!

Это сообщение отредактировал(а) koroplysov - 8.4.2011, 09:41
PM MAIL   Вверх
dobrolub
Дата 8.4.2011, 09:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 385
Регистрация: 18.12.2009
Где: Vancouver, Canada

Репутация: 4
Всего: 16



>Вначале делал просто: на каждый insert, update,delete и select открывался отдельный коннект.
Начни их возвращать - это будет первый правильный шаг, который, возможно, и решит проблему. 

- WebSphere имеет свой модуль соединений. Тебе надо его сконфигурировать и запрашивать соединения из объекта DataSource, который станет доступен на jndi.
- На томкат тоже научись это делать так, чтобы пул клал javax.sql.DataSource на JNDI.

Шаблон работы с соединениями следующий:

Код

import java.io.*;
import java.sql.*;
import javax.naming.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.sql.*;

public class MyServlet extends HttpServlet {
  public void service(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
     InitialContext context = new InitialContext();
     DataSource ds = (DataSource)context.lookup("java:comp/env/mydatasource");
     Connection con;
     try {
       con = ds.getConnection();
       // insert, update, delete
       con.commit();
     } catch (SqlException e) {
        con.rollback();
     } finally {
        conn.close();//возвратим в пул
     }
  }
}

PM   Вверх
koroplysov
Дата 8.4.2011, 09:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 29.8.2009

Репутация: нет
Всего: нет



Спасибо за советы!

Коннекты я всегда conn.close();. Сконфигурировать соединение на вебсфере не проблема. Проблема в логике работы. Использую отдельный пул на случай если на сервере такого нет(использую то odbc). За сервлет спасибо. Не нужно ли будет перенастраивать чего при переходе с Tomcat на WebSphere?
PM MAIL   Вверх
koroplysov
Дата 8.4.2011, 10:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 29.8.2009

Репутация: нет
Всего: нет



Что-то приложение не виснет после того как я прописал отдачу в пул коннекта pool.returnConnection( con ); где pool типа ConnectionPool(из второго листинга).
Помоему всетаки по этой причине.
Буду держать в курсе пишущих и смотрящих.
PM MAIL   Вверх
koroplysov
Дата 11.4.2011, 08:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 29.8.2009

Репутация: нет
Всего: нет



Все виснет через некоторое время!!!
PM MAIL   Вверх
batigoal
Дата 11.4.2011, 08:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


Профиль
Группа: Участник Клуба
Сообщений: 6423
Регистрация: 28.12.2004
Где: Санктъ-Петербургъ

Репутация: 16
Всего: 151



koroplysov, значит, ищи утечку. Можешь воспользоваться профайлером, либо на стороне базы посмотреть активные коннекты и исполняющийся в них код (не знаю, возможно ли это в DB2).


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
koroplysov
Дата 11.4.2011, 09:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 29.8.2009

Репутация: нет
Всего: нет



Блин, начинаю отчаиваться!!!
Народ научите использовать соединение JNDI, пожалуйста. Для кода в последнем листинге. Как на сервере(WebSphere) настроить я знаю. Как это в NetBeans настроить? smile 
PM MAIL   Вверх
dobrolub
Дата 11.4.2011, 19:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 385
Регистрация: 18.12.2009
Где: Vancouver, Canada

Репутация: 4
Всего: 16



PM   Вверх
koroplysov
Дата 12.4.2011, 07:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 29.8.2009

Репутация: нет
Всего: нет



С праздником всех!!!
Мы всегда будем первыми на земном шаре и в космосе!!!

Теперь по делу. Решил я всетаки настроить второй листинг и изменил:
Код

       connectionPool.setMaxIdle(20);//устанавливаем максимальное кол-во простаивающих соединений
       connectionPool.setMaxActive(200);//устанавилваем макс. кол-во активных соединений
       connectionPool.setMaxWait(10000);
       connectionPool.setTestWhileIdle(true);
       //connectionPool.setTestOnBorrow(true);
       connectionPool.setTimeBetweenEvictionRunsMillis(600000);
       connectionPool.setMinEvictableIdleTimeMillis(1800000);
       connectionPool.setNumTestsPerEvictionRun(20);

Со вчерашней второй половины дня полет нормальный!!! Буду держать в курсе. Ведь удобно
PM MAIL   Вверх
mbasil
Дата 12.4.2011, 11:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 399
Регистрация: 4.5.2007
Где: Москва

Репутация: 9
Всего: 13



А что под DB2 нет нормального JDBC драйвера? Использовать мост jdbc-odbc в продукционной системе кажется каким-то извращением.
PM MAIL   Вверх
koroplysov
Дата 14.4.2011, 11:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 29.8.2009

Репутация: нет
Всего: нет



Да есть конечно. Просто так сложилась, долго объяснять.
А теперь о приятном: РАБОТАЕТ!!! Вот уже два дня работает без сбоев и резервирование базы переваривает.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.0754 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.