App Engine Python 模块和渠道服务



我正在我的python项目中使用App Engine Modules。(https://developers.google.com/appengine/docs/python/modules/#Python_Background_threads(

我也在 m 项目中使用频道:https://developers.google.com/appengine/docs/python/channel/

我想将已连接/断开连接的帖子消息("/_ah/通道/已连接/"、"/_ah/通道/断开连接/"(定向到我的 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)

通道断开连接处理程序

    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)

通道连接处理程序

    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);
    };

此回调函数使用有效令牌访问。我成功创建了套接字并按预期完成了此功能。在我的本地系统上,然后调用 onOpen 函数,我从服务器接收消息。在生产中,打开永远不会被调用,我永远不会收到任何消息。/_ah/channel/connected/也永远不会被调用。

模块不支持通道服务吗?关于我错过了什么的任何想法?

根据谷歌企业支持(根据他们的原始答案略有修改(:

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

    inbound_services:
    - channel_presence
    

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

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

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

您必须为连接和取消链接 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)
        ...

我也遇到了在模块中使用通道 API 的问题,我试图使用与 Emil 提到的类似的技巧来解决它们,方法是将请求重定向到模块。

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

  • 模块前端(默认(
  • 模块服务 A(使用通道 API 1(
  • 模块服务B(使用通道 API 2(

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

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

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

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

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

相关内容

  • 没有找到相关文章

最新更新