Browse Source

cache: fix dns cache prefetch issue

Nick Peng 3 years ago
parent
commit
5006059074
4 changed files with 78 additions and 41 deletions
  1. 32 14
      src/dns_cache.c
  2. 2 2
      src/dns_cache.h
  3. 15 0
      src/dns_conf.c
  4. 29 25
      src/dns_server.c

+ 32 - 14
src/dns_cache.c

@@ -243,7 +243,8 @@ struct dns_cache_data *dns_cache_new_data_packet(uint32_t cache_flag, void *pack
 	return (struct dns_cache_data *)cache_packet;
 }
 
-int _dns_cache_replace(char *domain, int ttl, dns_type_t qtype, int speed, int inactive, struct dns_cache_data *cache_data)
+int _dns_cache_replace(char *domain, int ttl, dns_type_t qtype, int speed, int inactive,
+					   struct dns_cache_data *cache_data)
 {
 	struct dns_cache *dns_cache = NULL;
 	struct dns_cache_data *old_cache_data = NULL;
@@ -521,10 +522,12 @@ void dns_cache_update(struct dns_cache *dns_cache)
 	pthread_mutex_unlock(&dns_cache_head.lock);
 }
 
-void _dns_cache_remove_expired_ttl(dns_cache_callback inactive_precallback, int ttl_inactive_pre, time_t *now)
+void _dns_cache_remove_expired_ttl(dns_cache_callback inactive_precallback, int ttl_inactive_pre,
+								   unsigned int max_callback_num, time_t *now)
 {
 	struct dns_cache *dns_cache = NULL;
 	struct dns_cache *tmp;
+	int callback_num = 0;
 	int ttl = 0;
 	LIST_HEAD(checklist);
 
@@ -541,22 +544,24 @@ void _dns_cache_remove_expired_ttl(dns_cache_callback inactive_precallback, int
 			continue;
 		}
 
-		ttl = dns_cache->info.replace_time + dns_cache->info.ttl - *now;
-		if (ttl > 0) {
+		ttl = *now - dns_cache->info.replace_time;
+		if (ttl < ttl_inactive_pre || inactive_precallback == NULL) {
 			continue;
 		}
 
-		if (dns_cache->del_pending == 1) {
+		if (callback_num >= max_callback_num) {
 			continue;
 		}
 
-		/* If the TTL time is in the pre-timeout range, call callback function */
-		if (inactive_precallback && ttl_inactive_pre < -ttl) {
-			list_add_tail(&dns_cache->check_list, &checklist);
-			dns_cache_get(dns_cache);
-			dns_cache->del_pending = 1;
+		if (dns_cache->del_pending == 1) {
 			continue;
 		}
+
+		/* If the TTL time is in the pre-timeout range, call callback function */
+		dns_cache_get(dns_cache);
+		list_add_tail(&dns_cache->check_list, &checklist);
+		dns_cache->del_pending = 1;
+		callback_num++;
 	}
 	pthread_mutex_unlock(&dns_cache_head.lock);
 
@@ -570,14 +575,19 @@ void _dns_cache_remove_expired_ttl(dns_cache_callback inactive_precallback, int
 	}
 }
 
-void dns_cache_invalidate(dns_cache_callback precallback, int ttl_pre, dns_cache_callback inactive_precallback,
-						  int ttl_inactive_pre)
+void dns_cache_invalidate(dns_cache_callback precallback, int ttl_pre, unsigned int max_callback_num,
+						  dns_cache_callback inactive_precallback, int ttl_inactive_pre)
 {
 	struct dns_cache *dns_cache = NULL;
 	struct dns_cache *tmp;
 	time_t now;
 	int ttl = 0;
 	LIST_HEAD(checklist);
+	int callback_num = 0;
+
+	if (max_callback_num <= 0) {
+		max_callback_num = -1;
+	}
 
 	if (dns_cache_head.size <= 0) {
 		return;
@@ -590,10 +600,11 @@ void dns_cache_invalidate(dns_cache_callback precallback, int ttl_pre, dns_cache
 		ttl = dns_cache->info.insert_time + dns_cache->info.ttl - now;
 		if (ttl > 0 && ttl < ttl_pre) {
 			/* If the TTL time is in the pre-timeout range, call callback function */
-			if (precallback && dns_cache->del_pending == 0) {
+			if (precallback && dns_cache->del_pending == 0 && callback_num < max_callback_num) {
 				list_add_tail(&dns_cache->check_list, &checklist);
 				dns_cache_get(dns_cache);
 				dns_cache->del_pending = 1;
+				callback_num++;
 				continue;
 			}
 		}
@@ -609,7 +620,7 @@ void dns_cache_invalidate(dns_cache_callback precallback, int ttl_pre, dns_cache
 	pthread_mutex_unlock(&dns_cache_head.lock);
 
 	if (dns_cache_head.enable_inactive && dns_cache_head.inactive_list_expired != 0) {
-		_dns_cache_remove_expired_ttl(inactive_precallback, ttl_inactive_pre, &now);
+		_dns_cache_remove_expired_ttl(inactive_precallback, ttl_inactive_pre, max_callback_num, &now);
 	}
 
 	list_for_each_entry_safe(dns_cache, tmp, &checklist, check_list)
@@ -618,6 +629,7 @@ void dns_cache_invalidate(dns_cache_callback precallback, int ttl_pre, dns_cache
 		if (precallback) {
 			precallback(dns_cache);
 		}
+		list_del(&dns_cache->check_list);
 		dns_cache_release(dns_cache);
 	}
 }
@@ -695,11 +707,16 @@ int dns_cache_load(const char *file)
 {
 	int fd = -1;
 	int ret = 0;
+	size_t filesize;
 	fd = open(file, O_RDONLY);
 	if (fd < 0) {
 		return 0;
 	}
 
+	filesize = lseek(fd, 0, SEEK_END);
+	lseek(fd, 0, SEEK_SET);
+	posix_fadvise(fd, 0, filesize, POSIX_FADV_WILLNEED | POSIX_FADV_SEQUENTIAL);
+
 	struct dns_cache_file cache_file;
 	ret = read(fd, &cache_file, sizeof(cache_file));
 	if (ret != sizeof(cache_file)) {
@@ -717,6 +734,7 @@ int dns_cache_load(const char *file)
 		goto errout;
 	}
 
+	tlog(TLOG_INFO, "load cache file %s, total %d records", file, cache_file.cache_number);
 	if (_dns_cache_read_record(fd, cache_file.cache_number) != 0) {
 		goto errout;
 	}

+ 2 - 2
src/dns_cache.h

@@ -143,8 +143,8 @@ void dns_cache_update(struct dns_cache *dns_cache);
 
 typedef void dns_cache_callback(struct dns_cache *dns_cache);
 
-void dns_cache_invalidate(dns_cache_callback precallback, int ttl_pre, dns_cache_callback inactive_precallback,
-						  int ttl_inactive_pre);
+void dns_cache_invalidate(dns_cache_callback precallback, int ttl_pre, unsigned int max_callback_num,
+						  dns_cache_callback inactive_precallback, int ttl_inactive_pre);
 
 int dns_cache_get_ttl(struct dns_cache *dns_cache);
 

+ 15 - 0
src/dns_conf.c

@@ -913,6 +913,7 @@ static int _config_bind_ip(int argc, char *argv[], DNS_BIND_TYPE type)
 	char group_name[DNS_GROUP_NAME_LEN];
 	const char *group = NULL;
 	unsigned int server_flag = 0;
+	int i = 0;
 
 	/* clang-format off */
 	static struct option long_options[] = {
@@ -940,6 +941,20 @@ static int _config_bind_ip(int argc, char *argv[], DNS_BIND_TYPE type)
 		return 0;
 	}
 
+	for (i = 0; i < dns_conf_bind_ip_num; i++) {
+		bind_ip = &dns_conf_bind_ip[i];
+		if (bind_ip->type != type) {
+			continue;
+		}
+
+		if (strncmp(bind_ip->ip, ip, DNS_MAX_IPLEN) != 0) {
+			continue;
+		}
+
+		tlog(TLOG_WARN, "Bind server %s, type %d, already configured, skip.", ip, type);
+		return 0;
+	}
+
 	bind_ip = &dns_conf_bind_ip[index];
 	bind_ip->type = type;
 	bind_ip->flags = 0;

+ 29 - 25
src/dns_server.c

@@ -56,6 +56,7 @@
 #define SOCKET_PRIORITY (6)
 #define CACHE_AUTO_ENABLE_SIZE (1024 * 1024 * 128)
 #define EXPIRED_DOMAIN_PREFTCH_TIME (3600 * 8)
+#define DNS_MAX_DOMAIN_REFETCH_NUM 16
 
 #define RECV_ERROR_AGAIN 1
 #define RECV_ERROR_OK 0
@@ -556,14 +557,14 @@ static void _dns_rrs_result_log(struct dns_server_post_context *context, struct
 	}
 
 	if (addr_map->addr_type == DNS_T_A) {
-		tlog(TLOG_INFO, "result: %s, id: %d, index: %d, rtt: %d, %d.%d.%d.%d", request->domain, request->id,
-			 context->ip_num, addr_map->ping_time, addr_map->ip_addr[0], addr_map->ip_addr[1], addr_map->ip_addr[2],
-			 addr_map->ip_addr[3]);
+		tlog(TLOG_INFO, "result: %s, id: %d, index: %d, rtt: %.1f ms, %d.%d.%d.%d", request->domain, request->id,
+			 context->ip_num, ((float)addr_map->ping_time) / 10, addr_map->ip_addr[0], addr_map->ip_addr[1],
+			 addr_map->ip_addr[2], addr_map->ip_addr[3]);
 	} else if (addr_map->addr_type == DNS_T_AAAA) {
 		tlog(TLOG_INFO,
-			 "result: %s, id: %d, index: %d, rtt: %d, "
+			 "result: %s, id: %d, index: %d, rtt: %.1f ms, "
 			 "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
-			 request->domain, request->id, context->ip_num, addr_map->ping_time, addr_map->ip_addr[0],
+			 request->domain, request->id, context->ip_num, ((float)addr_map->ping_time) / 10, addr_map->ip_addr[0],
 			 addr_map->ip_addr[1], addr_map->ip_addr[2], addr_map->ip_addr[3], addr_map->ip_addr[4],
 			 addr_map->ip_addr[5], addr_map->ip_addr[6], addr_map->ip_addr[7], addr_map->ip_addr[8],
 			 addr_map->ip_addr[9], addr_map->ip_addr[10], addr_map->ip_addr[11], addr_map->ip_addr[12],
@@ -689,7 +690,7 @@ static int _dns_add_rrs(struct dns_server_post_context *context)
 		context->ip_num++;
 		if (context->qtype == DNS_T_A) {
 			ret |= dns_add_A(context->packet, DNS_RRS_AN, domain, request->ip_ttl, request->ip_addr);
-			tlog(TLOG_DEBUG, "result: %s, rtt: %d, %d.%d.%d.%d", request->domain, request->ping_time,
+			tlog(TLOG_DEBUG, "result: %s, rtt: %.1f ms, %d.%d.%d.%d", request->domain, ((float)request->ping_time) / 10,
 				 request->ip_addr[0], request->ip_addr[1], request->ip_addr[2], request->ip_addr[3]);
 		}
 
@@ -697,13 +698,13 @@ static int _dns_add_rrs(struct dns_server_post_context *context)
 		if (context->qtype == DNS_T_AAAA) {
 			ret |= dns_add_AAAA(context->packet, DNS_RRS_AN, domain, request->ip_ttl, request->ip_addr);
 			tlog(TLOG_DEBUG,
-				 "result: %s, rtt: %d, "
+				 "result: %s, rtt: %.1f ms, "
 				 "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
-				 request->domain, request->ping_time, request->ip_addr[0], request->ip_addr[1], request->ip_addr[2],
-				 request->ip_addr[3], request->ip_addr[4], request->ip_addr[5], request->ip_addr[6],
-				 request->ip_addr[7], request->ip_addr[8], request->ip_addr[9], request->ip_addr[10],
-				 request->ip_addr[11], request->ip_addr[12], request->ip_addr[13], request->ip_addr[14],
-				 request->ip_addr[15]);
+				 request->domain, ((float)request->ping_time) / 10, request->ip_addr[0], request->ip_addr[1],
+				 request->ip_addr[2], request->ip_addr[3], request->ip_addr[4], request->ip_addr[5],
+				 request->ip_addr[6], request->ip_addr[7], request->ip_addr[8], request->ip_addr[9],
+				 request->ip_addr[10], request->ip_addr[11], request->ip_addr[12], request->ip_addr[13],
+				 request->ip_addr[14], request->ip_addr[15]);
 		}
 	}
 
@@ -1539,18 +1540,18 @@ static int _dns_server_request_complete(struct dns_request *request)
 		tlog(TLOG_INFO, "result: %s, qtype: %d, SOA", request->domain, request->qtype);
 	} else {
 		if (request->qtype == DNS_T_A) {
-			tlog(TLOG_INFO, "result: %s, qtype: %d, rtt: %d, %d.%d.%d.%d", request->domain, request->qtype,
-				 request->ping_time, request->ip_addr[0], request->ip_addr[1], request->ip_addr[2],
+			tlog(TLOG_INFO, "result: %s, qtype: %d, rtt: %.1f ms, %d.%d.%d.%d", request->domain, request->qtype,
+				 ((float)request->ping_time) / 10, request->ip_addr[0], request->ip_addr[1], request->ip_addr[2],
 				 request->ip_addr[3]);
 		} else if (request->qtype == DNS_T_AAAA) {
 			tlog(TLOG_INFO,
-				 "result: %s, qtype: %d, rtt: %d, "
+				 "result: %s, qtype: %d, rtt: %.1f ms, "
 				 "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
-				 request->domain, request->qtype, request->ping_time, request->ip_addr[0], request->ip_addr[1],
-				 request->ip_addr[2], request->ip_addr[3], request->ip_addr[4], request->ip_addr[5],
-				 request->ip_addr[6], request->ip_addr[7], request->ip_addr[8], request->ip_addr[9],
-				 request->ip_addr[10], request->ip_addr[11], request->ip_addr[12], request->ip_addr[13],
-				 request->ip_addr[14], request->ip_addr[15]);
+				 request->domain, request->qtype, ((float)request->ping_time) / 10, request->ip_addr[0],
+				 request->ip_addr[1], request->ip_addr[2], request->ip_addr[3], request->ip_addr[4],
+				 request->ip_addr[5], request->ip_addr[6], request->ip_addr[7], request->ip_addr[8],
+				 request->ip_addr[9], request->ip_addr[10], request->ip_addr[11], request->ip_addr[12],
+				 request->ip_addr[13], request->ip_addr[14], request->ip_addr[15]);
 		}
 	}
 
@@ -2649,7 +2650,7 @@ void _dns_server_query_end(struct dns_request *request)
 		if (request->dualstack_selection_has_ip && request->dualstack_selection_ping_time > 0) {
 			goto out;
 		}
-		
+
 		request->has_ping_result = 1;
 		_dns_server_request_complete(request);
 	}
@@ -4560,7 +4561,7 @@ static void _dns_server_period_run_second(void)
 	}
 
 	if (now - 180 > last) {
-		dns_cache_invalidate(NULL, 0, NULL, 0);
+		dns_cache_invalidate(NULL, 0, 0, NULL, 0);
 		tlog(TLOG_WARN, "Service paused for 180s, force invalidate cache.");
 	}
 
@@ -4578,12 +4579,13 @@ static void _dns_server_period_run_second(void)
 						prefetch_time = EXPIRED_DOMAIN_PREFTCH_TIME;
 					}
 				}
-				dns_cache_invalidate(NULL, 0, _dns_server_prefetch_expired_domain, prefetch_time);
+				dns_cache_invalidate(NULL, 0, DNS_MAX_DOMAIN_REFETCH_NUM, _dns_server_prefetch_expired_domain,
+									 prefetch_time);
 			} else {
-				dns_cache_invalidate(_dns_server_prefetch_domain, 3, NULL, 0);
+				dns_cache_invalidate(_dns_server_prefetch_domain, 3, DNS_MAX_DOMAIN_REFETCH_NUM, NULL, 0);
 			}
 		} else {
-			dns_cache_invalidate(NULL, 0, NULL, 0);
+			dns_cache_invalidate(NULL, 0, 0, NULL, 0);
 		}
 	}
 
@@ -4806,6 +4808,8 @@ static int _dns_create_socket(const char *host_ip, int type)
 		}
 	}
 
+	fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+
 	freeaddrinfo(gai);
 
 	return fd;