[WCF] Limiter proprement l’accès à vos ressources serveur

Les ressources de nos très chers serveurs ne sont malheureusement pas illimitées (même dans le cloud). Il arrive toujours un moment où l’on doit se rendre à l’évidence. Soit on joue la guerre à l’armement, soit on se raisonne.

Une fois n’est pas coutume, je vais vous proposer une approche raisonnable. Partons sur un exemple simple. Supposons que vous êtes dans le cas où vous avez créé un service WCF qui accède à une ressource présente sur votre serveur (ex : disques durs, sonde de température, dongle USB, base de données). Vous savez très bien qu’au-delà d’un certain nombre d’utilisations simultané de cette ressource, les performances sont dégradées (voire pire, le matériel n’est plus accessible, ou la base de données passe hors ligne).

Votre esprit s’agite, vous voyez déjà deux ou trois solutions se profiler à l’horizon :

  • Sémaphore
  • Verrous attribués temporairement
  • Mécanisme de synchro maison
  • Singleton pour la gestion du nombre de clients entrants.
  • .. etc…

Mais j’arrive avec mes gros sabots et je dis STOP ! Pourquoi réinventer une roue carrée alors que WCF a de quoi gérer ça via ses behaviors ? (OK : en général quand je dis behavior, tout le monde par en courant)

Qui plus est, il n’y a rien à coder !

Le service doit être lié à un behavior disposant d’un paramètre serviceThrottling. Celui-ci dispose d’un attribut très intéressant, le maxConcurrentInstances (comme sont nom l’indique, il limite le nombre d’instances de votre service).

Par exemple, si mon service ne doit pas avoir plus de 10 instances concurrentes :

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <behavior 
        name="behaviorThrottled">
        <!-- Limite le nombre d'instance du service à 10-->
        <serviceThrottling 
          maxConcurrentInstances="10" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <services>
    <service 
      name="WcfService1.Service1"
      behaviorConfiguration="behaviorThrottled">
      <endpoint 
        binding="netTcpBinding"
        contract="WcfService1.IService1" />
    </service>
  </services>
</system.serviceModel>

Si l’envie vous prend, vous pouvez aussi utiliser les attributs maxConcurrentCalls et maxConcurrentSessions qui peuvent être très pratiques pour limiter l’impact sur le serveur lors de la montée en charge de vos services (ou vous protéger contre des attaques DOS).

Jérémy Jeanson

Comments

You have to be logged in to comment this post.