Nginx(十八):DNS模块

Nginx(十八):DNS模块

一、请求阶段

  1. ngx_resolve_start
    (1)分配ctx结构体;
    (2)赋值DNS结束后的回调函数。
  2. ngx_resolve_name->ngx_resolve_name_locked
    • 如果该域名在resolver中已存在节点:
      a.如果该节点仍有效,则更新node超时时间,将resolver中的DNS解析结果赋值给ctx,调用ctx的回调;
      b.如果该节点已失效。若因DNS响应还未返回(rn->waiting),则将该cxt挂至rn->waiting;若因响应后失效,则重新发起DNS请求(即2的流程)。
    • 如果该域名在resolver中不存在节点:
      a.分配并初始化rn节点,加入resolver红黑树;
      b.建立DNS请求字符串(rn->query);
      c.发送DNS请求(ngx_resolver_send_query);
      d.使能ctx->event超时定时器,用于ctx超时;
      e.将rn加入resolver的resend_queue队列,用于DNS的超时重传。如果这是resend_queue中的首个元素,则需要使能r->event重传定时器。该定时器超时时,会遍历resolver的resend_queue,对所有需要重传的node进行判断。

二、DNS连接的响应触发

  1. ngx_resolver_udp_read->ngx_resolver_process_response
    DNS响应报文解析包头。
  2. ngx_resolver_process_a响应处理
    (1)根据域名查找rn节点;
    (2)解析响应中的结果,保存在rn中;
    (3)复制一份结果,用于赋值给ctx,此时DNS成功,遍历rn->waiting,并调用ctx->handler;
    (4)将rn从resend_queue队列中删除,加入name_expire_queue节点超时队列。

三、ctx回调

  1. 如果解析过程出现问题,ctx->state被赋值,则返回502 BAD GATEWAY;
  2. ngx_resolve_name_done
    (1)删除ctx->event超时定时器,因为DNS解析已经成功;
    (2)检查resolver的name_expire_queue队列,删除所有的超时节点;
    (3)如果resolver的name_resend_queue队列为空,说明所有的DNS请求都已经被响应,则删除r->event超时重传定时器。
  3. 进行后续的上游处理。

四、超时

  1. ctx的超时
    触发:ctx->event
    说明:ctx超时期间,若始终没有得到DNS模块的回调(无论成功或失败),则ctx超时,代表该HTTP会话失败,返回502 BAD GATEWAY。
  2. DNS重传队列的超时
    触发:r->event
    说明:该超时检查resolver中resend_queue所有节点,对rn->expire超时节点进行重传。若rn->waiting为空,可能ctx已经超时释放,即该域名已经没有HTTP回话等会解析结果,则对rn在红黑树中进行删除释放。
  3. 已响应rn节点超时
    触发:ctx回调,较特殊
    说明:对于已响应的rn节点,已不存在于name_resend_queue中,而是存在于name_expire_queue。若rn->expire超时期间,没有HTTP会话对该节点结果进行使用,则该节点超时,对rn在红黑树中进行删除释放。