Solucionado (ver solução)
Solucionado
(ver solução)
12
respostas

conexão caindo com frequência

Pessoal tenho uma aplicação JAVA com um pouco de spring subi essa aplicação na AMAZON "My First Elastic Beanstalk Application" e criei um banco la mesmo "Mysql" tudo esta funcionando, subo a aplicação, efetuo login, faço tudo, mas com frequência ela cai e apresenta: "Could not create connection to database server. Attempted reconnect 3 times. Giving up."

e isso sempre acontece quando tem mais uma pessoa acessando a aplicação. www.head2head.link

eu acho que minha DAO pode vir a estar incorreta, não tenho certeza, vou postar alguns métodos abaixo e quem tiver um tempinho de dar uma olhada e passar um feedback agradeço.

FACTORY

public class ConnectionFactory {

    ExceptionHandling capturaException = new ExceptionHandling();
    private final String amazonRDS = "jdbc:mysql://*********.cbdhasdqz2vq.sa-east-1.rds.amazonaws.com:3306/nadalspringmvc"; // Servidor
    private final String usuarioAmazonRDS = "********"; // Usuário
    private final String senhaAmazonRDS = "*****"; // Senha

    public Connection getConnection() throws SQLException {

        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            capturaException.ExceptionHandlerController(e);
            throw new SQLException(e);
        }

