Intégrez le SDK iOS HTTPDNS à votre application pour une résolution de noms de domaine fiable, dotée d'une mise en cache intégrée.
Présentation
Le SDK iOS encapsule l'API JSON DoH de HTTPDNS. Il fournit des API pour la résolution de noms de domaine dans les applications iOS et met en œuvre une mise en cache des noms de domaine efficace, basée sur les politiques TTL (Time-to-Live) et LRU (Least Recently Used). Intégrez HTTPDNS à votre application iOS pour corriger les anomalies de résolution de noms de domaine et réaliser une planification de résolution précise et économique.
Vous pouvez également définir HTTPDNS comme résolveur DNS chiffré par défaut en utilisant la solution native de DNS chiffré iOS 14.
Principaux avantages :
-
Facilité d'utilisation :
L'intégration de HTTPDNS à votre application nécessite un minimum de code.
-
Latence nulle :
Un cache LRU interne stocke les adresses IP résolues localement et actualise proactivement les entrées expirées, permettant ainsi une résolution sans latence.
Exemple de projet Objective-C : code source de l'exemple de projet alidns_ios_demo.
Exemple de projet Swift : code source de l'exemple de projet DNSResolverSwiftDemo.
Intégration du SDK
Importer le SDK
CocoaPods
-
Dans votre Podfile, spécifiez l'emplacement du dépôt. Assurez-vous d'inclure le dépôt principal.
source 'https://github.com/CocoaPods/Specs.git' source 'https://github.com/aliyun/aliyun-specs.git' -
Ajoutez la dépendance pour la cible de votre projet :
pod 'AlicloudPDNS'
Manuel
Téléchargez le SDK iOS depuis la page Téléchargement du SDK.
Une fois que vous avez obtenu le framework du SDK
pdns-sdk-ios.framework, ajoutez-le manuellement à votre projet.-
Importez les bibliothèques système requises :
Foundation.framework
SystemConfiguration.framework
CoreFoundation.framework
CoreTelephony.framework
Dans les paramètres de compilation (Build Settings) de votre projet, ajoutez l'indicateur -ObjC aux autres indicateurs de l'éditeur de liens (Other Linker Flags).
Initialisation du SDK
Enregistrez votre application dans la console pour obtenir son ID de compte et ses identifiants AccessKey avant l'initialisation.
Pour éviter les échecs de résolution, initialisez le SDK aussi tôt que possible dans le cycle de vie de votre application.
Initialisez le SDK dans la méthode application:didFinishLaunchingWithOptions:.
DNSResolver *resolver = [DNSResolver share];
// setAccountId:@"******": Replace the asterisks with the Account ID from the Access Configuration page in the console.
// andAccessKeyId:@"********": Replace the asterisks with the AccessKey ID of the key that you created on the Access Configuration page.
// andAccesskeySecret:@"********": Replace the asterisks with the AccessKey Secret of the key that you created on the Access Configuration page.
[resolver setAccountId:@"******" andAccessKeyId:@"********" andAccesskeySecret:@"********"];
// Specify domains for automatic cache updates. The array can contain a maximum of 10 domains.
[resolver setKeepAliveDomains:@[@"your_domain_1", @"your_domain_2"]];
// Pre-resolve domains that you expect to use later.
[resolver preloadDomains:@[@"domain1", @"domain2", @"domain3"] complete:^{
// All domains are pre-resolved.
}];
Référence de l'API
Paramètres courants
1. ID de compte et authentification
Requis. La console génère un ID de compte unique lorsque vous enregistrez votre application. Créez une paire de clés AccessKey pour générer une clé AccessKey destinée à l'authentification, puis configurez-la :
// setAccountId:@"******": Replace the asterisks with the Account ID from the Access Configuration page in the console.
// andAccessKeyId:@"********": Replace the asterisks with the AccessKey ID of the key that you created on the Access Configuration page.
// andAccesskeySecret:@"********": Replace the asterisks with the AccessKey Secret of the key that you created on the Access Configuration page.
[[DNSResolver share] setAccountId:@"******" andAccessKeyId:@"********" andAccesskeySecret:@"********"];
Pour empêcher l'exposition de votre ID de compte, de votre AccessKey ID ou de votre AccessKey Secret dans les journaux ou autres données générées par votre application en cours d'exécution, désactivez la journalisation de débogage du SDK dans votre version de production.
À des fins de démonstration, l'exemple de code transmet directement l'ID de compte, l'AccessKey ID et l'AccessKey Secret. Ces identifiants sont utilisés pour la facturation. Pour éviter qu'ils ne soient exposés via une décompilation malveillante, ne codez pas en dur les identifiants en texte clair dans votre application de production. Encodez ou chiffrez-les plutôt, et décodez ou déchiffrez-les uniquement lorsque cela est nécessaire. Nous vous recommandons également d'obscurcir et de renforcer le code de votre application. Sinon, votre ID de compte, votre AccessKey ID et votre AccessKey Secret pourraient être compromis.
2. Définir le protocole de résolution
Définissez le protocole de résolution (HTTP ou HTTPS) à l'aide de la propriété scheme.
Le SDK utilise et recommande le protocole HTTPS par défaut, car il offre une meilleure sécurité. HTTPDNS est facturé en fonction du nombre de requêtes de résolution. Les requêtes HTTPS sont facturées cinq fois plus cher que les requêtes HTTP. Sélectionnez un type de schéma en fonction de vos besoins métier. Définissez la propriété comme suit :
[DNSResolver share].scheme = DNSResolverSchemeHttps;
3. Activer ou désactiver la mise en cache
Lorsqu'elle est activée, les résultats de résolution sont mis en cache localement, de sorte que les recherches suivantes renvoient instantanément les données depuis le cache.
La mise en cache est activée par défaut. Pour la désactiver, utilisez le code suivant :
[DNSResolver share].cacheEnable=NO;
4. Définir la mise en cache keep-alive pour les domaines
Lorsque cette option est activée, le SDK actualise proactivement les entrées du cache pour les domaines spécifiés avant leur expiration. Cela permet de maintenir les données à jour, mais augmente le nombre de requêtes de résolution et le trafic réseau. Sans cette fonctionnalité, les mises à jour du cache se produisent uniquement lorsqu'une méthode de résolution est appelée.
// The array can contain a maximum of 10 domains.
[[DNSResolver share] setKeepAliveDomains:@[@"www.taobao.com",@"www.aliyun.com"]];
-
Avantages :
Les enregistrements sont mis à jour rapidement (avant l'expiration du TTL).
Lorsqu'elle est combinée à la pré-résolution, cette fonction peut réduire la latence de résolution initiale à 0 ms.
Inconvénient : Le renouvellement des requêtes à 75 % du TTL d'un enregistrement entraîne des coûts supplémentaires.
5. Pré-résolution
Pré-résolvez les domaines au démarrage de l'application afin que les recherches ultérieures atteignent le cache avec une latence quasi nulle.
Exemple de code :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
DNSResolver *resolver = [DNSResolver share];
// setAccountId:@"******": Replace the asterisks with the Account ID from the Access Configuration page in the console.
// andAccessKeyId:@"********": Replace the asterisks with the AccessKey ID of the key that you created on the Access Configuration page.
// andAccesskeySecret:@"********": Replace the asterisks with the AccessKey Secret of the key that you created on the Access Configuration page.
[resolver setAccountId:@"******" andAccessKeyId:@"********" andAccesskeySecret:@"********"];
resolver.cacheEnable = YES;
// Pre-resolve domains that you expect to use later.
[resolver preloadDomains:@[@"domain1", @"domain2", @"domain3"] complete:^{
// All domains are pre-resolved.
}];
return YES;
}
Paramètres avancés
1. Activer l'accès IPv6 côté serveur
Le service HTTPDNS prend en charge l'accès double pile (IPv4 et IPv6). Par défaut, le SDK utilise IPv4.
Pour utiliser IPv6, assurez-vous que votre réseau le prend en charge et activez cette fonctionnalité :
[DNSResolver share].ipv6Enable = YES;
2. Mode court
L'API JSON DoH de HTTPDNS renvoie soit un JSON complet, soit un tableau d'adresses IP simplifié. Le SDK utilise le JSON complet par défaut.
Pour utiliser le format de tableau d'adresses IP simplifié :
[DNSResolver share].shortEnable = YES;
3. Définir la taille du cache
Si la mise en cache est activée, vous pouvez personnaliser le nombre de domaines à mettre en cache. La plage prise en charge va de 100 à 500.
La taille de cache par défaut est de 100 domaines. Pour définir une taille de cache personnalisée, utilisez la propriété cacheCountLimit :
[DNSResolver share].cacheCountLimit = 200;
4. Activer ou désactiver le test de vitesse des adresses IP
Lorsque le test de vitesse des adresses IP est activé, les résultats de résolution sont triés par latence, l'adresse IP la plus rapide étant renvoyée en premier.
À partir de la version 2.3.1 du SDK, le test de vitesse des adresses IP est activé par défaut (YES). Dans les versions antérieures, il est désactivé par défaut (NO). Pour définir explicitement cette fonctionnalité, utilisez le code suivant :
[DNSResolver share].speedTestEnable=YES;
5. Définir la méthode de test de vitesse des adresses IP
Configurez la méthode de sondage : définissez-la sur 0 pour un sondage ICMP, ou sur un numéro de port (80, 443, etc.) pour un sondage de socket sur ce port.
À partir de la version 2.3.1 du SDK, le port par défaut est 80. Dans les versions antérieures, le port par défaut est 443.
[DNSResolver share].speedPort = 80;
6. Définir le handicap de test de vitesse IPv6 (pris en charge depuis la version 2.3.1)
Définissez un handicap de test de vitesse IPv6 en millisecondes. Lorsqu'un résultat de résolution contient à la fois des adresses IPv4 et IPv6, le SDK soustrait ce handicap de la latence IPv6 mesurée avant de la comparer à la latence IPv4. Une adresse IPv6 est alors toujours préférée lorsqu'elle n'est que marginalement plus lente, tant que l'écart reste dans les limites du handicap. La plage valide va de 0 à 1000. Ce paramètre prend effet uniquement lorsque le test de vitesse des adresses IP est activé.
La valeur par défaut est 0, ce qui désactive le handicap. Pour définir un handicap personnalisé, utilisez le code suivant :
[DNSResolver share].speedTestIpv6PreferMs = 0;
7. Activer ou désactiver la mise en cache des noms de domaine spécifique au FAI
Lorsqu'elle est activée, les entrées du cache sont isolées par réseau de FAI. Lorsqu'elle est désactivée, tous les réseaux partagent un seul cache.
La mise en cache des noms de domaine spécifique au FAI est activée par défaut.
[DNSResolver share].ispEnable = YES;
8. Définir le TTL maximal pour le cache négatif
Définissez un TTL maximal pour le cache négatif, qui stocke les résultats des recherches ayant échoué.
La valeur par défaut est de 30 s. Pour définir un TTL maximal personnalisé pour le cache négatif, utilisez le code suivant :
[DNSResolver share].maxNegativeCache = 30;
9. Définir le TTL maximal du cache
Définissez un TTL maximal du cache pour limiter la durée de vie des entrées, indépendamment des valeurs TTL fournies par le serveur.
La valeur par défaut est de 3600 s. Pour définir un TTL maximal de cache personnalisé, utilisez le code suivant :
[DNSResolver share].maxCacheTTL= 3600;
10. Activer le cache immuable
[DNSResolver share].immutableCacheEnable = NO;// Immutable cache is disabled by default.
Le SDK propose trois mécanismes de mise à jour du cache :
-
Cache immuable : Lorsque cette fonctionnalité est activée, le cache est considéré comme toujours valide pendant l'exécution de l'application. Le SDK ignore les vérifications d'expiration et les mises à jour, ce qui minimise le nombre de requêtes de résolution.
Pour l'activer, appelez :
[DNSResolver share].immutableCacheEnable = YES -
Mise à jour active du cache : Maintient les résultats de résolution mis en cache à jour. Lorsqu'un enregistrement faisant autorité pour un domaine change, les requêtes bénéficient toujours de hits de cache à faible latence tandis que le SDK actualise les enregistrements mis en cache. Le tableau est limité à un maximum de 10 domaines.
Pour l'activer, appelez :
[[DNSResolver share] setKeepAliveDomains:@[@"your_domain_1",@"your_domain_2"]] -
Mise à jour passive du cache : Le cache est mis à jour passivement lorsque vous appelez l'une des deux méthodes suivantes pour obtenir les résultats de résolution :
La méthode
- (void)getIpv4DataWithDomain:(NSString *)domain complete:(void(^)(NSArray<NSString *> *dataArray))completeobtient un tableau d'adresses IPv4 pour un domaine. Si le cache n'est pas vide et que l'entrée est dans sa période TTL, la méthode renvoie immédiatement le résultat mis en cache. Sinon, elle récupère le dernier résultat via le réseau, le renvoie et met à jour le cache. Utilisez cette méthode dans les scénarios nécessitant une grande précision.-
La méthode
- (NSArray<NSString *> *)getIpv4ByCacheWithDomain:(NSString *)domain andExpiredIPEnabled:(BOOL)enablerécupère les résultats de résolution IPv4 depuis le cache. Le comportement de cette méthode dépend du paramètreenable.Description du paramètre : Si
enableest défini surYES, la méthode renvoie un enregistrement obsolète même si le cache a expiré (ounilsi le cache est vide), puis met à jour le cache de manière asynchrone. Si la valeur estNO, elle renvoienillorsque le cache a expiré ou est vide, puis met à jour le cache de manière asynchrone.
11. Délai d'attente
La propriété timeout définit le timeout de la requête pour la résolution. Valeur par défaut : 3 s. Plage recommandée : 2 s à 5 s.
12. Définir le nombre maximal de requêtes de résolution simultanées (pris en charge depuis la version 2.3.1)
Définissez le nombre maximal de requêtes de résolution DNS simultanées envoyées par le SDK. La plage valide va de 1 à 50. La valeur par défaut est 10. Pour définir une limite personnalisée, utilisez le code suivant :
[DNSResolver share].maxConcurrentResolveCount = 10;
API de service
Exemple de code :
/// Pre-resolves domain information. Call this method at app startup. The results are stored in the cache to accelerate subsequent resolutions.
/// Automatically detects the network environment (IPv4-only, IPv6-only, or dual-stack) to get an IP suitable for the current network.
/// @param domainArray An array of domain names.
/// @param complete A callback that is executed after resolution is complete.
- (void)preloadDomains:(NSArray<NSString *> *)domainArray complete:(void(^)(void))complete;
/// Gets an array of IP addresses for a domain. This method automatically detects the network environment (IPv4-only, IPv6-only, or dual-stack) to get a suitable IP.
/// If caching is enabled, it returns data from the cache first. If the cache is empty or expired, it fetches the IP over the network. If caching is disabled, it always fetches the IP over the network.
/// @param domain The domain name.
/// @param complete A callback that returns all IP addresses.
- (void)getIpsDataWithDomain:(NSString *)domain complete:(void(^)(NSArray<NSString *> *dataArray))complete;
/// Gets an array of IP addresses directly from the cache without waiting. This method automatically detects the network environment (IPv4-only, IPv6-only, or dual-stack).
/// Returns nil if the cache is empty. If the cache is not empty and `enable` is set to YES, it returns the cached data. If the data is expired, it asynchronously updates the cache. If the cache is not empty and `enable` is set to NO, it returns nil for expired entries and asynchronously updates the cache.
/// @param domain The domain name.
/// @param enable Specifies whether to return expired IP addresses.
- (NSArray<NSString *> *)getIpsByCacheWithDomain:(NSString *)domain andExpiredIPEnabled:(BOOL)enable;
/// Gets an array of IPv4 information objects for a domain.
/// If caching is enabled, it returns data from the cache first. If the cache is empty or expired, it fetches the IPs over the network. If caching is disabled, it always fetches the IPs over the network.
/// @param domain The domain name.
/// @param complete A callback that returns all domain information objects.
- (void)getIpv4InfoWithDomain:(NSString *)domain complete:(void(^)(NSArray<DNSDomainInfo *> *domainInfoArray))complete;
/// Gets an array of IPv6 information objects for a domain.
/// If caching is enabled, it returns data from the cache first. If the cache is empty or expired, it fetches the IPs over the network. If caching is disabled, it always fetches the IPs over the network.
/// @param domain The domain name.
/// @param complete A callback that returns all domain information objects.
- (void)getIpv6InfoWithDomain:(NSString *)domain complete:(void(^)(NSArray<DNSDomainInfo *> *domainInfoArray))complete;
/// Gets a random IPv4 information object for a domain.
/// If caching is enabled, it returns data from the cache first. If the cache is empty or expired, it fetches the IP over the network. If caching is disabled, it always fetches the IP over the network.
/// @param domain The domain name.
/// @param complete A callback that returns one random domain information object.
- (void)getRandomIpv4InfoWithDomain:(NSString *)domain complete:(void(^)(DNSDomainInfo *domainInfo))complete;
/// Gets a random IPv6 information object for a domain.
/// If caching is enabled, it returns data from the cache first. If the cache is empty or expired, it fetches the IP over the network. If caching is disabled, it always fetches the IP over the network.
/// @param domain The domain name.
/// @param complete A callback that returns one random domain information object.
- (void)getRandomIpv6InfoWithDomain:(NSString *)domain complete:(void(^)(DNSDomainInfo *domainInfo))complete;
/// Gets an array of IPv4 addresses for a domain.
/// If caching is enabled, it returns data from the cache first. If the cache is empty or expired, it fetches the IPs over the network. If caching is disabled, it always fetches the IPs over the network.
/// @param domain The domain name.
/// @param complete A callback that returns all IP addresses.
- (void)getIpv4DataWithDomain:(NSString *)domain complete:(void(^)(NSArray<NSString *> *dataArray))complete;
/// Gets an array of IPv6 addresses for a domain.
/// If caching is enabled, it returns data from the cache first. If the cache is empty or expired, it fetches the IPs over the network. If caching is disabled, it always fetches the IPs over the network.
/// @param domain The domain name.
/// @param complete A callback that returns all IP addresses.
- (void)getIpv6DataWithDomain:(NSString *)domain complete:(void(^)(NSArray<NSString *> *dataArray))complete;
/// Gets a random IPv4 address for a domain.
/// If caching is enabled, it returns data from the cache first. If the cache is empty or expired, it fetches the IP over the network. If caching is disabled, it always fetches the IP over the network.
/// @param domain The domain name.
/// @param complete A callback that returns one random IP address.
- (void)getRandomIpv4DataWithDomain:(NSString *)domain complete:(void(^)(NSString *data))complete;
/// Gets a random IPv6 address for a domain.
/// If caching is enabled, it returns data from the cache first. If the cache is empty or expired, it fetches the IP over the network. If caching is disabled, it always fetches the IP over the network.
/// @param domain The domain name.
/// @param complete A callback that returns one random IP address.
- (void)getRandomIpv6DataWithDomain:(NSString *)domain complete:(void(^)(NSString *data))complete;
/// Pre-resolves IPv4 information for domains. Call this at app startup. The results are stored in the cache to accelerate subsequent resolutions.
/// @param domainArray An array of domain names.
/// @param complete A callback that is executed after resolution is complete.
- (void)preloadIpv4Domains:(NSArray<NSString *> *)domainArray complete:(void(^)(void))complete;
/// Pre-resolves IPv6 information for domains. Call this at app startup. The results are stored in the cache to accelerate subsequent resolutions.
/// @param domainArray An array of domain names.
/// @param complete A callback that is executed after resolution is complete.
- (void)preloadIpv6Domains:(NSArray<NSString *> *)domainArray complete:(void(^)(void))complete;
/// Gets an array of IPv4 addresses directly from the cache without waiting.
/// Returns nil if the cache is empty. If the cache is not empty and `enable` is set to YES, it returns the cached data. If the data is expired, it asynchronously updates the cache. If the cache is not empty and `enable` is set to NO, it returns nil for expired entries and asynchronously updates the cache.
/// @param domain The domain name.
/// @param enable Specifies whether to return expired IP addresses.
- (NSArray<NSString *> *)getIpv4ByCacheWithDomain:(NSString *)domain andExpiredIPEnabled:(BOOL)enable;
/// Gets an array of IPv6 addresses directly from the cache without waiting.
/// Returns nil if the cache is empty. If the cache is not empty and `enable` is set to YES, it returns the cached data. If the data is expired, it asynchronously updates the cache. If the cache is not empty and `enable` is set to NO, it returns nil for expired entries and asynchronously updates the cache.
/// @param domain The domain name.
/// @param enable Specifies whether to return expired IP addresses.
- (NSArray<NSString *> *)getIpv6ByCacheWithDomain:(NSString *)domain andExpiredIPEnabled:(BOOL)enable;
/// Collects request statistics.
-(NSArray *)getRequestReportInfo;
Exemples d'utilisation de l'API
1. Définissez les informations de base
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Initialization method
DNSResolver *resolver = [DNSResolver share];
// setAccountId:@"******": Replace the asterisks with the Account ID from the Access Configuration page in the console.
// andAccessKeyId:@"********": Replace the asterisks with the AccessKey ID of the key that you created on the Access Configuration page.
// andAccesskeySecret:@"********": Replace the asterisks with the AccessKey Secret of the key that you created on the Access Configuration page.
[resolver setAccountId:@"******" andAccessKeyId:@"********" andAccesskeySecret:@"********"];
// Specify domains for automatic cache updates. The array can contain a maximum of 10 domains.
[resolver setKeepAliveDomains:@[@"your_domain_1",@"your_domain_2"]];
// Pre-resolve domains to get resolution results in advance and store them in the cache.
[resolver preloadDomains:@[@"domain1", @"domain2", @"domain3"] complete:^{
// All domains are pre-resolved.
}];
return YES;
}
2. Utilisez l'API de résolution de noms de domaine
Le SDK propose plusieurs méthodes de résolution dans le fichier DNSResolver.h. L'exemple suivant utilise une méthode qui s'adapte automatiquement à l'environnement réseau (IPv4 uniquement, IPv6 uniquement ou double pile).
Déclaration de l'API :
/// Gets an array of IP addresses for a domain. This method automatically adapts to the network environment (IPv4-only, IPv6-only, or dual-stack).
/// If caching is enabled, it returns data from the cache first. If the cache is empty or expired, it fetches the IPs over the network. If caching is disabled, it always fetches the IPs over the network.
/// @param domain The domain name.
/// @param complete A callback that returns all IP addresses.
- (void)getIpsDataWithDomain:(NSString *)domain complete:(void(^)(NSArray<NSString *> *dataArray))complete;
Exemple d'appel de l'API :
[[DNSResolver share] getIpsDataWithDomain:@"www.taobao.com" complete:^(NSArray<NSString *> *dataArray) {
// dataArray is the array of IP addresses for www.taobao.com.
if (dataArray.count > 0) {
//TODO: Use an IP address for the URL connection.
}
}];
3. Récupérez directement les résultats de résolution depuis le cache
Déclaration de l'API :
/// Gets an array of IP addresses directly from the cache without waiting. This method automatically adapts to the network environment (IPv4-only, IPv6-only, or dual-stack).
/// Returns nil if the cache is empty. If the cache is not empty and `enable` is set to YES, it returns the cached data. If the data is expired, it asynchronously updates the cache. If the cache is not empty and `enable` is set to NO, it returns nil for expired entries and asynchronously updates the cache.
/// @param domain The domain name.
/// @param enable Specifies whether to return expired IP addresses.
- (NSArray<NSString *> *)getIpsByCacheWithDomain:(NSString *)domain andExpiredIPEnabled:(BOOL)enable;
Exemple d'appel :
NSArray *result = [[DNSResolver share] getIpsByCacheWithDomain:@"your_domain" andExpiredIPEnabled:YES];
// Use the cached result.
if (result.count > 0) {
//TODO: Use an IP address for the URL connection.
}
Remarque : La récupération directe des résultats depuis le cache est rapide, mais la méthode renvoie nil si le cache est vide, ou si les données du cache ont expiré et que le paramètre enable est défini sur NO.
4. Effacez le cache
Déclaration de l'API :
/// `hostArray` is an array of hostnames to clear from the cache. To clear all data, pass nil or an empty array.
-(void)clearHostCache:(NSArray <NSString *>*)hostArray;
Exemple d'appel :
[[DNSResolver share] clearHostCache:@[@"domain1", @"domain2"]];
5. Collectez des statistiques
Déclaration de l'API :
/// Collects request statistics.
-(NSArray *)getRequestReportInfo;
Exemple d'appel :
NSArray *array = [[DNSResolver share] getRequestReportInfo];
Format des données :
(
{
avgRtt = "1"; // Average domain resolution time (ms)
cacheDnsNum = 0; // Number of cache hits
domain = "www.taobao.com"; // The resolved domain
gobackLocaldnsNum = 0; // Number of fallbacks to local DNS
localErro = 0; // Number of local DNS resolution failures
maxRtt = "60"; // Maximum domain resolution time (ms)
noPermissionErro = 0; // Number of authentication failures
noResponseErro = 0; // Number of no-response errors
requestPDnsNum = 1; // Number of recursive queries
sp = "China Mobile"; // ISP name
successNum = 1; // Number of successful resolutions
timeoutErro = 0; // Number of network timeout errors
type = 28; // IP type: 1 for IPv4, 28 for IPv6
urlParameterErro = 0; // Number of URL parameter format errors
urlPathErro = 0; // Number of URL path errors
}
......
);
Bonnes pratiques pour la résolution de noms de domaine
Combinez la pré-résolution avec la stratégie stale-while-revalidate pour des performances optimales.
La pré-résolution des domaines clés au démarrage permet de remplir le cache afin que les recherches ultérieures évitent les allers-retours réseau, ce qui permet d'obtenir une résolution avec une latence quasi nulle.
Le cache intégré sert ensuite les requêtes suivantes directement depuis la mémoire.
1. Pré-résolution
Activez la mise en cache et pré-résolvez les domaines clés au démarrage de l'application.
Dans la méthode application:didFinishLaunchingWithOptions: de l'objet AppDelegate, pré-résolvez les noms de domaine utilisés par votre application et mettez en cache les résultats dans la mémoire locale.
1. Pour les scénarios IPv4 uniquement
//******** For IPv4-only scenarios *******
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
DNSResolver *resolver = [DNSResolver share];
// setAccountId:@"******": Replace the asterisks with the Account ID from the Access Configuration page in the console.
// andAccessKeyId:@"********": Replace the asterisks with the AccessKey ID of the key that you created on the Access Configuration page.
// andAccesskeySecret:@"********": Replace the asterisks with the AccessKey Secret of the key that you created on the Access Configuration page.
[resolver setAccountId:@"******" andAccessKeyId:@"********" andAccesskeySecret:@"********"];
// Enable caching. Default is YES.
resolver.cacheEnable = YES;
// Pre-resolve IPv4 information for domains that you expect to use later.
[resolver preloadIpv4Domains:@[@"domain1", @"domain2", @"domain3"] complete:^{
// All domains are pre-resolved.
}];
return YES;
}
2. Pour les scénarios IPv6
//******** For dual-stack scenarios that support IPv6 *******
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
DNSResolver *resolver = [DNSResolver share];
// setAccountId:@"******": Replace the asterisks with the Account ID from the Access Configuration page in the console.
// andAccessKeyId:@"********": Replace the asterisks with the AccessKey ID of the key that you created on the Access Configuration page.
// andAccesskeySecret:@"********": Replace the asterisks with the AccessKey Secret of the key that you created on the Access Configuration page.
[resolver setAccountId:@"******" andAccessKeyId:@"********" andAccesskeySecret:@"********"];
// Enable caching. Default is YES.
resolver.cacheEnable = YES;
// Enable domain resolution over IPv6 networks. Default is NO.
resolver.ipv6Enable = YES;
// Enable IP speed test. Default is NO.
resolver.speedTestEnable = YES;
// Pre-resolve domains. This automatically detects the network (IPv4-only, IPv6-only, or dual-stack) and gets a suitable IP.
[resolver preloadDomains:@[@"domain1", @"domain2", @"domain3"] complete:^{
// All domains are pre-resolved.
}];
return YES;
}
2. Autorisez les réponses obsolètes (stale)
Avant d'effectuer une requête réseau, récupérez l'adresse IP depuis le cache en autorisant les enregistrements expirés (andExpiredIPEnabled:YES). Cette approche renvoie un résultat immédiatement tant que le cache est rempli, même si le TTL a expiré, permettant ainsi une résolution sans latence.
1. Pour les scénarios IPv4 uniquement
//******** For IPv4-only scenarios *******
__weak typeof(self) ws = self;
// Prioritize getting the IP from the cache, allowing stale but usable records.
NSArray<NSString *> *cachedIPs = [[DNSResolver share] getIpv4ByCacheWithDomain:domain andExpiredIPEnabled:YES];
if (cachedIPs && cachedIPs.count > 0) {
NSString *ip = cachedIPs.firstObject;
NSLog(@"Fast cache hit. Domain %@ resolved to IP: %@", domain, ip);
[self requestWithIP:ip domain:domain]; // Connect directly using the IP.
} else {
// Cache miss. Perform an asynchronous resolution.
[[DNSResolver share] getIpv4DataWithDomain:domain complete:^(NSArray<NSString *> *resolvedIPs) {
if (resolvedIPs && resolvedIPs.count > 0) {
NSString *ip = resolvedIPs.firstObject;
NSLog(@"Async resolution complete. Domain %@ resolved to IP: %@", domain, ip);
[ws requestWithIP:ip domain:domain]; // Connect directly using the IP.
} else {
NSLog(@"Domain resolution failed. Falling back to original domain.");
[ws requestWithIP:domain domain:domain]; // Fallback: Use the original domain.
}
}];
}
2. Pour les scénarios IPv6
//******** For dual-stack scenarios that support IPv6 *******
__weak typeof(self) ws = self;
// Prioritize getting the IP from the cache, allowing stale but usable records.
NSArray<NSString *> *cachedIPs = [[DNSResolver share] getIpsByCacheWithDomain:domain andExpiredIPEnabled:YES];
if (cachedIPs && cachedIPs.count > 0) {
NSString *ip = cachedIPs.firstObject;
NSLog(@"Fast cache hit. Domain %@ resolved to IP: %@", domain, ip);
[self requestWithIP:ip domain:domain]; // Connect directly using the IP.
} else {
// Cache miss. Perform an asynchronous resolution.
[[DNSResolver share] getIpsDataWithDomain:domain complete:^(NSArray<NSString *> *resolvedIPs) {
if (resolvedIPs && resolvedIPs.count > 0) {
NSString *ip = resolvedIPs.firstObject;
NSLog(@"Async resolution complete. Domain %@ resolved to IP: %@", domain, ip);
[ws requestWithIP:ip domain:domain]; // Connect directly using the IP.
} else {
NSLog(@"Domain resolution failed. Falling back to original domain.");
[ws requestWithIP:domain domain:domain]; // Fallback: Use the original domain.
}
}];
}
Remarques relatives à l'utilisation
Le framework
pdns-sdk-ios.frameworknécessite une version minimale d'iOS 9.0.Lorsque vous effectuez des requêtes via HTTP, vous devez définir
App Transport Security Settings->Allow Arbitrary LoadssurYESdans votre fichierInfo.plist.-
Après avoir résolu une adresse IP à partir de HTTPDNS, définissez l'en-tête HTTP
Hostavec le nom de domaine d'origine lors des requêtes de service.Exemple :
// `ip` is the IP address resolved from the original domain name. NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"https://%@", ip]]; NSMutableURLRequest *mutableReq = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval: 10]; // Set the host. [mutableReq setValue:@"original_domain" forHTTPHeaderField:@"host"]; -
Mettez en œuvre un mécanisme de secours : si le SDK ne renvoie aucune adresse IP, effectuez la requête en utilisant le nom de domaine d'origine.
NSArray *array = [[DNSResolver share] getIpsByCacheWithDomain:@"original_domain" andExpiredIPEnabled:YES]; if (array && array.count > 0 && array.firstObject.length > 0) { // Replace the host in the URL with the IP and make the request. } else { // Implement fallback logic (use the original URL for the request). } En présence d'un proxy HTTP et lorsque vous utilisez HTTPDNS avec une URL basée sur une adresse IP, le proxy transfère l'adresse IP en tant qu'informations d'hôte au lieu du nom d'hôte d'origine. Cela empêche le serveur cible de traiter correctement la requête. Vérifiez si un proxy est activé sur l'appareil. Si votre appareil est en mode proxy, n'utilisez pas HTTPDNS pour la résolution de noms de domaine.
DNS sur site
À partir de la version 2.3.0, le SDK iOS HTTPDNS prend en charge le DNS sur site pour les déploiements privés.
Le DNS sur site convient aux scénarios exigeant une conformité stricte des données et des politiques de résolution personnalisées, tels que les secteurs financier, gouvernemental ou les grandes entreprises. Le SDK prend en charge quatre modes de déploiement : cloud public uniquement, DNS sur site uniquement, et deux modes hybrides principal/secours où le cloud public et le DNS sur site servent de solutions de secours mutuelles.
Fonctionnalités principales
Prise en charge du déploiement privé : configurez les endpoints du serveur DNS sur site à l'aide d'adresses IPv4/IPv6 ou de noms d'hôte.
Authentification mutuelle : utilisez votre
accessKeyIdet votreaccessKeySecretdédiés pour signer les requêtes et sécuriser la communication.Disjoncteur et contrôles d'intégrité : si un nœud DNS sur site échoue trois fois ou plus consécutivement, le disjoncteur se déclenche automatiquement. Ensuite, le système vérifie sa disponibilité chaque minute en utilisant le paramètre
healthCheckDomainspécifié. Le nœud est réactivé automatiquement après sa récupération.Contrôle de la validation des certificats : activez ou désactivez la validation des certificats TLS. Nous recommandons vivement de l'activer dans les environnements de production.
Basculement intelligent : bascule automatiquement vers le DNS de secours lorsque le DNS principal (cloud public ou sur site) atteint un seuil d'échec, garantissant ainsi une haute disponibilité pour la résolution.
Compatibilité API transparente : les appels d'API de résolution restent identiques, que vous utilisiez le DNS du cloud public ou le DNS sur site, sans nécessiter de modifications de votre logique métier.
Exemples de configuration
1. Utiliser uniquement le DNS du cloud public
Ce mode est destiné aux utilisateurs SaaS standard qui n'ont pas déployé de DNS sur site.
DNSResolver *resolver = [DNSResolver share];
[resolver setAccountId:@"******"
andAccessKeyId:@"********"
andAccesskeySecret:@"********"];
2. Utiliser uniquement le DNS sur site (déploiement privé)
Ce mode est destiné aux clients qui s'appuient entièrement sur leur DNS sur site.
DNSResolver *resolver = [DNSResolver share];
[resolver setFusionDNSWithIPv4:@[@"1.1.X.X", @"2.2.X.X"]
IPv6:nil
Host:nil
Port:@"443"
HealthCheckDomain:@"check.example.com"
accessKeyId:@"your_fusion_ak"
accesskeySecret:@"your_fusion_sk"];
// Optional: Disable certificate validation (for test environments only).
// [resolver setEnableCertificateValidation:NO];
3. Cloud public en principal, DNS sur site en secours
Si le HTTPDNS public principal d'Alibaba Cloud échoue, la résolution bascule automatiquement vers le DNS sur site.
DNSResolver *resolver = [DNSResolver share];
// Primary: Public cloud DNS
[resolver setAccountId:@"******"
andAccessKeyId:@"********"
andAccesskeySecret:@"********"];
// Backup: On-premises DNS
[resolver setFusionDNSWithIPv4:@[@"1.1.X.X", @"2.2.X.X"]
IPv6:nil
Host:nil
Port:@"443"
HealthCheckDomain:@"check.example.com"
accessKeyId:@"your_fusion_ak"
accesskeySecret:@"your_fusion_sk"];
// Optional: Disable certificate validation (for test environments only).
// [resolver setEnableCertificateValidation:NO];
4. DNS sur site en principal, cloud public en secours
Si le DNS sur site principal échoue, la résolution bascule automatiquement vers le HTTPDNS public d'Alibaba Cloud.
DNSResolver *resolver = [DNSResolver share];
// Primary: On-premises DNS
[resolver setFusionDNSWithIPv4:@[@"1.1.X.X", @"2.2.X.X"]
IPv6:nil
Host:nil
Port:@"443"
HealthCheckDomain:@"check.example.com"
accessKeyId:@"your_fusion_ak"
accesskeySecret:@"your_fusion_sk"];
// Optional: Disable certificate validation (for test environments only).
// [resolver setEnableCertificateValidation:NO];
// Backup: Public cloud DNS
[resolver setAccountId:@"******"
andAccessKeyId:@"********"
andAccesskeySecret:@"********"];
Nouvelles API de service
Le SDK fournit trois API principales pour la configuration du DNS sur site, le contrôle des politiques de sécurité et le basculement automatique principal/secours.
1. Configuration du DNS sur site
/** This is related to on-premises DNS for private deployments. Do not call this method if you only use public DNS.
*
* Sets the on-premises DNS server address and authentication information.
* Use this interface to pass your private DNS server's address and authentication credentials.
* The SDK will use this information to initiate requests.
* @param ipv4 An array of IPv4 addresses (can be nil).
* @param ipv6 An array of IPv6 addresses (can be nil).
* @param host An array of hostnames (can be nil).
* @param port The service port (for example, @"443"). If nil, the default port is used.
* @param healthCheckDomain The domain for health checks after a circuit break. If a resolution service fails more than three consecutive times, the circuit is tripped, and the service IP enters a healthCheck state. Subsequent requests will not use this service. A timer then probes this healthCheckDomain every minute to check if the service is available. If a probe succeeds, the service state is restored to alive and can receive requests again.
* @param accessKeyId Your private accessKeyId for authentication.
* @param accesskeySecret Your private accesskeySecret for authentication.
*/
- (void)setFusionDNSWithIPv4:(NSArray<NSString *> * _Nullable)ipv4
IPv6:(NSArray<NSString *> * _Nullable)ipv6
Host:(NSArray<NSString *> * _Nullable)host
Port:(NSString * _Nullable)port
HealthCheckDomain:(NSString * _Nonnull)healthCheckDomain
accessKeyId:(NSString * _Nonnull)accessKeyId
accesskeySecret:(NSString * _Nonnull)accesskeySecret;
2. Validation des certificats TLS
/** This is related to on-premises DNS for private deployments. Do not call this method if you only use public DNS.
*
* Enable or disable certificate validation for on-premises DNS. The default is YES. If your server is not configured with a domain or IP certificate, you can set this to NO for testing. For production environments, set this to YES to avoid security risks.
* @param enable YES to enable (default), NO to disable.
*/
- (void)setEnableCertificateValidation:(BOOL)enable;
3. Seuil de basculement automatique
/** When both public cloud DNS and on-premises DNS are configured, this sets the number of primary DNS failures that trigger an automatic failover to the backup DNS. If only one type of DNS is configured, do not call this method.
*
* Sets the number of primary DNS failures before automatically failing over to the backup DNS. If only one type of DNS is configured, do not call this method.
* @param fallbackThreshold The number of failures. The default is 4 when public cloud DNS is primary, and 2 when on-premises DNS is primary.
* The valid range is [0-4]. A value of 0 means failover occurs immediately. The maximum is 4.
*/
- (void)setFallbackThreshold:(NSInteger)fallbackThreshold;