Oracle JDBC неустойчивая проблема соединения

56

У меня очень странная проблема Это очень простое подключение JDBC к базе данных Oracle

OS: Ubuntu
Java Version:  1.5.0_16-b02
               1.6.0_17-b04
Database: Oracle 11g Release 11.1.0.6.0

Когда я использую файл jar OJDBC14.jar он подключается к базе данных каждый раз Когда я использую файл jar OJDBC5.jar он соединяется несколько раз, а иногда он выдает ошибку (показано ниже) Если я перекомпиляю с Java 6 и OJDBC6.jar Я получаю те же результаты, что и OJDBC5.jar

Мне нужны конкретные функции в JODB5.jar, которые недоступны в OJDBC14.jar

Любые идеи

Ошибка

> Connecting to oracle
    java.sql.SQLException: Io exception: Connection reset
    at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:74)
    at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:110)
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:171)
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:227)
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:494)
    at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:411)
    at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:490)
    at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:202)
    at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:33)
    at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:474)
    at java.sql.DriverManager.getConnection(DriverManager.java:525)
    at java.sql.DriverManager.getConnection(DriverManager.java:171)
    at TestConnect.main(TestConnect.java:13)

код

Ниже приведен код, который я использую

import java.io.*;
import java.sql.*;
public class TestConnect {
    public static void main(String[] args) {
        try {
            System.out.println("Connecting to oracle"); 
            Connection con=null;
            Class.forName("oracle.jdbc.driver.OracleDriver");
            con=DriverManager.getConnection(
               "jdbc:oracle:thin:@172.16.48.100:1535:sample",
               "JOHN",
               "90009000");
            System.out.println("Connected to oracle"); 
            con.close();
            System.out.println("Goodbye");
        } catch(Exception e) { e.printStackTrace(); }
    }
}
Теги:
jdbc

12 ответов

89

