【问题标题】:What can cause the JVM to fail to resolve DNS under load?什么会导致 JVM 在负载下无法解析 DNS?
【发布时间】:2012-01-03 01:03:56
【问题描述】:

我正在调查我们的服务存在的问题,该问题无法解析负载下的 s3 存储桶名称。

我强调的是单个 c1.medium ec2 实例:

root@ip-10-243-126-111:/mnt/log# uname -a
Linux ip-10-243-126-111 2.6.35-30-virtual #56-Ubuntu SMP Mon Jul 11 23:41:40 UTC 2011 i686 GNU/Linux
root@ip-10-243-126-111:/mnt/log# cat /etc/issue
Ubuntu 10.10 \n \l
root@ip-10-243-126-111:/mnt/log# free
             total       used       free     shared    buffers     cached
Mem:       1746008    1681752      64256          0      29600    1582508
-/+ buffers/cache:      69644    1676364
Swap:       917500         32     917468

应用程序正在使用-server, jvm build 1.6.0_23-b05, 32bit 运行

我看到的行为是网络通信开始“表现得很有趣”,有时我们的 mongo 连接驱动程序会发生套接字超时,如下所示:

Caused by: java.net.SocketTimeoutException: Read timed out
        at java.net.SocketInputStream.socketRead0(Native Method) ~[na:1.6.0_23]
        at java.net.SocketInputStream.read(SocketInputStream.java:129) ~[na:1.6.0_23]
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:218) ~[na:1.6.0_23]
        at java.io.BufferedInputStream.read1(BufferedInputStream.java:258) ~[na:1.6.0_23]
        at java.io.BufferedInputStream.read(BufferedInputStream.java:317) ~[na:1.6.0_23]
        at org.bson.io.Bits.readFully(Bits.java:35) ~[mongo-java-driver-2.5.3.jar:na]
        at org.bson.io.Bits.readFully(Bits.java:28) ~[mongo-java-driver-2.5.3.jar:na]
        at com.mongodb.Response.<init>(Response.java:35) ~[mongo-java-driver-2.5.3.jar:na]
        at com.mongodb.DBPort.go(DBPort.java:110) ~[mongo-java-driver-2.5.3.jar:na]
        at com.mongodb.DBPort.go(DBPort.java:75) ~[mongo-java-driver-2.5.3.jar:na]
        at com.mongodb.DBPort.call(DBPort.java:65) ~[mongo-java-driver-2.5.3.jar:na]
        at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:201) ~[mongo-java-driver-2.5.3.jar:na]
        ... 43 common frames omitted

有时会发生以下情况

Caused by: java.net.UnknownHostException: bucket-system.s3.amazonaws.com
        at java.net.InetAddress.getAllByName0(InetAddress.java:1158) ~[na:1.6.0_23]
        at java.net.InetAddress.getAllByName(InetAddress.java:1084) ~[na:1.6.0_23]
        at java.net.InetAddress.getAllByName(InetAddress.java:1020) ~[na:1.6.0_23]
        at org.apache.http.impl.conn.DefaultClientConnectionOperator.resolveHostname(DefaultClientConnectionOperator.java:242) ~[httpclient-4.1.jar:4.1]
        at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:130) ~[httpclient-4.1.jar:4.1]
        at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149) ~[httpclient-4.1.jar:4.1]
        at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:121) ~[httpclient-4.1.jar:4.1]
        at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:562) ~[httpclient-4.1.jar:4.1]
        at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415) ~[httpclient-4.1.jar:4.1]
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820) ~[httpclient-4.1.jar:4.1]
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754) ~[httpclient-4.1.jar:4.1]
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732) ~[httpclient-4.1.jar:4.1]
        at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:240) ~[aws-java-sdk-1.2.5.jar:na]
        ... 48 common frames omitted

这是可重现的,但不一致。一旦机器上开始加载(50 个并发 http 请求),机器就会在正确响应周期之间切换约 5 分钟,然后所有请求失败约 10 秒,然后是另一个正确响应周期。

什么会导致这种行为?是否有任何 ulimit 或其他系统设置我可以尝试调整以改进这一点?还有什么线索可以搜索吗?

我怀疑的另一个选项是亚马逊(us-east-1 区域)的基础设施,我怀疑那里的路由器对服务启用了某种 DoS 预防策略,因为请求几乎立即从 0 跳转到 50 . 一段时间后,它稳定在稳定的 50 并发率上,此时硬件会适应新的流量。牵强?我在任何地方都没有发现任何提到这种类型的模式。

【问题讨论】:

  • 您能检查一下您的 java.security 策略文件中的值 networkaddress.cache.ttl 吗?默认设置是永久缓存名称服务查找的结果,但如果该值为 300(=5 分钟),那么这可能是对您的周期的解释。

标签: java linux load amazon-ec2 linux-kernel


【解决方案1】:

您只是用完了文件描述符吗?第一个堆栈跟踪看起来与 DNS 无关。

ulimit -n 说什么? 如果你给你的进程一个(很多)更高的打开文件描述符限制,问题会消失吗?

(打开/半关闭套接字消耗文件描述符)。

【讨论】:

  • 谢谢,这是我的 UnknownHostExceptions 的原因。增加打开的文件会限制固定的东西。
【解决方案2】:

看起来您只是尝试对亚马逊 DNS 服务器进行 DoS。 缓存您尝试访问的主机的 IP 并定期更新缓存。这也将提高应用程序的整体性能

更新: 从跟踪中可以看出 DNS 主机只是没有响应您的请求。如果达到 ulimit,您将面临另一个异常(例如无法创建套接字)。

【讨论】:

  • 感谢 Funtik,但正如您所见,其他服务器(如我们的 mongo 集群)或其他可扩展的东西(如 CloudFront)也会发生这种情况。缓存不是重点,因为发送实际请求的是 aws-java-sdk S3 客户端。
  • 与亚马逊合作的不多,但我仍然会尝试将其缓存或将其隔离在单独的服务中,这不会为每个客户端生成新的 DNS 请求。 Mongo驱动程序是否与aws java同时崩溃?
  • @Maxim Veksler:我在生产环境中遇到了类似的问题。您是否能够找到问题的根本原因和解决方案。你能分享一下吗?谢谢,Ashish
  • @user1270392 我不再受雇于相关职位,但我相信我们最终使用 Guava 过期缓存将 IP 地址存储了几毫秒。这缓解了所有相关的 DNS 解析问题。
  • 非常感谢 Maxim...如果我理解正确,这意味着你们可能无法找到根本原因。我的意思是它与 DNS 服务器本身有关,还是在代码/配置中没有最佳地完成某些事情?使用番石榴添加缓存听起来不错,但这是否意味着我们在代码中硬编码了 IP 地址?我尝试过的一件事是在 /etc/hosts 中添加主机名-IP 并解决了这个问题。但是对我来说这也不是很好,因为 IP 地址可能会改变。
猜你喜欢
  • 1970-01-01
  • 2013-03-14
  • 1970-01-01
  • 1970-01-01
  • 2010-09-18
  • 2013-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多