        return DriverManager.getConnection(amazonRDS, usuarioAmazonRDS, senhaAmazonRDS);
    }

}
    ExceptionHandling capturaException = new ExceptionHandling();
    private Connection connection;

    public ModalidadeDAO() {
        try {
            this.connection = new ConnectionFactory().getConnection();
        } catch (SQLException e) {
            capturaException.ExceptionHandlerController(e);
            throw new RuntimeException(e);
        }
    }
    public void adiciona(ModalidadeDTO modalidade, int sessionID) throws SQLException {

        if ("".equals(modalidade.getNomeModalidadeTemp())) {
            throw new IllegalArgumentException("Existe algum dado nulo");
        }

        String sql = "INSERT INTO dt_modalidades (nome_modalidade, id_usuario) VALUES ( ?, " + sessionID + " );";

        try {
            try (PreparedStatement stmt = connection.prepareStatement(sql)) {
                stmt.setString(1, modalidade.getNomeModalidadeTemp());
                stmt.execute();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    public List<ModalidadeDTO> seleciona(int sessionID) {

        String sql = "SELECT id_modalidade, nome_modalidade FROM dt_modalidades WHERE id_usuario = " + sessionID + " order by nome_modalidade asc;";

        try {
            List<ModalidadeDTO> results = new ArrayList<>();
            try (PreparedStatement stmt = this.connection.prepareStatement(sql);
                    ResultSet rs = stmt.executeQuery()) {

                while (rs.next()) {
                    results.add(populaConta(rs));
                }
            }
            return results;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
12 respostas

Oi Rodrigo,

tudo bem?

Uma coisa que percebi é que aparentemente você nunca fecha uma conexão. Isso pode estar sendo o gargalo da sua aplicação, se não houver essa preocupação em fechar, chega uma hora que você não consegue mais abrir pela sua Factory.

Normalmente usamos um pool de conexões para tirar esse overhead de ficar controlando abertura e fechamento das conexões.

Para minimizar isso... sem que você configure um pool de conexões... pelo menos dá um close nelas depois de ter usado. Faz a sua DAO receber uma conexão em vez de criá-la no construtor:

public ModalidadeDAO(Connection con) {
        this.con = con;
}
`

E toda vez que for usar um DAO, faça esse controle:

Connection con = new ConnectionFactory().getConnection();

dao = new ModalidadeDAO(con);
//faça as suas coisa com esse DAO ou outro tb...
con.close()

Abraços

Uma coisa que você deveria nos dizer é sobre o erro com o log completo para termos uma ajuda mais guiada.

Manda aqui :)

07-Dec-2017 14:23:23.136 SEVERE [http-nio-8084-exec-27] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [dispatcher] in context with path [/Head2Head] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.] with root cause
 com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
    at com.mysql.jdbc.Util.getInstance(Util.java:408)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:918)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:897)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:886)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:860)
    at com.mysql.jdbc.ConnectionImpl.throwConnectionClosedException(ConnectionImpl.java:1187)
    at com.mysql.jdbc.ConnectionImpl.checkClosed(ConnectionImpl.java:1182)
    at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4071)
    at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4040)
    at br.com.head2head.dao.UsuarioDAO.verificaUsuario(UsuarioDAO.java:201)
    at br.com.head2head.controller.LoginController.efetuaLogin(LoginController.java:30)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:214)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:690)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
t javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

Acredito que seja exatamente oque vc falou :/

07-Dec-2017 15:40:52.029 SEVERE [http-nio-8084-exec-3] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [dispatcher] in context with path [/Head2Head] threw exception [Request processing failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController' defined in file [C:\Users\faria\Documents\NetBeansProjects\head2headApplication\build\web\WEB-INF\classes\br\com\head2head\controller\HomeController.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [br.com.head2head.controller.HomeController]: Constructor threw exception; nested exception is java.lang.RuntimeException: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.] with root cause
 com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Too many connections

Oi Rodrigo,

isso mesmo! Para evitar isso antes de configurar um pool, você pode usar isso que comentei de fechar a connection. Ou se quiser resolver mesmo sem ter que mexer em mil pontos da sua aplicação, tem que configurar um pool nela.

Não é nada de outro mundo... você está usando qual container?Tomcat?

Abraços

usando tomcat, você tem algum material para indicar? se esta errado quero refazer certo.

Fábio, bom dia refiz a classe me diz quando tiver tempo se esta ok! pois o erro agora é outro

usuário e senha estão corretos!

public class ConnectionFactory {

    private static final String URL_MYSQL = "jdbc:mysql://*****.cbdhasdqz2vq.sa-east-1.rpool.amazonaws.com:3306/nadalspringmvc";
    private static final String USER = "***";
    private static final String PASS = "***";
    private static final String DRIVER_CLASS = "com.mysql.jdbc.Driver";

    private static ComboPooledDataSource pool;

    public static Connection getConnection() throws PropertyVetoException, SQLException {
        if (pool == null) {
            pool = new ComboPooledDataSource();
            pool.setDriverClass(DRIVER_CLASS);
            pool.setJdbcUrl(URL_MYSQL);
            pool.setUser(USER);
            pool.setPassword(PASS);
            pool.setMinPoolSize(5);//Minimo de conexões paradas(standby)   
            //pool.setAcquireIncrement(10);//   
            pool.setMaxPoolSize(30);//Maximo de conexões aberta  
            //pool.setAcquireRetryAttempts(30);
            //pool.setMaxIdleTime(60);

        }
        return pool.getConnection();
    }

}

adiciona / seleciona

public class JogadorDAO {

    ExceptionHandling capturaException = new ExceptionHandling();

    public void adiciona(JogadorDTO jogador, int sessionID) throws SQLException, PropertyVetoException {

        if ("".equals(jogador.getNomeJogadorTemp()) || "".equals(jogador.getNivelJogador()) || "".equals(jogador.getCaracteristica()) || "".equals(jogador.getMao()) || "".equals(jogador.getBackhand())) {
            throw new IllegalArgumentException("Existe algum dado nulo");
        }
        try (Connection connection = ConnectionFactory.getConnection()) {
            String sql = "INSERT INTO dt_jogadores (nome_jogador, nivel_jogador, caracteristica, mao, backhand, id_usuario)VALUES(?,?,?,?,?, " + sessionID + ")";
            try (PreparedStatement stmt = connection.prepareStatement(sql)) {
                stmt.setString(1, jogador.getNomeJogadorTemp());
                stmt.setString(2, jogador.getNivelJogador());
                stmt.setString(3, jogador.getCaracteristica());
                stmt.setString(4, jogador.getMao());
                stmt.setString(5, jogador.getBackhand());
                stmt.execute();
                stmt.close();
            } catch (Exception e) {
                capturaException.ExceptionHandlerController(e);
            }
        } catch (SQLException e) {
            capturaException.ExceptionHandlerController(e);
            throw new RuntimeException(e);
        }
    }

    public List<JogadorDTO> seleciona(int sessionID) throws PropertyVetoException {

        try (Connection connection = ConnectionFactory.getConnection()) {
            List<JogadorDTO> results = new ArrayList<>();
            String sql = "SELECT id_jogador, nome_jogador, nivel_jogador, caracteristica, mao, backhand FROM dt_jogadores WHERE id_usuario = " + sessionID + " order by nome_jogador asc;";
            try (PreparedStatement stmt = connection.prepareStatement(sql);
                    ResultSet resultSet = stmt.executeQuery()) {

                while (resultSet.next()) {
                    results.add(populaConta(resultSet));
                }
                resultSet.close();
                stmt.close();
                connection.close();
            } catch (SQLException e) {
                capturaException.ExceptionHandlerController(e);
                throw new RuntimeException(e);
            }
            return results;

        } catch (SQLException e) {
            capturaException.ExceptionHandlerController(e);
            throw new RuntimeException(e);
        }
    }
}

erro

08-Dec-2017 11:22:14.829 SEVERE [http-nio-8084-exec-3] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [dispatcher] in context with path [/Head2Head] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: java.sql.SQLException: Connections could not be acquired from the underlying database!] with root cause
 java.net.UnknownHostException: aapt7ly16nddqg.cbdhasdqz2vq.sa-east-1.rpool.amazonaws.com
    at java.net.InetAddress.getAllByName0(InetAddress.java:1280)
    at java.net.InetAddress.getAllByName(InetAddress.java:1192)
    at java.net.InetAddress.getAllByName(InetAddress.java:1126)
    at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:188)
    at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:300)
    at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2189)
    at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2222)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2017)
    at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:779)
    at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
    at sun.reflect.GeneratedConstructorAccessor20.newInstance(Unknown Source)

após cerca de 36h sem dormir rsrsrs acredito que esteja ok agora ¬¬

fiz vários testes com varias contas e muitas requisições e o erro parou.

Fábio, poderia por favor dar um feedback? agradeceria muito.

public class ConnectionPool {

    private static final String DB_USERNAME = "******";
    private static final String DB_PASSWORD = "******";
    private static final String DB_URL = "jdbc:mysql://********************?autoReconnect=true&useSSL=false";
    private static final String DB_DRIVER_CLASS = "com.mysql.jdbc.Driver";

    private static ComboPooledDataSource dataSource;

    static {
        try {
            dataSource = new ComboPooledDataSource();
            dataSource.setDriverClass(DB_DRIVER_CLASS);

            dataSource.setJdbcUrl(DB_URL);
            dataSource.setUser(DB_USERNAME);
            dataSource.setPassword(DB_PASSWORD);

            dataSource.setMinPoolSize(100);
            dataSource.setMaxPoolSize(1000);
            dataSource.setAcquireIncrement(5);

        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
    }

    public static DataSource getDataSource() {
        return dataSource;
    }
}
public class JogadorDAO {

    ExceptionHandling capturaException = new ExceptionHandling();

    public void adiciona(JogadorDTO jogador, int sessionID) throws SQLException, PropertyVetoException, IOException {

        if ("".equals(jogador.getNomeJogadorTemp()) || "".equals(jogador.getNivelJogador()) || "".equals(jogador.getCaracteristica()) || "".equals(jogador.getMao()) || "".equals(jogador.getBackhand())) {
            throw new IllegalArgumentException("Existe algum dado nulo");
        }
        String sql = "INSERT INTO dt_jogadores (nome_jogador, nivel_jogador, caracteristica, mao, backhand, id_usuario)VALUES(?,?,?,?,?, " + sessionID + ")";
        try (Connection connection = ConnectionPool.getDataSource().getConnection();
                PreparedStatement stmt = connection.prepareStatement(sql);) {
            stmt.setString(1, jogador.getNomeJogadorTemp());
            stmt.setString(2, jogador.getNivelJogador());
            stmt.setString(3, jogador.getCaracteristica());
            stmt.setString(4, jogador.getMao());
            stmt.setString(5, jogador.getBackhand());
            stmt.execute();
            stmt.close();
            connection.close();
        } catch (Exception e) {
            capturaException.ExceptionHandlerController(e);
            throw new RuntimeException(e);
        }
    }
}
solução!

Oi Rodrigo,

boa!!

Aparentemente o pool está corretamente configurado .

Só ainda acho que você pode seguir a abordagem de fazer o seu DAO receber uma conexão em vez de abri-la para cada método dele.

Perceba que da maneira que implementou, se eu usasse dois métodos do DAO ele abriria duas vezes e fecharia duas vezes. Além disso, se o seu sistema for usar dois DAO's em uma lógica ele tb usaria ao menos duas conexão(abre->fecha, abre->fecha)

Conexão é um recurso caro, na verdade todo IO é, por isso evite isso.

Lá atrás eu comentei da solução de fazer o DAO receber uma conexão.

Abraços

opa! blz vou fazer desse jeito então, ainda assim MUITO OBRIGADO :)