Outils pour utilisateurs

Outils du site


perspective_broker

Python: Twisted Perspective Broker

Niveau Pro et intergalactique !

Introduction Perspective Broker

Traduction Google de Introduction to Perspective Broker améliorée par un humain !

Introduction

Supposons que vous vous retrouviez dans le contrôle des deux extrémités du fil: vous avez deux programmes qui doivent se parler et vous pouvez utiliser n'importe quel protocole. Si vous pouvez penser à votre problème en termes d'objets nécessitant des appels de méthode, il est alors probable que vous puissiez utiliser le protocole Perspective Broker de Twisted plutôt que d'essayer d'intégrer vos besoins dans HTTP, ou encore d'implémenter un autre RPC. mécanisme.

Le système Perspective Broker (en abrégé «PB») repose sur quelques concepts centraux:

  • serialization = sérialisation : prendre des objets et des types assez arbitraires, les transformer en un bloc d'octets, les envoyer sur un fil, puis les reconstituer à l'autre extrémité. En surveillant attentivement les identifiants d'objet, les objets sérialisés peuvent contenir des références à d'autres objets et la copie distante sera toujours utile.
  • remote method calls = ppels de méthode distants : faire quelque chose sur un objet local et provoquer l'exécution d'une méthode distante. L'objet local est appelé RemoteReference et vous «faites quelque chose» en exécutant sa méthode .callRemote .

Ce document contiendra plusieurs exemples qui sembleront redondants et verbeux une fois que vous aurez compris ce qui se passe. Pour commencer, une grande partie du code sera simplement étiquetée «magic»: ne vous inquiétez pas du fonctionnement de ces pièces. Il sera expliqué plus en détail plus tard.

Feuille de route de l'objet

Pour commencer, voici les principales classes, interfaces et fonctions impliquées dans PB, avec des liens vers le fichier où elles sont définies (qui sont toutes sous twisted bien sûr). Ne vous souciez pas de comprendre ce qu'ils font tous encore: il est plus facile de les comprendre grâce à leur interaction que de les expliquer un par un.

Autres classes impliquées à un moment donné:

  • RemoteReference : spread/pb.py
  • pb.Root : spread/pb.py , défini comme twisted.spread.flavors.Root dans spread/flavors.py
  • pb.Referenceable : spread/pb.py , défini comme twisted.spread.flavors.Referenceable dans spread/flavors.py

Classes et interfaces impliquées lorsque vous commencez à vous soucier de l'autorisation et de la sécurité:

  • Portal : cred/portal.py
  • IRealm : cred/portal.py
  • IPerspective : spread/pb.py , avec lequel vous interagirez généralement via pb.Avatar (un implémenteur de base de l'interface).

Sous-classement et mise en œuvre

Techniquement, vous pouvez sous-classer tout ce que vous voulez, mais techniquement, vous pouvez aussi écrire un tout nouveau framework, ce qui vous fera perdre beaucoup de temps. Connaître les classes utiles à la sous-classe ou les interfaces à implémenter est l'une des connaissances essentielles à la réussite de l'utilisation de PB (et de Twisted). Voici quelques conseils pour commencer:

  • pb.Root , pb.Referenceable : vous les sous- classez pour créer des objets à distance référençable (c.-à-d. des objets sur lesquels vous pouvez appeler des méthodes à distance) en utilisant PB. Vous n'avez pas besoin de modifier le comportement existant, il vous suffit d'en hériter et d'ajouter les méthodes accessibles à distance que vous souhaitez exporter.
  • pb.Avatar : Vous serez en train de sous - classer cela lorsque vous entrerez dans la programmation PB avec autorisation. Ceci est un implémenteur de IPerspective.
  • ICredentialsChecker : Implémentez ceci si vous souhaitez authentifier vos utilisateurs contre une sorte de magasin de données: par exemple, une base de données LDAP, un SGBDR, etc. Il existe déjà quelques implémentations pour différents back-end dans twisted.cred.checkers.

Les choses que vous pouvez appeler à distance

À cette écriture, il existe trois «saveurs» d’objets accessibles à distance via des objets RemoteReference . Chacune de ces variantes possède une règle sur la manière dont le message callRemote est transformé en appel de méthode local sur le serveur. Pour utiliser l'une de ces «saveurs», sous-classez-les et nommez vos méthodes publiées avec le préfixe approprié.

C'est la première interface avec laquelle nous traitons. C'est une «perspective» sur votre application PB. Les perspectives sont un peu spéciales car elles sont généralement le premier objet auquel un utilisateur donné peut accéder dans votre application (après sa connexion). Un utilisateur ne devrait recevoir qu'une référence à sa propre perspective. PB s'efforce de vérifier, autant que faire se peut, que toute méthode pouvant être appelée directement dans une perspective est appelée au nom de l'utilisateur représenté par cette perspective. (Les services avec des exigences inhabituelles pour «pour le compte de», telles que les simulations avec la possibilité de posséder l'avatar d'un autre joueur, sont réalisés en fournissant un accès indirect au point de vue d'un autre utilisateur.)

