10

Python プロジェクトで App Engine モジュールを使用しています。( https://developers.google.com/appengine/docs/python/modules/#Python_Background_threads )

m プロジェクトでもチャネルを使用しています: https://developers.google.com/appengine/docs/python/channel/

接続/切断されたポスト メッセージ ('/_ah/channel/connected/'、'/_ah/channel/disconnected/') を API モジュールに送信したいと考えています。現在、それらをどのモジュールにも表示できません(デフォルトまたはAPI)

app.yaml

    api_version: 1
    application: integrate
    version: 1-0-0
    runtime: python27
    threadsafe: true

    builtins:
      - deferred: on

    libraries:
      - name: pycrypto
      version: "2.6"

    handlers:
      - url: /favicon\.ico
      static_files: static/favicon.ico
      upload: static/favicon\.ico

      - url: /admin/.+
      script: src.default.main.app
      login: admin

      - url: /.*
      script: src.default.main.app

api.yaml

    api_version: 1
    application: integrate
    module: api
    version: 1-0-0
    runtime: python27
    threadsafe: true

    inbound_services:
      - channel_presence

    builtins:
      - deferred: on

    libraries:
      - name: pycrypto
      version: "2.6"

    handlers:
      - url: /admin/.+
      script: src.api.main.app
      login: admin

      - url: /.*
      script: src.api.main.app

ディスパッチ.yaml

    application: integrate

    dispatch:
       - url: "*/_ah/channel/*"
       module: api

注: 明確にするために、これはすべてローカルで dev モードで動作します。

api.main.app

    app = webapp2.WSGIApplication(debug=True)
    _routes = [
        :
        ChannelDisconnectedHandler.mapping(),
        ChannelConnectHandler.mapping()
    ]

    for r in self._routes:
        app.router.add(r)

ChannelDisconnectHandler

    CHANNEL_DISCONNECTED_URL_PATTERN = '/_ah/channel/disconnected/'


    class ChannelDisconnectedHandler(RequestHandler):

        @classmethod
        def mapping(cls):
            return CHANNEL_DISCONNECTED_URL_PATTERN, cls

        def post(self):
            """
            Channel Presence handler. Will be called when a client disconnects.
            """
            channel_id = self.request.get('from')
            logging.info("Channel Disconnect. Id: %s" % channel_id)

ChannelConnectHandler

    CHANNEL_CONNECT_URL_PATTERN = '/_ah/channel/connected/'

    class ChannelConnectHandler(RequestHandler):

        @classmethod
        def mapping(cls):
            return CHANNEL_CONNECT_URL_PATTERN, cls

        def post(self):
            """
            Channel Presence handler. Will be called when a client connects.
            """
            channel_id = self.request.get('from')
            logging.info("Channel Connect. Id: %s" % channel_id)

したがって、クライアント (javascript で記述) は API モジュールに投稿し、チャネルを開きます。

    var open_channel = function(tokenResponse) {
        console.log("Open Channel. token Response: " + tokenResponse)
        token = tokenResponse.token;
        var channel = new goog.appengine.Channel(token);
        if (socket != null) {
            socket.close();
        }
        socket = channel.open();
        socket.onopen = onOpened;
        socket.onmessage = onMessage;
        socket.onerror = onError;
        socket.onclose = onClose;
    };

    onOpened = function() {
        console.info("Channel API Connection is open.");
    };

    onError = function(e) {
        console.info("CHANNEL Error. Code: " + e.code + ", Description: " + e.description);
    };

    onClose = function() {
        console.info("Close Channel");
    };

    onMessage = function(msg) {
       console.info("Message Received: " + msg + ", Data: " + msg.data);
    };

このコールバック関数は、有効なトークンで到達します。ソケットを正常に作成し、この関数を期待どおりに完了します。次に、ローカル システムで onOpened 関数が呼び出され、サーバーからメッセージを受信します。実稼働環境では onOpened が呼び出されることはなく、メッセージを受信することもありません。/_ah/channel/connected/ も呼び出されません。

チャネル サービスはモジュールでサポートされていませんか? 私が欠けているものについて何か考えはありますか?

4

3 に答える 3

6

Googleエンタープライズサポートによると(生の回答からわずかに変更されています):

  1. channel_presenceで受信サービスを有効にする必要がありますapp.yaml

    inbound_services:
    - channel_presence
    

    モジュールの yaml ファイル (たとえば、api.yamlこの質問) でこのインバウンド サービスを有効にしても、このサービスは有効になりません。

  2. で始まる URL パス*/_ahはディスパッチ可能なパスではなく、 でルーティングできませんdispatch.yaml。そのため、channel_presenceURL パス ハンドラは に記述する必要がありますapp.yaml

    handlers:
    - url: /_ah/channel/connected/
      script: mymodule.application
    
于 2014-10-29T04:40:05.973 に答える
0

モジュールでChannel APIを使用する際にも問題が発生し、リクエストをモジュールにリダイレクトすることで、Emilが言及したのと同様のトリックを使用して問題を回避しようとしました.

ただし、実際には 3 つのモジュールがあり、そのうち 2 つがチャネル API を使用し、1 つが「フロントエンド」であったため、セットアップは少し複雑でした。このようなもの:

  • モジュールフロントエンド (デフォルト)
  • モジュール serviceA (チャネル api 1 を使用)
  • モジュール serviceB (チャネル API 2 を使用)

フロントエンドで 2 つの別々のサービスからの「通知」を聞くことができるようにしたかったのです。

そして、私が(開発で)それを回避する方法は、各サービスにプレフィックスを付けたトークンを読み取り、各サービスにリダイレクトするリダイレクトをフロントエンドに追加することでした。

「すごい、うまくいく!」と思ったのですが、App Engine にデプロイしようとしたときに、Channel API によって内部的に使用される talkgadget エンドポイントが特定のソース アプリを予期しているように見えたため、クロスドメイン通信を許可しなかったため、そこにはさらに多くの機能があることに気付きました。

そのため、モジュールの代わりに複数のプロジェクトを使用し、クロスドメインの問題を回避するために HTML iframe の「postMessage ブリッジ」を配置することになりました。嬉しいことに、これは非常にうまく機能し、副作用として、2 倍の「無料」チャンネルを使用できるようになりました。

これに関連する問題をここで見つけました。追跡すると興味深いかもしれません: https://code.google.com/p/googleappengine/issues/detail?id=10293

于 2014-11-13T09:17:59.943 に答える