Twistedを使用したXMPPパブリッシュ/サブスクライブの実装

良い一日! この記事では、 TwistedWokkelライブラリーを使用して、XMPPプロトコルを使用て基本的なパブリッシュ/サブスクライブ実装を作成する方法について説明します。 XMPPはXEP-0060拡張のおかげでpub / subをサポートします。 pub / subを使用すると、イベントおよびその他多くの参加者すべてに通知する問題を解決できます。 Appleが通知サーバー内でWokkelベースのpub / subを使用していることは確実に知られていますが、それについては後で詳しく説明します。


パブリッシュ/サブスクライブする理由


プロジェクトの開発時に、次のタスクが発生しました。クライアントがサーバーに保存されたデータを使用してアクションを実行するクライアントサーバーアーキテクチャを構築することです。 データはパブリックドメインにあり、クライアントがデータの最新バージョンに基づいて行動する必要があります。 システムの仕組みを少し説明します。 クライアントはサービスにサブスクライブします。 サービスに加入すると、クライアントはサーバーに保存されているすべてのデータを受け取ります。 クライアントはサーバーにデータを送信します。 サーバーは送信されたデータを保存し、すべてのサブスクライバーに転送します。 サブスクライバーは、データの整合性が侵害されていることを発見した場合、サーバーにデータの転送などを依頼します。

ツール


ソリューションは、XMPPとその拡張機能XEP-0060を使用する形で見つかりました。 XMPPが選ばれたのは、その人気と豊富な機能のためです。 Twistedは、Pythonで最も強力なネットワークフレームワークの1つとして選択されました。 Twisted.wordsには基本的なxmppプロトコルのサポートがありますが、残念ながらpub / sub拡張機能のサポートはありません。 Wokkelは、Twistedにpub / subサポートを追加するライブラリーと見なされました。 Wokkelはpub / subだけでなく、( service discovery )およびその他の便利な拡張機能もサポートしています。


Wokkelライブラリの操作方法を示す小さな例を作成してみましょう。 サービスを提供し、顧客はサービスの更新を購読します。 クライアントは5秒ごとにメッセージを生成し、サーバーに送信します。 サーバーは、購読しているすべての参加者にメッセージを送信します。 始めましょう。

まず、サービスであるXMPPClientクラスのオブジェクトを作成する必要があります(Twisted用語)。 彼は、Jabberサーバーの認証と接続管理を担当しています。 PubSubClientまたはPubSubServiceクラスのオブジェクトは、pub / subプロトコルレベルで対話する機能を提供します。 プロトコルとサービスが相互にやり取りできるように、setHandlerParentを呼び出します。 サービスを開始します。 プロトコルは、pub / subに関連するメッセージのスレッドのリッスンを開始し、上記のメッセージを受信すると、対応するハンドラーを呼び出します。 次のステップは、Serviceクラスの実装を検討することです。

def main
ログ。 startLogging sys。stdout
オプション、args = parse_args
jid、resource、password = args
サービス=オプション。 奉仕
fulljid = jabber。 jidinternJID jid + '/' +リソース
transport = XMPPClient fulljid、password
輸送。 logTraffic = True
protocol = Client jabber。jid。internJID service if service else Service
プロトコル。 setHandlerParent transport
輸送。 startService
リアクター。 実行


この場合、pub / subサービスのタスクは単純です。サブスクライバーからメッセージを受信し、他のすべてのサブスクライバーに送信します。 クライアントは、サブスクリプション要求を送信することにより、サービスとの対話を開始します。 サービスは、サブスクライブ要求が到着したことを認識するとすぐに、サブスクライブメソッドを呼び出します。 このメソッドでは、クライアントに関連付けられたサブスクリプションを作成し、コールバックで返す必要があります。 アクセスモデルを実装せず、誰でも購読できると考えています。 サブスクライバーがデータを送信すると、publishメソッドが呼び出されます。 sendDataメソッドでは、サービスにサブスクライブしている全員に着信データを送信します。 次に、クライアントの検討に移ります。

