我们如何才能弄清楚为什么我们偶尔会收到 401 错误谷歌 c2dm推送服务AWS要求 c2dm 发送通知时的情况?
这是一个暂时性问题。所有 AWS 实例在向 Google c2dm 发送 HTTPS 请求时大多能成功,有些实例 100% 成功,有些实例偶尔会收到 401 错误。因此,我们认为这不是我们 c2dm 注册或已投入生产一年多的通知代码 (python) 的问题。401 错误始于 2012 年 5 月 16 日。
相反,我们认为亚马逊基础设施中的某些内容(包括 DNS 缓存)可能在某种程度上与该问题有关。Google 友好地回复了我们的询问,称:
我会寻找可能导致通信不稳定的原因。尝试查看该机器的网络适配器上是否出现了异常数量的损坏或丢失的数据包。
但是,我们没有看到任何“不稳定通信”的证据。当问题发生时,实例上的 CPU 负载几乎为 0,并且问题机器上的以太网连接数平均低于没有问题的实例。
一个线索是 401 错误似乎成群出现(几个错误在 4 分钟内相继出现),并且这些错误群通常间隔 10 到 60 分钟(尽管可能有许多小时没有错误)。我们没有看到 I/O 错误或“不稳定通信”错误,只有来自 Google c2dm 的 401 错误。
Aserverfault 帖子让我们考虑 AWS 上的 DNS 缓存,因为它与 Google c2dm 服务提供的证书中的主机名的 SSL 验证有关,但似乎我们使用的 python 2.7 urllib2 默认并不验证主机。
另一个线索是,我们使用“弹性 IP”功能更改了出现问题的第一个 Web 实例的 IP 地址:同一个持续运行的实例,只是换了一个新 IP。该实例在 4 天内 100% 成功,但此后又偶尔出现 401 错误。
我们能做什么来阐明这一点?
堆栈跟踪示例:
c2dm push error: HTTP Error 401: Unauthorized
Traceback (most recent call last):
File "/home/django/base/src/mmsite/push/models.py",
line 262, in send_c2dm_message
response = urllib2.urlopen(request) # third try
File "/usr/local/lib/python2.7/urllib2.py",
line 126, in urlopen
return _opener.open(url, data, timeout)
File "/usr/local/lib/python2.7/urllib2.py",
line 400, in open
response = meth(req, response)
File "/usr/local/lib/python2.7/urllib2.py",
line 513, in http_response 'http', request, response, code, msg, hdrs)
File "/usr/local/lib/python2.7/urllib2.py",
line 438, in error
return self._call_chain(*args)
File "/usr/local/lib/python2.7/urllib2.py",
line 372, in _call_chain
result = func(*args)
File "/usr/local/lib/python2.7/urllib2.py",
line 521, in http_error_default
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
HTTPError: HTTP Error 401: Unauthorized
401 回复中返回的 HTTP 标头示例:
'headers': [
'Content-Type: text/html; charset=UTF-8\r\n', 'Date: Fri, 25 May 2012 00:24:25 GMT\r\n',
'Expires: Fri, 25 May 2012 00:24:25 GMT\r\n', 'Cache-Control: private, max-age=0\r\n',
'X-Content-Type-Options: nosniff\r\n', 'X-Frame-Options: SAMEORIGIN\r\n',
'X-XSS-Protection: 1; mode=block\r\n', 'Server: GSE\r\n', 'Connection: close\r\n']
编辑其他测试信息:
我们能够在开发网络上重现这个瞬态 401。有时它可以正常工作,有时它会得到 401。由于开发网络与 AWS 完全分开,这消除了我们考虑的有关 AWS 的所有变量,并增加了问题出在 Google 方面的理论的可信度。Google 友好地回复说他们会上报这个问题。
答案1
这个问题通过更改 auth 密钥(通过 URL 请求 c2dm 服务获取新密钥,然后立即将其放入我们的服务器端推送代码中)解决了。当密钥对大多数 c2dm 推送都正常工作时,我们不愿意这样做,但看起来有些 Google 服务器对密钥不满意,导致我们出现间歇性错误。自从一周前更改它以来,我们一直没有出现错误。