В некоторых форумах OTN есть решение, предлагаемое этой проблемой (https://kr.forums.oracle.com/forums/thread.jspa?messageID=3699989). Но основная причина проблемы не объясняется. Ниже приведена моя попытка объяснить основную причину проблемы.

Драйверы JDBC Oracle взаимодействуют с сервером Oracle безопасным способом. Драйверы используют класс java.security.SecureRandom для сбора энтропии для обеспечения связи. Этот класс опирается на поддержку собственной платформы для сбора энтропии.

Энтропия - это случайность, собранная/созданная операционной системой или приложением для использования в криптографии или других целях, требующих случайных данных. Эта случайность часто собирается из аппаратных источников, будь то аппаратные шумы, аудиоданные, движения мыши или специально создаваемые генераторы случайности. Ядро собирает энтропию и сохраняет ее в виде энтропийного пула и делает случайные символьные данные доступными для процессов или приложений операционной системы через специальные файлы /dev/random и /dev/urandom.

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

В отличие от вышеизложенного, чтение из /dev/urandom не блокируется. Чтение из /dev/urandom также истощает пул энтропии, но при недостаточной энтропии он не блокирует, а повторно использует биты из частично прочитанных случайных данных. Говорят, что это восприимчиво к криптоаналитическим атакам. Это теоретическая возможность, и поэтому не рекомендуется читать /dev/urandom для сбора случайности в криптографических операциях.

Класс java.security.SecureRandom, по умолчанию, считывает из файла /dev/random и, следовательно, иногда блокирует случайный период времени. Теперь, если операция чтения не вернется в течение необходимого количества времени, сервер Oracle время от времени клиент (в этом случае драйверы jdbc) и отключает связь, закрывая сокет с его конца. Клиент, когда пытается возобновить связь после возврата из блокирующего вызова, встречает исключение IO. Эта проблема может возникать случайным образом на любой платформе, особенно, когда энтропия собирается из аппаратных шумов.

Как было предложено на форуме OTN, решение этой проблемы - переопределить поведение по умолчанию класса java.security.SecureRandom для использования неблокирующего чтения из /dev/urandom вместо блокировки, считанной с /dev/random, Это можно сделать, добавив в JVM следующее системное свойство -Djava.security.egd = file:///dev/urandom. Хотя это хорошее решение для приложений, таких как JDBC-драйверы, не рекомендуется для приложений, которые выполняют основные криптографические операции, такие как создание криптографических ключей.

Другими решениями могут быть использование различных случайных реализаций сеялок, доступных для платформы, которые не полагаются на аппаратные шумы для сбора энтропии. При этом вам может потребоваться переопределить поведение по умолчанию java.security.SecureRandom.

Увеличение времени ожидания сокета на стороне сервера Oracle также может быть решением, но побочные эффекты следует оценивать с точки зрения сервера, прежде чем пытаться это сделать.

  • 0
    О той же проблеме / решении сообщается в документе Oracle для настройки swingbench, генератора нагрузки для баз данных Oracle на странице 7: oracle.com/technetwork/database/database-appliance/…
  • 0
    @ miracle173 Спасибо, что поделились!
Показать ещё 5 комментариев
15

Я столкнулся с одной и той же проблемой. В Windows Vista я не смог воспроизвести проблему, но на Ubuntu я постоянно воспроизводил "соединение reset" - ошибка.

Я нашел http://forums.oracle.com/forums/thread.jspa?threadID=941911&tstart=0&messageID=3793101

По словам пользователя на этом форуме:

Я открыл билет с Oracle, и это то, что они мне сказали.

java.security.SecureRandom - стандартный API, предоставляемый солнцем. среди различные методы, предлагаемые этим классом, void nextBytes (byte []) - это один. Этот метод используется для генерации случайных байтов. Oracle 11g JDBC драйверы используют этот API для генерации случайного числа во время входа в систему. пользователей с использованием Linux встречаются SQLException ( "исключение Io: Соединение reset" ).

Проблема состоит в двухкратном

  • JVM пытается перечислить все файлы в каталоге /tmp (или альтернативный каталог tmp, заданный -Djava.io.tmpdir), когда SecureRandom.nextBytes(byte []) вызывается. Если количество файлов велико, метод принимает длинный время реагирования и, следовательно, на время ожидания сервера

  • Метод void nextBytes (byte []) использует /dev/random в Linux и на некоторых машинах, которым не хватает оборудования, генерирующего случайное число, операция замедляется до степени полного процесса входа в систему на остановке. В конечном счете пользователь сталкивается с SQLException ( "Io исключение: соединение reset" )

Обновление пользователей до 11g может столкнуться с этой проблемой, если базовая ОС это Linux, работающий на неисправном оборудовании.

Причина Причина этого еще не определена точно. Это могло бы либо проблема в вашем оборудовании, либо тот факт, что по какой-либо причине программное обеспечение не может читать из dev/random

Решение. Измените настройку для своего приложения, чтобы добавить следующую параметр для команды java:

-Djava.security.egd = файл:/DEV/../DEV/urandom

Мы внесли это изменение в наш файл java.security, и он избавился от ошибка.

который решил мою проблему.

4

Сообщение об ошибке "соединение reset" обычно означает, что другая сторона прервала соединение во время попытки создать соединение (рукопожатие). Это имеет множество причин. Ошибка в драйвере JDBC, тайм-аут на стороне БД, перезагрузка базы данных, наличие БД из доступных подключений, плохое качество сети, плохой virusscanner/firewall/proxy и т.д.

Как это происходит с периодичностью, ошибка в драйвере JDBC может быть менее или более исключена. Остались по-прежнему возможные причины. Я предлагаю начать с поиска в журналах сервера БД.

1

Другая вещь, которая вызывала у меня эту проблему, была неправильной настройкой HOSTNAME. Моя попытка подключения была изменена:

"main" prio=10 tid=0x00007f7cc8009000 nid=0x2f3a runnable [0x00007f7cce69e000]
   java.lang.Thread.State: RUNNABLE
        at java.net.Inet4AddressImpl.getLocalHostName(Native Method)
        at java.net.InetAddress.getLocalHost(InetAddress.java:1444)
        at sun.security.provider.SeedGenerator$1.run(SeedGenerator.java:176)
        at sun.security.provider.SeedGenerator$1.run(SeedGenerator.java:162)
        at java.security.AccessController.doPrivileged(Native Method)

Поэтому убедитесь, что у вас есть запись для вашего имени хоста в /etc/hosts/.

Если вы выполните команду hostname следующим образом:

$ hostname
my.server.com

Вам нужна строка в /etc/hosts:

127.0.0.1 my my.server.com
1

Просто уточнить - по крайней мере, от того, что мы нашли на нашей стороне! Это проблема с настройкой рандомизатора для Linux в дистрибутиве JDK - и мы нашли его в Java6, не уверен в Java7. Синтаксис для linux для рандомизатора - файл:///dev/urandom, но запись в файле (вероятно, оставлена ​​/скопирована из Windows) в виде файла:/dev/urandom. Таким образом, Java, вероятно, падает на значение по умолчанию, которое является /dev/random. И что не работает на безголовой машине!!!

1

Я нашел эту ссылку для той же проблемы с 64-битной системой, драйвером jdbc 11g и соединением reset: http://forums.oracle.com/forums/thread.jspa?messageID=3793101

1

Трудно сказать, но если бы я проверил фактическую версию драйвера JDBC. Удостоверьтесь, что это 11.1.0.6.

Oracle не включает версию базы данных в имени файла. Таким образом, драйвер для 11.2 - это то же имя, что и драйвер для 11.1 - ojdbc5.jar. Я извлечу файл драйвера jar и найду файл MANIFEST.MF, это будет содержать некоторую информацию о версии. Убедитесь, что версия драйвера JDBC соответствует версии вашей базы данных. Я подозреваю, что это может быть проблема с версией, так как нет файла jar с именем ojdbc14.jar в Oracle 11.1.0.6 скачать.

Если версия соответствует - у меня нет идей:)

0

В соответствии с ошибкой https://bugs.openjdk.java.net/browse/JDK-6202721

Java не будет содержать -Djava.security.egd = файл:/dev/urandom

Он должен быть -Djava.security.egd = file:/dev/./urandom

0

-Djava.security.egd = файл:/dev/./Уранд должен быть прав! not -Djava.security.egd = файл:/dev/../dev/urandom или -Djava.security.egd = файл:///dev/urandom

  • 3
    Было бы здорово, если бы вы могли дать какое-то объяснение, что это делает и почему это решение.
  • 0
    В веб-приложении Java можно установить свойство как «System.setProperty (« java.security.egd »,« file: / dev /./ urandom »)»?
0

Отключение SQL Net Баннеры сохранены.

0

Обратите внимание, что предлагаемое решение по использованию /dev/urandom действительно работало впервые для меня, но не работало всегда после этого.

DBA на моей фирме переключился на "чистые баннеры SQL *" и зафиксировал ее для меня с или без нее.

Я не знаю, что такое "сетевые баннеры SQL", но я надеюсь, что если вы будете иметь (а) DBA, он (вы) знал бы, что делать.

-1

OracleXETNSListener - эта служба должна быть запущена, если она отключена.

run -> services.msc 

и обратите внимание на эти услуги

Ещё вопросы

Сообщество Overcoder
Наверх
Меню