3

私が取り組んでいるdjangoアプリケーションの場合、2つの方法でRPCを実装する必要があります:

  • クライアントはプラットフォームから RPC メソッドを呼び出すことができ、
  • プラットフォームは、各クライアントから RPC メソッドを呼び出すことができます。

クライアントはほとんどが NAT の背後にあるため (つまり、パブリック IP がなく、予測不可能な奇妙なファイアウォール ポリシーが適用されます)、プラットフォームからクライアントへの方法はクライアントが開始する必要があります。

これを最初から書く方法についてはかなり良い考えがあります。ツイストのパブリッシャー/サブスクライバー モデルから何かを作ることもできると思いますが、Python でそれを行う最善の方法が常にあることを学びました。

だから私はそれを行うための最良の方法は何だろうと思っています.djangoにも最適です。コードは、短期的には数百のクライアントに対応できる必要があり、中長期的には数千のクライアントに対応できる必要があります。

では、どのライブラリ/実装を使用するようアドバイスしてくれますか? 私は主に RTFM の出発点を探しています!

4

4 に答える 4

7

websocket は常に新しい仕様が追加されており、変化するターゲットです。勇敢な開発者はサーバー側のライブラリを実装していますが、クライアント側を実装している人はほとんどいません。Web ソケットのクライアントは Web ブラウザーです。

websocket は、サーバーがクライアントと対話する唯一の方法ではありません。イベント ソースは、情報をクライアントにプッシュするためのシンプルで実用的な方法です。それは終わりのないページです。Twitter 消防ホースは、その仕様の前にこのトリックを使用します。クライアントは http 接続を開き、イベントを待ちます。接続は開いたままにしておき、何らかの問題 (接続の切断など) があれば再開します。タイムアウトなし。1 回の接続で多くのイベントを送信できます。

websocket と eventsource の違いは単純です。Websocket は双方向であり、実装が困難です。Eventsource は単方向であり、クライアント側とサーバー側の両方で簡単に実装できます。

eventsource をゾンビ コントローラーとして使用できます。各クライアントはマスターに接続して再接続し、指示を待ちます。命令が受信されると、ゾンビが動作し、必要に応じて、従来の http 接続を使用して、django アプリをターゲットにして、そのマスターと通信できます。

Eventsource は接続を開いたままにするため、トルネードのような非同期サーバーが必要です。Django には同期サーバーが必要なので、nginx などのディスパッチャと両方が必要です。Django または cron のようなアクションは、適切なゾンビと対話する非同期サーバーと対話します。Zombie は django と対話するため、非同期サーバーはペリスタンスを必要とせず、ゾンビがプラグインされたハブにすぎません。

Gevent はそのような http サーバーを処理できますが、この点に関する適切なドキュメントと例はありません。それは残念だ。私は車が欲しい、あなたは私にネジをくれます。

于 2012-05-23T16:55:29.523 に答える
2

Tornado + Tornadio + Socket.ioも使用できます。これが現在通知に使用しているものであり、作成する必要があるコードの量はそれほど多くありません。

from tornadio2 import SocketConnection, TornadioRouter, SocketServer
class RouterConnection(SocketConnection):
__endpoints__ = {'/chat': ChatConnection,
                 '/ping': PingConnection,
                 '/notification' : NotificationConnection
                 }

def on_open(self, info):
    print 'Router', repr(info)

MyRouter = TornadioRouter(RouterConnection)

# Create socket application
application = web.Application(
MyRouter.apply_routes([(r"/", IndexHandler),
    (r"/socket.io.js", SocketIOHandler)]),
        flash_policy_port = 843,
        flash_policy_file = op.join(ROOT, 'flashpolicy.xml'),
        socket_io_port = 3001,
        template_path=os.path.join(os.path.dirname(__file__), "templates/notification")
)

class PingConnection(SocketConnection):
     def on_open(self, info):
       print 'Ping', repr(info)

     def on_message(self, message):
       now = dt.utcnow()
       message['server'] = [now.hour, now.minute, now.second, now.microsecond / 1000]
       self.send(message)
class ChatConnection(SocketConnection):
   participants = set()
   unique_id = 0

   @classmethod
   def get_username(cls):
       cls.unique_id += 1
       return 'User%d' % cls.unique_id

   def on_open(self, info):
       print 'Chat', repr(info)

       # Give user unique ID
       self.user_name = self.get_username()
       self.participants.add(self)

   def on_message(self, message):
       pass

   def on_close(self):
       self.participants.remove(self)

   def broadcast(self, msg):
       for p in self.participants:
            p.send(msg)
于 2012-05-23T22:05:48.593 に答える
1

私は最近、Django、Server-Sent Events、および WebSocket で遊んでおり、http://curella.org/blog/2012/jul/17/django-push-using-server-sentで記事を書いています。 -events-and-websocket/

もちろん、これには通常、Django がイベント処理に最適ではないという通常の注意事項が伴います。また、両方のプロトコルはまだドラフト段階です。

于 2012-07-18T16:22:51.150 に答える
1

ここに私が思いついた本当に簡単な解決策があります:

import tornado.ioloop
import tornado.web
import time

class MainHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous 
    def get(self):
        self.set_header("Content-Type", "text/event-stream")
        self.set_header("Cache-Control", "no-cache")
        self.write("Hello, world")
        self.flush()
        for i in range(0, 5):
            msg = "%d<br>" % i
            self.write("%s\r\n" % msg) # content
            self.flush()
            time.sleep(5)


application = tornado.web.Application([
    (r"/", MainHandler),
])

if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

curl http://localhost:8888

来たら出力します!

ここで、完全なイベント ソースの仕様と、サーバーとクライアントの間のある種のデータ シリアライゼーションを実装する必要がありますが、それは簡単なことです。完成したら、ここに書くライブラリに URL を投稿します。

于 2012-05-23T17:46:30.137 に答える