Acabei de acertar este problema recentemente ao construir o updown.io e o investiguei um pouco (obrigado @Dan pelo comando strace
). Aqui está o que eu encontrei:
Condição
No meu caso, o curl às vezes demorava 65ms para resolver e às vezes < 5ms. Parecia demorar 65 ms após um curto período de inactividade (alguns minutos) e < 5 ms após repetidas chamadas. Definitivamente soa como um problema de cache e TTL, obviamente. Mas meu disco tem um 86400s TTL (1 dia) e já estava em cache no meu resolvedor local e dig sempre demorou 1ms.
Medidas
Então, tentei executar o curl com strace
para ver onde o tempo foi gasto, e foi isso que encontrei (removi alguns detalhes para esclarecer):
05:57:52.303 connect(3) = 0
05:57:52.303 sendmmsg(3, ["1$ dig AAAA jarthon-architecte.com
;; AUTHORITY SECTION:
jarthon-architecte.com. 180 IN SOA ns0.dnsmadeeasy.com. dns.dnsmadeeasy.com. 2008010120 43200 3600 1209600 180
;; Query time: 86 msec
;; SERVER: ::1#53(::1)
05:57:52.303 connect(3) = 0
05:57:52.303 sendmmsg(3, ["1$ dig AAAA jarthon-architecte.com
;; AUTHORITY SECTION:
jarthon-architecte.com. 180 IN SOA ns0.dnsmadeeasy.com. dns.dnsmadeeasy.com. 2008010120 43200 3600 1209600 180
;; Query time: 86 msec
;; SERVER: ::1#53(::1)
%pre%%pre%%pre%%pre%%pre%%pre%%pre%jarthon-architecte"..., "53%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%jarthon-architecte"...] , 2) = 2
05:57:52.303 poll([{fd=3, events=POLLIN}], 1, 5000) = 1
05:57:52.303 ioctl(3, FIONREAD, [56]) = 0
05:57:52.303 recvfrom(3, "110%pre%%pre%%pre%%pre%%pre%%pre%jarthon-architecte"...) = 56
05:57:52.304 poll([{fd=3, events=POLLIN}], 1, 4999) = 1
05:57:52.373 ioctl(3, FIONREAD, [96]) = 0
05:57:52.373 recvfrom(3, "5310%pre%%pre%%pre%%pre%%pre%%pre%jarthon-architecte"...) = 96
05:57:52.373 close(3) = 0
%pre%%pre%%pre%%pre%%pre%%pre%jarthon-architecte"..., "53%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%jarthon-architecte"...] , 2) = 2
05:57:52.303 poll([{fd=3, events=POLLIN}], 1, 5000) = 1
05:57:52.303 ioctl(3, FIONREAD, [56]) = 0
05:57:52.303 recvfrom(3, "110%pre%%pre%%pre%%pre%%pre%%pre%jarthon-architecte"...) = 56
05:57:52.304 poll([{fd=3, events=POLLIN}], 1, 4999) = 1
05:57:52.373 ioctl(3, FIONREAD, [96]) = 0
05:57:52.373 recvfrom(3, "5310%pre%%pre%%pre%%pre%%pre%%pre%jarthon-architecte"...) = 96
05:57:52.373 close(3) = 0
Esta é parte da resolução de DNS, o que podemos ver claramente aqui é que 2 mensagens são enviadas, uma resposta é recebida rapidamente, e outra é recebida após um atraso de 69ms. Eu pensei que esta segunda resposta é provavelmente a consulta IPv6 (AAAA), então eu tentei em dig:
%pre%Ok, não há resposta óbvia, mas esse registro SOA tem um TTL de 180s, isso parece muito com o tempo que levou para passar de 5ms para 65ms em meus testes de curvas.
Explicação
O registro SOA é retornado pelo seu servidor DNS quando não há resposta e contém, entre outras coisas, o TTL negativo (último número na linha que você pode ver 180) que é o momento em que qualquer resolvedor pode armazenar respostas negativas (ausência de registro). Então, isso significa que, quando você consulta o registro AAAA, você precisa pressionar o servidor DNS pelo menos a cada 3 minutos apenas para ter certeza de que ainda não existe.
Corrigir
-
Adicione um IPv6 ☺
-
Se você gerencia o DNS, a solução mais fácil é aumentar esse valor. No meu caso, estou usando DNSMadeEasy, posso criar um registro SOA personalizado com um valor TTL mais alto e atribuí-lo aos meus domínios: link . Isso fará com que o curl seja resolvido mais rapidamente na maior parte do tempo, retornando ao nível de desempenho que temos em nosso registro A em cache.
-
Se você é quem faz os cachos, mas não gerencia o DNS, provavelmente há maneiras de otimizar isso no nível do resolvedor de DNS, atendendo a respostas negativas obsoletas ao buscar os valores reais ou coisas assim, mas eu não olhei para isso ainda.
-
Se você não se importa com o IPv6, também pode desativá-lo usando o sinalizador de linha de comando
curl
-4