nghttpx: Periodically remove expired DNS cache entries
This commit is contained in:
parent
fd403a85c8
commit
c487cd888f
|
@ -28,9 +28,21 @@
|
||||||
|
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
|
|
||||||
DNSTracker::DNSTracker(struct ev_loop *loop) : loop_(loop) {}
|
namespace {
|
||||||
|
void gccb(struct ev_loop *loop, ev_timer *w, int revents) {
|
||||||
|
auto dns_tracker = static_cast<DNSTracker *>(w->data);
|
||||||
|
dns_tracker->gc();
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
DNSTracker::DNSTracker(struct ev_loop *loop) : loop_(loop) {
|
||||||
|
ev_timer_init(&gc_timer_, gccb, 0., 12_h);
|
||||||
|
gc_timer_.data = this;
|
||||||
|
}
|
||||||
|
|
||||||
DNSTracker::~DNSTracker() {
|
DNSTracker::~DNSTracker() {
|
||||||
|
ev_timer_stop(loop_, &gc_timer_);
|
||||||
|
|
||||||
for (auto &p : ents_) {
|
for (auto &p : ents_) {
|
||||||
auto &qlist = p.second.qlist;
|
auto &qlist = p.second.qlist;
|
||||||
while (!qlist.empty()) {
|
while (!qlist.empty()) {
|
||||||
|
@ -94,6 +106,8 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) {
|
||||||
ents_.emplace(host, make_entry(nullptr, std::move(host_copy),
|
ents_.emplace(host, make_entry(nullptr, std::move(host_copy),
|
||||||
DNS_STATUS_ERROR, nullptr));
|
DNS_STATUS_ERROR, nullptr));
|
||||||
|
|
||||||
|
start_gc_timer();
|
||||||
|
|
||||||
return DNS_STATUS_ERROR;
|
return DNS_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +121,8 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) {
|
||||||
ents_.emplace(host, make_entry(nullptr, std::move(host_copy),
|
ents_.emplace(host, make_entry(nullptr, std::move(host_copy),
|
||||||
DNS_STATUS_ERROR, nullptr));
|
DNS_STATUS_ERROR, nullptr));
|
||||||
|
|
||||||
|
start_gc_timer();
|
||||||
|
|
||||||
return DNS_STATUS_ERROR;
|
return DNS_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
case DNS_STATUS_OK: {
|
case DNS_STATUS_OK: {
|
||||||
|
@ -118,6 +134,8 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) {
|
||||||
ents_.emplace(host, make_entry(nullptr, std::move(host_copy),
|
ents_.emplace(host, make_entry(nullptr, std::move(host_copy),
|
||||||
DNS_STATUS_OK, result));
|
DNS_STATUS_OK, result));
|
||||||
|
|
||||||
|
start_gc_timer();
|
||||||
|
|
||||||
return DNS_STATUS_OK;
|
return DNS_STATUS_OK;
|
||||||
}
|
}
|
||||||
case DNS_STATUS_RUNNING: {
|
case DNS_STATUS_RUNNING: {
|
||||||
|
@ -127,6 +145,8 @@ int DNSTracker::resolve(Address *result, DNSQuery *dnsq) {
|
||||||
make_entry(std::move(resolv), std::move(host_copy),
|
make_entry(std::move(resolv), std::move(host_copy),
|
||||||
DNS_STATUS_RUNNING, nullptr));
|
DNS_STATUS_RUNNING, nullptr));
|
||||||
|
|
||||||
|
start_gc_timer();
|
||||||
|
|
||||||
auto &ent = (*p.first).second;
|
auto &ent = (*p.first).second;
|
||||||
|
|
||||||
add_to_qlist(ent, dnsq);
|
add_to_qlist(ent, dnsq);
|
||||||
|
@ -260,4 +280,33 @@ void DNSTracker::cancel(DNSQuery *dnsq) {
|
||||||
dnsq->in_qlist = false;
|
dnsq->in_qlist = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DNSTracker::start_gc_timer() {
|
||||||
|
if (ev_is_active(&gc_timer_)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ev_timer_again(loop_, &gc_timer_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DNSTracker::gc() {
|
||||||
|
if (LOG_ENABLED(INFO)) {
|
||||||
|
LOG(INFO) << "Starting removing expired DNS cache entries";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto now = ev_now(loop_);
|
||||||
|
for (auto it = std::begin(ents_); it != std::end(ents_);) {
|
||||||
|
auto &ent = (*it).second;
|
||||||
|
if (ent.expiry >= now) {
|
||||||
|
++it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
it = ents_.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ents_.empty()) {
|
||||||
|
ev_timer_stop(loop_, &gc_timer_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -88,6 +88,10 @@ public:
|
||||||
int resolve(Address *result, DNSQuery *dnsq);
|
int resolve(Address *result, DNSQuery *dnsq);
|
||||||
// Cancels name lookup requested by |dnsq|.
|
// Cancels name lookup requested by |dnsq|.
|
||||||
void cancel(DNSQuery *dnsq);
|
void cancel(DNSQuery *dnsq);
|
||||||
|
// Removes expired entries from ents_.
|
||||||
|
void gc();
|
||||||
|
// Starts GC timer.
|
||||||
|
void start_gc_timer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ResolverEntry make_entry(std::unique_ptr<DualDNSResolver> resolv,
|
ResolverEntry make_entry(std::unique_ptr<DualDNSResolver> resolv,
|
||||||
|
@ -100,6 +104,10 @@ private:
|
||||||
void add_to_qlist(ResolverEntry &ent, DNSQuery *dnsq);
|
void add_to_qlist(ResolverEntry &ent, DNSQuery *dnsq);
|
||||||
|
|
||||||
std::map<StringRef, ResolverEntry> ents_;
|
std::map<StringRef, ResolverEntry> ents_;
|
||||||
|
// Periodically iterates ents_, and removes expired entries to avoid
|
||||||
|
// excessive use of memory. Since only backend API can potentially
|
||||||
|
// increase memory consumption, interval could be very long.
|
||||||
|
ev_timer gc_timer_;
|
||||||
struct ev_loop *loop_;
|
struct ev_loop *loop_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue