8

我需要制作需要经常轮询服务器的应用程序,但 GAE 对请求有限制,因此发出大量请求可能会非常昂贵。是否可以使用长轮询并使请求等待最多 30 秒进行更改?

4

3 回答 3

10

Google AppEngine 有一个新的特性 Channel API,你有可能构建一个好的实时应用程序

另一种解决方案是使用第三方彗星服务器,如 mochiweb 或使用 iframe 模式扭曲。

Client1,等待事件:

client1 --Iframe Pattern--> Erlang/Mochiweb(HttpLongPolling):

Client2,发送消息:

client2 --XhrIo--> AppEngine --UrlFetch--> Erlang/Mochiweb

为了将 mochiweb 与彗星模式一起使用,Richard Jones 写了一个很好的主题(在 google 上:Richard Jones A Million-user Comet Application)。

于 2010-09-01T08:52:54.363 回答
2

我们尝试在 App Engine 上实施类似 Comet 的长轮询解决方案,但结果好坏参半。

def wait_for_update(request, blob):
    """
    Wait for blob update, if wait option specified in query string.
    Otherwise, return 304 Not Modified.
    """
    wait = request.GET.get('wait', '')
    if not wait.isdigit():
        return blob
    start = time.time()
    deadline = start + int(wait)
    original_sha1 = blob.sha1
    try:
        while time.time() < deadline:
            # Sleep one or two seconds.
            elapsed = time.time() - start
            time.sleep(1 if elapsed < 7 else 2)
            # Try to read updated blob from memcache.
            logging.info("Checking memcache for blob update after %.1fs",
                         elapsed)
            blob = Blob.cache_get_by_key_name(request.key_name)
            # Detect changes.
            if blob is None or blob.sha1 != original_sha1:
                break
    except DeadlineExceededError:
        logging.info("Caught DeadlineExceededError after %.1fs",
                     time.time() - start)
    return blob

我看到的问题是,长轮询请求之后的请求在长轮询请求之后被序列化(同步)​​。我可以在 Chrome 中查看跟踪,然后看到这样的时间线:

  1. 请求 1 已发送。GET(未修改)blob(等到更改)。
  2. 请求 2 已发送。修改 blob。
  3. 完全超时后,请求 1 返回(数据未修改)。
  4. 请求 2 在服务器上得到处理,并返回成功。

我使用了 wireshark 和 Chrome/timeline 来确认我正在通过与长轮询不同的 TCP 连接向服务器发送修改请求。所以这种同步必须发生在 App Engine 生产服务器上。据我所知,谷歌没有记录服务器行为的这个细节。

我认为等待通道 API 是我们从 App Engine 获得良好实时行为的最大希望。

于 2010-11-30T00:06:02.033 回答
1

我认为长时间轮询是不可能的。google appengine 的默认请求超时时间为 30 秒。在长轮询中,如果消息的生成时间超过 30 秒,那么它将失败。使用短轮询可能会更好。

另一种方法是在 30 秒限制内“模拟”长轮询。要做到这一点,如果消息在 20 秒内没有到达,服务器可以发送“令牌”消息而不是普通消息,要求客户端使用它并再次连接。

google appengine 上似乎有功能请求(及其接受)进行长轮询

于 2010-09-01T08:18:12.183 回答