クラスサービス PubSubService
def __init__ self
PubSubService。 __init__ self
self ._subscriptions = { }

def publish self 、requestor、service、nodeIdentifier、items
自己sendData items
延期を返します。 成功 なし

def subscribe self 、requestor、service、nodeIdentifier、subscriber
自己 ._subscriptionsのサブスクライバーの場合
info = self ._subscriptions [購読者]
その他
info =サブスクリプション NODE_NAME、サブスクライバー、 'subscribed'
self ._subscriptions [ subscriber ] = info
延期を返します。 成功 情報

def sendData self 、items
sendList = [ ]
セルフ ._subscriptionsのサブスクリプション。
sendList。 追加 [ subscription。subscriber、 None 、items ]
自己notifyPublish self。parent。jid 、NODE_NAME、sendList


クライアントを作成するとき、私たちは彼に彼が購読するサービスのアドレスを与えます。 サービス(XMPPClient)がjabberサーバーで許可され、接続が確立されると、connectionInitializedメソッドがサービス(XMPPClient)に接続されているすべてのプロトコルで呼び出されます。 接続が確立された直後に、必要なサービスのサブスクリプションがサブスクライブされるようにします。 サブスクリプションが正常に完了した後、4秒ごとに発生するイベントを開始し、サービスにメッセージを生成して送信します。 転送されるデータは、適切にフォーマットされたXMLである必要があります。 実際にはそれだけです。

クラス Client PubSubClient
def __init__ self 、service
PubSubClient。 __init__ self
self .__ service = service

def connectionInitialized self
PubSubClient。 connectionInitialized self
d = self サブスクライブ self .__ service、NODE_NAME、 self。parent。jid
d。 addCallback lambda success: task。LoopingCall sendGeneratedData、 self
d。 addCallback lambda lc: lc。start 5 、now = True

def itemsReceived self 、event
イベントのアイテム。 アイテム
ログ。 msg item。getAttribute 'sender' + 'sends' +
アイテム。 getAttribute 'message' + 'at' + item。 getAttribute 'time'

def sendData self 、items
自己発行 self .__サービス、NODE_NAME、アイテム

def sendGeneratedData プロトコル
element = Element None'item'
要素。 属性 [ '送信者' ] =プロトコル。 jidフル
要素。 属性 [ 'time' ] =時間。 strftime "%H:%M:%S" 、時間。localtime
要素。 属性 [ 'メッセージ' ] = 'こんにちは!'
プロトコル。 sendData [ element ]


ここでソースコードを見る
操作を確認するには、次のものが必要です。
サーバーの開始: pubsub.py test@example.comサーバーのパスワード
2つのクライアントを実行します: pubsub.py --service test@example.com/server test@example.com client1 password
pubsub.py --service test@example.com/server test@example.com client2 password

Appleはそれと何をしなければなりませんか?


これまでに行ったのは、何百ものpub / sub機能の1つを示す例です。 仕様に目を向けると、設定がpersistItems = False deliveryPayloads = Trueで、所属、検出、他のノードの作成の可能性をサポートしないオープンアクセスモデルで、リーフノードのタイプに対応していることがわかります。 pub / sub仕様全体または必要な部分を実装するのがどれほど難しいか想像してみてください。 しかし、wokkelの作者であるRalph Meijerはタスクを単純化し、 Idavollを書きました。 IdavollはWokkelのアドオンです。 XEP-0060をほぼ完全にサポートし、http経由で通信する機能があります。 Idavollは、Appleが通知サーバーとして使用します。 この事実はここで確認できます

おわりに


Twistedを学ぶには、公式ドキュメントとkrondo.com/?page_id=1327をお勧めします
残念ながら、Wokkelに関する情報はほとんどありませんが、Idavollに関する情報はまったくないため、生成されたドキュメントのみが残ります。
学習に成功しました!

Source: https://habr.com/ru/post/J111681/


All Articles