V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
netssfy
V2EX  ›  Node.js

[坑] 由 DNS 造成的 ETIMEDOUT 错误

  •  2
     
  •   netssfy · 2017-05-18 20:19:59 +08:00 · 2237 次点击
    这是一个创建于 2771 天前的主题,其中的信息可能已经有所发展或是发生改变。
    这几天碰到一个小坑,花了点时间调研了下,希望对后人有帮助
    描述:
    设想你有一个应用,对外暴露 2 个接口
    http://www.my.com/api/77
    http://www.my.com/api/88
    他们内部各自会依赖第三方的 http 接口
    接口 88 依赖: http://www.88.com/api,http 请求超时设置为 5S
    接口 77 依赖: http://www.77.com/api,http 请求超时设置为 5S
    假设你自己的应用所在的机器设置了一个 DNS SERVER,地址为 66.66.66.66,这台 DNS 更像一个代理,
    他对 www.88.com 的解析需要依赖上游的 88.88.88.88 这台 DNS 服务
    他对 www.77.com 的解析需要依赖上游的 77.77.77.77 这台 DNS 服务

    如果这时候 77.77.77.77 这台 DNS 挂了会发生什么?情况如下

    1. 在 66.66.66.66 这台代理 DNS 代理中,对 www.77.com,www.88.com 的记录缓存都还没过期时一切正常
    2. 当 66 对 www.77.com 的记录过期了,那么所有外部对你的 www.my.com/api/77 的访问都将失败,因为你内部无法访问 www.77.com
    3. 坑的地方来了, 当 66 对 www.88.com 的记录过期了,外部访问你的 www.my.com/api/88 会发生什么?答案是都有可能,既可能正常,也可能失败,原因如下:

    正常的原因就不赘述了,因为 88.88.88.88 服务器依然坚挺,即使记录过期了 66.66.66.66 还是可以问 88.88.88.88 拿到 www.88.com 的 IP
    那为什么会错误呢!因为 nodejs 的 runtime 默认使用了 4 个 worker 线程去处理 dns 解析请求。如果这 4 个线程都在处理对 77 的解析,那么这些线程都会 pending 在那边,直到 DNS 解析失败发生。(感受了一下好像是 10S,应该是 OS 的一个设置值)
    那在 pending 期间所有的对 www.88.com 的请求也都会被 pending 起来(因为 88 此时也需要解析,他在 66 中的记录已经过期了)。又因为 http 请求超时设置的是 5S,最终就都会变成 ETIMEDOUT 或者 ESOCKETTIMEDOUT

    此外,该问题还可能引发 v8 out of memory 的问题,原本一个请求花费 50MS,那么他占用的内存在 50MS 后就可以被 GC,但是当这个时间变成 5S 后,他占用的内存也要在 5S 后才能被 GC。如果 5S 内量很大,就有可能造成 OOM
    4 条回复    2017-05-19 15:48:37 +08:00
    seasstyle
        1
    seasstyle  
       2017-05-19 10:02:09 +08:00
    我可以说我不明白但觉得很厉害吗?
    最近在玩本地 DNS 帆樯
    hilyjiang
        2
    hilyjiang  
       2017-05-19 10:46:48 +08:00
    重点是,“ nodejs 的 runtime 默认使用了 4 个 worker 线程去处理 dns 解析请求”,为什么只有 4 个。
    liaohongxing
        3
    liaohongxing  
       2017-05-19 13:33:35 +08:00
    一般无脑装了个 nscd 缓存 DNS,其他倒是没怎么关注
    netssfy
        4
    netssfy  
    OP
       2017-05-19 15:48:37 +08:00
    @hilyjiang nodejs 用的线程池是由 libuv 库提供的,libuv 默认设置的就是 4,这个配置可修改.
    通过环境变量 UV_THREADPOOL_SIZE 来修改,最大 128
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1017 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 20:49 · PVG 04:49 · LAX 12:49 · JFK 15:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.