Nouvelles Chroniques d'Amethyste

Penser au Sens, pas au Verbe

Requêter un web site spécifique

Poster un commentaire

Le problème à résoudre est d’écrire un script capable de requêter un web site afin de lui demander de vider son cache. Un tel script peut correspondre à une mise à jour d’une base de données par exemple.

Le problème est que notre web site est derrière un pare feu et que le nombre de site est dynamiquement réajusté en fonction de la charge.
Alors comment faire?

Si on regarde les cookies une fois connecté à un web service on observe ceci:

2015-02-22_21-49-17

Un cookie appelé ARRAffinity est ajouté par Azure avec ce qui ressemble fort à un ID. Il s’agit de l’identifiant unique attribué à chaque instance de web api. Ce cookie permet au load balancer de faire de l’affinité de session.

Donc si on peut obtenir la liste des ID attribué à notre web site, il suffirait de les balayer avec notre requête afin de vider les caches de façon déterministe.

On a plusieurs façons de faire les choses.

Si le script est destiné à fonctionner dans l’environnement du site, un web job par exemple, on peut obtenir cette valeur en interrogeant la variable d’environnement WEB_INSTANCE_ID:

var environments = Environment.GetEnvironmentVariables();
String ID = environments["WEBSITE_INSTANCE_ID"];

Il est possible également que le script se situe sur un autre serveur qui n’a rien à voir. Ce n’est pas compliqué à faire, mais il y a un peu plus de travail. On va mettre en œuvre deux méthodes.

Dans tous les cas on aura besoin de quelques informations:

  •  Un ID d’abonnement
  •  Un certificat

Pour les obtenir le moyen le plus simple est de demander à la personne qui gère le portail (il fait être admin). Si c’est vous vous devez juste récupérer le fichier publishing comme indiqué ici:

https://amethyste16.wordpress.com/2014/07/15/charger-le-publishsettingsfile-dans-la-console-powershell/

Les infos sont dedans.
Un certificat est donc sérialisé en base 64 dans une chaîne qui commence par MII…  On devra pouvoir le désérialiser, une méthode comme celle-ci fera le boulot:

 

using System.Security.Cryptography.X509Certificates;

private static X509Certificate2 GetCredentials(string idAbonnement, string certificatEncode64)
{
    Byte[] certificate = Convert.FromBase64String(certificatEncode64);
    return new X509Certificate2(certificate);
}

On obtient la liste des instances ID d’un site web en lançant la requête suivante:

GET /
https://management.core.windows.net/<ID_ABONNEMENT>/services/WebSpaces/<WEBSPACENAME>/sites/<WEBSITE>/instanceids

On n’oublie pas le https.

  •   ID_ABONNEMENT est l’id de l’abonnement.
  • Le WEBSPACENAME dépend de la localisation du data center et du groupe de ressources. Je ne suis pas arrivé à trouver une doc complète qui indique comment il est formé et le portail ne donne pas l’info.

Voici un script Powershell qui récupère la liste des websites de votre abonnement et affiche le webspace correspondant:

$a = @{Expression={$_.Name};Label= »Web site »}, `
@{Expression={$_.Webspace};Label= »Web space »}

$instances = Get-AzureWebsite
$instances | Format-Table $a

2015-03-06_14-32-31

On devra également passer le header x-ms-version avec la valeur 2014-04-01:
https://msdn.microsoft.com/en-us/library/azure/dd894041.aspx
Finalement, le code pourrait ressembler à:

string url = "https://management.core.windows.net/.......";

WebRequest webRequest = WebRequest.Create(url);
webRequest.Method = "GET";
webRequest.Headers.Add("x-ms-version", "2014-04-01");
webRequest.ContentType = "application/json";

// https, il nous faut un certificat
X509Certificate2 credentials = GetCertificate(cacheDumpInfo.Certificate);
((HttpWebRequest)webRequest).Credentials = CredentialCache.DefaultCredentials;
((HttpWebRequest)webRequest).ClientCertificates.Add(credentials);

List<string> ids = new List<string>();
using (WebResponse webResponse = webRequest.GetResponse())
{
    using (StreamReader streamReader = new StreamReader(webResponse.GetResponseStream()))
    {
        string json = streamReader.ReadToEnd().Trim();
        ids = JsonConvert.DeserializeObject<List<string>>(json);
    }
}

Puis on lance la boucle de requête en direction du Web Site:

 

foreach (string id in ids)
{
    Uri uri = new Uri(urlWebService);
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    request.Method = "DELETE";

    request.CookieContainer = new CookieContainer();
    request.CookieContainer.Add(uri, new Cookie("ARRAffinity", instanceId));

    HttpWebResponse reponse = (HttpWebResponse)request.GetResponse();
}

Si votre projet est en .NET 4.5 ou bien une version supérieure, on peut simplifier les choses à l’aide d’un SDK Nuget:

https://www.nuget.org/packages/Microsoft.WindowsAzure.Management.Libraries

La classe <strong>WebSiteManagementClient</strong> nous permet d'interroger avec une Api objet Azure. On obtient la liste des instances avec ce code:

X509Certificate2 certificate = GetCertificate(cacheDumpInfo.Certificate);
SubscriptionCloudCredentials credentials = new CertificateCloudCredentials(idAbonnement,certificate);

WebSiteManagementClient client = new WebSiteManagementClient(credentials);
WebSiteInstanceIdsResponse instanceIds = client.WebSites.GetInstanceIds(webspace, website);

IList<string> ids = instanceIds.InstanceIds; // liste des id d'instance

La suite est identique au cas précédent.

 

Depuis j’ai rédigé un article complet sur la prise en compte des certificats sous Azure qui présente une autre façon de faire. C’est ici:

https://amethyste16.wordpress.com/2015/03/07/fournir-ses-credentials-aux-services-azure/
Bibliographie

 

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s