mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-03-02 17:41:47 +00:00
MEDIUM: dns: implement synchronous send
In dns_send_query(), there's no point in first waking up the FD, to get called back by the poller to send the request and sleep. Instead let's simply send the request as soon as it's known and only subscribe to the poller when the socket buffers are full and it's required to poll (i.e. almost never). This significantly reduces the number of calls to the poller. A large config sees the number of epoll_ctl() calls reduced from 577 to 7 over 10 seconds, the number of recvfrom() from 1533 to 582 and the number of sendto() from 369 to 162. It also has the extra benefit of building each requests only once per resolution and sending it to multiple resolvers instead of rebuilding it for each and every resolver. This will reduce the risk of seeing situations similar to bug #416 in the future.
This commit is contained in:
parent
e5891ca6c1
commit
0eae6323bf
47
src/dns.c
47
src/dns.c
@ -272,22 +272,49 @@ static int dns_send_query(struct dns_resolution *resolution)
|
||||
{
|
||||
struct dns_resolvers *resolvers = resolution->resolvers;
|
||||
struct dns_nameserver *ns;
|
||||
int len;
|
||||
|
||||
/* Update resolution */
|
||||
resolution->nb_queries = 0;
|
||||
resolution->nb_responses = 0;
|
||||
resolution->last_query = now_ms;
|
||||
|
||||
len = dns_build_query(resolution->query_id, resolution->query_type,
|
||||
resolvers->accepted_payload_size,
|
||||
resolution->hostname_dn, resolution->hostname_dn_len,
|
||||
trash.area, trash.size);
|
||||
|
||||
list_for_each_entry(ns, &resolvers->nameservers, list) {
|
||||
int fd = ns->dgram->t.sock.fd;
|
||||
int ret;
|
||||
|
||||
if (fd == -1) {
|
||||
if (dns_connect_namesaver(ns) == -1)
|
||||
continue;
|
||||
fd = ns->dgram->t.sock.fd;
|
||||
resolvers->nb_nameservers++;
|
||||
}
|
||||
fd_want_send(fd);
|
||||
}
|
||||
|
||||
/* Update resolution */
|
||||
resolution->nb_queries = 0;
|
||||
resolution->nb_responses = 0;
|
||||
resolution->last_query = now_ms;
|
||||
if (len < 0)
|
||||
goto snd_error;
|
||||
|
||||
ret = send(fd, trash.area, len, 0);
|
||||
if (ret == len) {
|
||||
ns->counters.sent++;
|
||||
resolution->nb_queries++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret == -1 && errno == EAGAIN) {
|
||||
/* retry once the socket is ready */
|
||||
fd_cant_send(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
snd_error:
|
||||
ns->counters.snd_error++;
|
||||
resolution->nb_queries++;
|
||||
}
|
||||
|
||||
/* Push the resolution at the end of the active list */
|
||||
LIST_DEL(&resolution->list);
|
||||
@ -1751,8 +1778,14 @@ static void dns_resolve_send(struct dgram_conn *dgram)
|
||||
goto snd_error;
|
||||
|
||||
ret = send(fd, trash.area, len, 0);
|
||||
if (ret != len)
|
||||
if (ret != len) {
|
||||
if (ret == -1 && errno == EAGAIN) {
|
||||
/* retry once the socket is ready */
|
||||
fd_cant_send(fd);
|
||||
continue;
|
||||
}
|
||||
goto snd_error;
|
||||
}
|
||||
|
||||
ns->counters.sent++;
|
||||
res->nb_queries++;
|
||||
|
Loading…
Reference in New Issue
Block a user