спорадические проблемы с разрешением DNS в Java-клиенте http - PullRequest
0 голосов
/ 05 февраля 2019

У нас есть пакетное задание, которое запускается каждый день на экземпляре EC2 в AWS.Экземпляр EC2 существует в VPC.Пакетное задание использует Java для выполнения серии вызовов REST API на общедоступном сервере.Большинство дней пакетная работа выполняется без проблем.Однако в некоторые дни что-то не работает в разрешении DNS.Задание будет успешно выполнено, а затем внезапно произойдет сбой разрешения DNS, и оставшийся API вызовет ошибку, за исключением следующего:

java.net.UnknownHostException: some.publicserver.com: Name or service not known
  at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method) ~[na:1.8.0_191]
  at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:929) ~[na:1.8.0_191]
  at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1324) ~[na:1.8.0_191]
  at java.net.InetAddress.getAllByName0(InetAddress.java:1277) ~[na:1.8.0_191]
  at java.net.InetAddress.getAllByName(InetAddress.java:1193) ~[na:1.8.0_191]
  at java.net.InetAddress.getAllByName(InetAddress.java:1127) ~[na:1.8.0_191]
  at org.apache.http.impl.conn.SystemDefaultDnsResolver.resolve(SystemDefaultDnsResolver.java:44) ~[batchjob.jar:na]
  at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:102) ~[batchjob.jar:na]
  at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:319) ~[batchjob.jar:na]
  at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:363) ~[batchjob.jar:na]
  at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219) ~[batchjob.jar:na]
  at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195) ~[batchjob.jar:na]
  at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86) ~[batchjob.jar:na]
  at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108) ~[batchjob.jar:na]
  at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) ~[batchjob.jar:na]
  at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) ~[batchjob.jar:na]
  at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106) ~[batchjob.jar:na]
  ...

В некоторые дни каждый вызов API завершится с ошибкой, иногда тамбудет строка успешных звонков, а затем все начнет сбой.В дни, когда не удается выполнить задание, я могу одновременно подключиться к серверу и убедиться, что DNS работает.Например, если я использую следующую команду

nslookup some.publicserver.com

Возвращает успешный ответ.В то же время пакетное задание будет извергать кучу UnknownHostExceptions.

Я озадачен тем, где искать источник проблемы.Кто-нибудь испытывал что-то подобное?

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Для чего это стоит, в моей конкретной ситуации вот что я смог выяснить.Надеюсь, это поможет кому-то еще в будущем.

Авторитетные DNS-серверы для цели в моем примере (some.publicserver.com) возвращают SERVFAIL для некоторых запросов.Вероятно, это является проблемой нагрузки, так как это происходит спорадически в течение дня.С моей настройкой AWS я использую DNS-серверы по умолчанию для моего VPC, которые предоставляются AWS.Эти серверы, по-видимому, не делают никакого кэширования.Я узнал, что Java выполняет некоторое кэширование для разрешений DNS через InetAddress, но по умолчанию это короткое окно (в большинстве реализаций, на мой взгляд, 30 секунд).

Итак, в конце концов, настоящая причина проблемыавторитетные DNS-серверы для some.publicserver.com не являются полностью надежными.Поскольку я не контролирую эти серверы, я думаю, что лучшим решением является использование кэширования DNS.Вариант № 1 - использовать локальное DNS-кэширование на моем экземпляре EC2 Ubuntu (что-то вроде dnsmasq).Вариант № 2 заключается в том, чтобы увеличить продолжительность кэширования, используемую Java, выполнив что-то вроде этого:

java.security.Security.setProperty("networkaddress.cache.ttl" , "900");

Я выбрал вариант № 2, так как он требовал меньших усилий и сводил к минимуму возможные побочные эффекты.Так что, это решило проблему для меня.

0 голосов
/ 05 февраля 2019

Я думаю, что это не проблема Java, а проблема разрешения DNS с экземпляром EC2.Java будет эффективно выполнять действия по разрешению DNS, сначала проверяя файл hosts, а затем вызывая функции, связанные с DNS соответствующей ОС.

Учитывая это, а также тот факт, что базовый экземпляр EC2 эффективно выполняетВ дистрибутиве Linux эти шаги приведут к вызову функции gethostbyname2 ОС.Это, в свою очередь, выполнит всю скрытую магию для разрешения рассматриваемого имени.

Теперь две вещи очень важны для устранения проблемы.Во-первых, часто ли меняется IP-адрес вызываемого вами сервера.Во-вторых, используемая вами программа nslookup будет запрашивать DNS-сервер напрямую.Это означает, что вполне могут быть расхождения между тем, что Java пытается сделать для разрешения имени домена, и тем, что делает программа.Кроме того, это также может означать, что ОС могла кэшировать IP-адрес, который не соответствует последнему адресу сервера.Таким образом, я бы предложил проверить IP-адрес имени хоста с помощью какой-либо другой утилиты (например, ping).

Моими лучшими советами по устранению неполадок будут следующие:

  • Добавление какой-либо трассировки журнала при попытке выполнить разрешение имени хоста и сравнение его с nslookupРазрешенное значение.

  • Проверка правильности настройки DNS в EC2 (какой DNS-сервер вы используете и т. д.).

  • Добавлениезапись в файле hosts, сопоставляющая имя домена с IP-адресом (при условии, что последний не изменяется).

Надеюсь, что приведенная выше справка поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...