Les perspectives ne sont généralement pas sérialisées en tant que références distantes. Ne renvoyez donc pas directement un exécuteur IPerspective.

La façon dont la plupart des gens voudront implémenter IPerspective est de sous-classer pb.Avatar. Les méthodes accessibles à distance sur les instances pb.Avatar sont nommées avec le préfixe perspective_ .

Les objets référençables sont le type d'objet PB le plus simple. Vous pouvez appeler des méthodes sur ces méthodes et les renvoyer à partir de méthodes permettant d'accéder aux méthodes des autres objets.

Cependant, lorsqu'une méthode est appelée sur un objet référençable, il n'est pas possible de dire qui l'a appelée.

Les méthodes accessibles à distance sur les référenceables sont nommées avec le préfixe remote_ .

Les objets visualisables sont des objets pouvant être référencés à distance et qui nécessitent en outre la possibilité de savoir qui les appelle. La liste d'arguments des méthodes distantes d'une Viewable est modifiée afin d'inclure la perspective représentant l'utilisateur appelant.

Les méthodes accessibles à distance sur les affichages sont nommées avec le préfixe view_ .

Les choses que vous pouvez copier à distance

En plus de renvoyer des objets sur lesquels vous pouvez appeler des méthodes distantes, vous pouvez renvoyer des copies structurées d'objets locaux.

Deux variantes de base permettent de copier des objets à distance. Encore une fois, vous pouvez les utiliser en les sous-classant. Afin de spécifier l'état que vous souhaitez copier lorsque ceux-ci sont sérialisés, vous pouvez soit utiliser le

__getstate__

ou méthode spécialisée par défaut de Python pour cette saveur.

C'est le type d'objet le plus simple qui peut être copié. Chaque fois que cet objet est renvoyé par une méthode ou transmis en tant qu'argument, il est sérialisé et dé-sérialisé.

Copyable fournit une méthode que vous pouvez remplacer, getStateToCopyFor(perspective) , qui vous permet de décider à quoi un objet va ressembler pour la perspective qui le demande. L'argument perspective sera la perspective qui transmet un argument ou renvoie un résultat, une instance de votre classe Copyable.

Pour des raisons de sécurité, afin de permettre la copie d'une classe Copyable particulière, vous devez déclarer un gestionnaire RemoteCopy pour cette sous-classe Copyable. Le moyen le plus simple est de déclarer les deux dans le même module, comme ceci:

from twisted.spread import flavors
 
class Foo(flavors.Copyable):
    pass
 
class RemoteFoo (flavors.RemoteCopy):
    pass
 
flavors.setUnjellyableForClass(Foo, RemoteFoo)

Dans ce cas, chaque fois qu'un Foo est copié entre pairs, un RemoteFoo sera instancié et rempli avec l'état de Foo. Si vous ne le faites pas, PB se plaindra qu'il y a eu des violations de la sécurité, et la connexion pourrait être fermée.

Permettez-moi de commencer par un avertissement: Cacheable peut être difficile à comprendre. La motivation à cela peut ne pas être claire si vous n'avez pas d'expérience avec les applications du monde réel qui utilisent des méthodes d'appels à distance. Une fois que vous avez compris pourquoi vous en avez besoin, ce que vous faites peut paraître simple et évident, mais si vous vous trompez, oubliez-le et revenez plus tard. Il est possible d'utiliser PB sans comprendre Cacheable du tout.

