优化请求

和风天气会根据你的请求,通过API或SDK的方式向你提供天气服务,在这一过程中,需要尽量优化你的请求,以便更高效的使用我们的服务,这篇文档将介绍几种常见的优化方式。

为了更有效的使用和风天气开发服务,你需要尽量优化你的请求。这篇文档将介绍几种常见的优化方式。

构建合法的URL

当你使用API获取数据的时候,会通过URL向我们发起请求,例如:

https://abcxyz.qweatherapi.com/v7/weather/3d?parameters

一般来说,这段请求URL不会出现错误,但是在传递一些特殊的参数和值的时候需要特别注意:

特殊字符

根据 RFC 3986 URI 标准,URL 中除英文字母、数字和部分非预留字符(- _ . ~)外,其他字符在请求参数值中都必须进行 URL 编码(URL encoding)或称之为百分号编码(Percent-encoding),以确保请求能被正确解析和传输。

请求参数中无需编码的字符:

  • 英文字母:A-Z, a-z
  • 数字:0-9
  • 非预留字符:- _ . ~

请求参数必须编码的字符:

  • 空格,请编码为%20,不建议使用 +,例如 new york ➡️ new%20york
  • 中文或其他非 ASCII 字符,例如 北京 ➡️ %E5%8C%97%E4%BA%AC
  • 英文逗号,作为保留字符通常无需编码,但为了确保兼容所有服务器和客户端的解析行为,强烈建议也将其进行 URL编码,避免歧义:color=blue,red ➡️ color=blue%2Cred
  • 上述无需编码字符列表以外的字符

无效的空格

请求URL中还需要注意那些无效的空格,这种情况常见于复制粘贴操作。例如,当复制一段 Token 时,可能会在其前后不小心夹带空格。粘贴后应仔细检查并手动删除这些空格,否则可能导致请求 URL 格式错误,或传递的参数不正确,进而影响接口的正常访问。

中文符号混用

在使用允许的特殊字符时,请注意不要与对应的中文符号混淆。例如,查询参数的起始符应使用英文问号?,而不是中文问号。符号混用可能导致请求解析失败或行为异常。

安全的请求

请不要共享完整的请求URL,这有可能泄露你的敏感信息,使用HTTPS、JWT身份认证等方式发送安全的API请求。关于如果保护API安全,请参考安全指南

处理错误

当你的请求返回错误码时,你需要暂停请求并妥善的处理这些错误,否则这些错误可能看起来像DDoS攻击,我们的安全策略将冻结你的帐号。

例如: 当你传入了错误的参数或KEY,将返回400403,此时你应该暂停这一次的请求,排除故障后再继续。否则当程序不断重试而产生大量失败的请求时,这违反了我们的许可协议且被视为一种攻击,我们将中止你的服务并冻结你的帐号。

了解状态码

请参考错误码

使用指数退避算法处理错误

当出现错误的时候,请停止请求并进行检查,待故障排除后再恢复请求。然而一些错误并非由于请求不符合规范而导致的,例如超过每分钟请求限制,没有足够的余额等等,这时你应该使用指数退避算法优化请求。

例如,当你的请求收到429状态码时,代表你超过了每分钟请求次数,此时你应该在下次请求开始前添加x秒的等待期。如果下次请求仍然返回429,则将等待期延长一倍,再发送另一次请求,以此类推,继续延长等待期,直至不再返回错误状态码。

简单的公式可以参考:

t = bc

其中t代表下次请求的间隔时间,或称之为等待期,b代表基数,c是发生错误的次数。如果按照上述的例子来讲,假设b = 2,那么在出现第一次错误时,下一次请求应该等待21 = 2秒,再下一次请求应等待22 = 4秒,第三次请求等待23 = 8秒,如果第四次请求响应正常,则恢复之前的请求频率并重置c = 1

避免冲突

如果你有大量独立设备发送请求,为了避免这些设备产生了相同的等待期而产生冲突(比如都在等待2秒后重新发送,这并不能恢复QPM),你可以在等待期中设置一个随机数,或称之为插槽,这个随机数的取值范围可以是0~2c-1。在上述例子中,前三次的等待期的随机数分别是:

  • 第一次:0, 1
  • 第二次:0, 1, 2, 3
  • 第三次:0, 1, 2, 3, 4, 5, 6, 7

这样你的多个独立设备每次都有不同的等待期而避免了冲突。

截断

等待期不应是无限的,如果连续出现20次错误,那么此时的等待期就已经长达291个小时,这显然是不现实的。因此你需要为等待期设置一个最大值,当达到这个值时,则不再增加c的取值。我们的建议是c = 10

按需请求

仅在需要天气数据的时候再进行请求。

例如:在APP中,天气内容的位置较为靠下,你可以让程序在用户滑动到天气内容部分再进行请求。

如果已经加载了天气内容,你也可以为这个内容设置缓存时间,或者增加一个刷新按钮,让用户手动去刷新数据。关于设置缓存,请参考缓存你的数据