【问题标题】:App Engine Python Modules and channel serviceApp Engine Python 模块和渠道服务
【发布时间】:2013-10-10 09:06:33
【问题描述】:

我在我的 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

dispatch.yaml

    application: integrate

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

注意:为了清楚起见,这一切都在本地开发模式下工作。

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/ 也永远不会被调用。

模块不支持频道服务吗?关于我缺少什么的任何想法?

【问题讨论】:

    标签: google-app-engine python-2.7 module channel-api gae-module


    【解决方案1】:

    您必须为连接和断开 URL 声明一个 hadler 路由。

    main.py 中的处理程序路由:

    application = webapp2.WSGIApplication([
        ...
        # Define a URL routing for /_ah/channel/connected/
        webapp2.Route(r'/_ah/channel/connected/',
                      handler=ChannelConnectedHandler,
                      name='channel_connected')
    
    ], debug=True, config=webapp2_config)
    
    
    # Implement class handler of /_ah/channel/connected/
    class ChannelConnectedHandler(webapp2.RequestHandler):
        def post(self):
            client_id = self.request.get('from')
            logging.info('client %s has connected!' % client_id)
            ...
    

    【讨论】:

    • 感谢您的回答,但恐怕这不是这里的问题。我没有在这里发布代码,但我确实添加了路线。如果我没有,它将无法在开发模式下工作。
    【解决方案2】:

    根据谷歌企业支持(根据他们的原始答案稍作修改):

    1. channel_presence 入站服务必须在app.yaml 中启用。

      inbound_services:
      - channel_presence
      

      在模块的 yaml 文件中启用此入站服务(例如,此问题中的 api.yaml)不会启用此服务。

    2. */_ah 开头的URL 路径不是可调度的路径,并且不能被dispatch.yaml 路由。因此,channel_presence URL 路径处理程序必须在 app.yaml 中描述。

      handlers:
      - url: /_ah/channel/connected/
        script: mymodule.application
      

    【讨论】:

    • 这里 golang 的正确行是什么:script: mymodule.application?
    • mattes- 我认为该行与语言无关,但 Emil- 我也希望能对它的工作原理进行更多解释
    • 有关app.yaml 的更多信息,请参阅它的语言特定文档。对于 Go,相关版本在这里cloud.google.com/appengine/docs/go/config/appconfig
    【解决方案3】:

    我也遇到了在模块中使用 Channel API 的问题,我尝试使用 Emil 提到的类似技巧,通过将请求重定向到模块来解决这些问题。

    这是一个稍微复杂的设置,因为我实际上有 3 个模块,其中 2 个使用 Channel API,一个是“前端”。像这样的:

    • 模块前端(默认)
    • 模块 serviceA(使用通道 api 1)
    • 模块 serviceB(使用通道 api 2)

    我希望能够在前端收听来自两个独立服务的“通知”。

    我设法解决这个问题的方法(在开发中)是将重定向添加到前端,该前端读取我在每个服务上添加前缀的令牌并重定向到每个服务。

    “太好了,它有效!”我想,但是当我尝试部署到应用程序引擎时,我意识到那里还有更多内容,因为 Channel API 内部使用的talkgadget端点似乎期望某个源应用程序,因此不允许跨域通信。

    所以我最终使用了多个项目而不是模块,并通过放置一个 HTML iframe“postMessage 桥”来解决跨域问题。很高兴它真的很好用,而且作为副作用,我可以使用两倍的“免费”频道。

    我在这里发现了一个与此相关的问题,您可能会感兴趣,可以跟踪:https://code.google.com/p/googleappengine/issues/detail?id=10293

    【讨论】:

      猜你喜欢
      • 2016-10-09
      • 1970-01-01
      • 2013-06-12
      • 2011-12-30
      • 2016-09-29
      • 2020-12-13
      • 1970-01-01
      • 2014-05-27
      • 1970-01-01
      相关资源
      最近更新 更多