Cacheable est une saveur conçue pour être copiée uniquement lorsque cela est nécessaire et mise à jour à la volée au fur et à mesure des modifications. Lorsqu'elle est transmise en tant qu'argument ou valeur de retour, si une mise en cache existe du côté de la connexion sur laquelle elle est copiée, elle sera appelée par ID et non copiée.

Cacheable est conçu pour minimiser les erreurs liées à la réplication d'un objet entre plusieurs serveurs, en particulier ceux liés aux informations obsolètes. Pour ce faire, Cacheable enregistre automatiquement les états des observateurs et des requêtes, ensemble. Vous pouvez remplacer la méthode getStateToCacheAndObserveFor(self, perspective, observer) afin de spécifier comment vos observateurs seront stockés et mis à jour.

Semblable à getStateToCopyFor , getStateToCacheAndObserveFor reçoit une perspective. Il reçoit également un observer , qui est une référence distante à une quatrième version référençable «secrète»: RemoteCache .

Un RemoteCache est simplement l'objet qui représente votre Cacheable de l'autre côté de la connexion. Il est enregistré en utilisant la même méthode que RemoteCopy , ci-dessus. RemoteCache est différent, cependant, car il sera référencé par son homologue. Il agit en tant que référenceur, où toutes les méthodes préfixées par observe_ seront appelables à distance. Il est recommandé à votre objet de maintenir une liste d'observateurs (note: support de la bibliothèque à venir!) Et de les mettre à jour à l'aide de callRemote lorsque la mise en callRemote modifie de manière à être perceptible par ses clients.

Enfin, lorsque toutes les références à un Cacheable depuis une perspective donnée sont perdues, stoppedObserving(perspective, observer) sera appelé sur Cacheable, avec la même paire perspective / observateur avec laquelle getStateToCacheAndObserveFor a été initialement appelé. Tous les appels distants de nettoyage peuvent être effectués à cet endroit, tout comme la suppression de l'objet observateur de toutes les listes dans lesquelles il se trouvait auparavant. Tout appel supplémentaire à cet objet observateur sera invalide.

Des exemples

Bon là, je ne comprends pas, c'est de l'intergalactique!

Exemple 1

pb1client.py
#!/usr/bin/env python3
 
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
 
 
from twisted.spread import pb
from twisted.internet import reactor
 
def main():
    factory = pb.PBClientFactory()
    reactor.connectTCP("localhost", 8800, factory)
    def1 = factory.getRootObject()
    def1.addCallbacks(got_obj1, err_obj1)
    reactor.run()
 
def err_obj1(reason):
    print("error getting first object", reason)
    reactor.stop()
 
def got_obj1(obj1):
    print("got first object:", obj1)
    print("asking it to getTwo")
    def2 = obj1.callRemote("getTwo")
    def2.addCallbacks(got_obj2)
 
def got_obj2(obj2):
    print("got second object:", obj2)
    print("telling it to do three(12)")
    obj2.callRemote("three", 12)
 
main()
pb1server.py
#!/usr/bin/env python3
 
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
 
from twisted.spread import pb
 
class Two(pb.Referenceable):
    def remote_three(self, arg):
        print("Two.three was given", arg)
 
class One(pb.Root):
    def remote_getTwo(self):
        two = Two()
        print("returning a Two called", two)
        return two
 
from twisted.internet import reactor
reactor.listenTCP(8800, pb.PBServerFactory(One()))
reactor.run()
Lancement du serveur $ python3 pb1server.py 
returning a Two called <__main__.Two object at 0x7fd4aacfb128>
Two.three was given 12
 
Lancement du client $ python3 pb1client.py 
got first object: <twisted.spread.pb.RemoteReference object at 0x7f00e4c76a90>
asking it to getTwo
got second object: <twisted.spread.pb.RemoteReference object at 0x7f00e4c76b00>
telling it to do three(12)
perspective_broker.txt · Dernière modification: 2018/10/18 14:57 par serge