很多团队第一次接入天气数据时,会把它当成一个展示型功能:页面上显示晴天、多云、温度和风力,用户看一眼即可。但在物流、出行、本地生活和线下运营系统里,天气数据更常见的价值,是成为业务判断的一类输入。暴雨会影响配送 ETA,强风会影响户外服务,连续高温会影响门店排班,气象预警会影响活动执行和客服话术。
如果天气接口只是前端页面上的一个小组件,系统能获得的信息价值很有限。更可维护的做法,是把天气数据放进后端的规则链路:先把城市、区域和时间窗口标准化,再查询天气数据,再生成内部的 weather_context,最后由 ETA 引擎、通知中心、运营后台和客服系统消费同一份上下文。
本文以物流 ETA 和运营预警为主线,梳理天气 API 在生产系统中的接入位置、数据流、字段设计、缓存降级、重试、错误码、监控和成本治理。重点不是把接口调通,而是让天气数据能稳定进入业务动作。
物流系统里,用户真正关心的不是“今天是否下雨”,而是订单是否还能按时送达、是否需要提前提醒、客服是否要解释时效变化。运营系统里,团队关心的是某个城市未来 24 小时是否有高影响天气,是否需要调整排班、库存、活动策略或服务范围。
因此,天气能力应该回答三个问题:第一,当前区域的天气是否会影响业务;第二,影响程度应该映射成什么风险等级;第三,风险等级触发哪些系统动作。只展示天气字段不会自动解决这些问题,系统需要把气象数据翻译成业务规则。
后端统一封装天气查询,业务系统消费标准化 weather_context,避免页面、订单、通知和运营后台各自调用第三方接口。
这套架构的关键,是让天气服务层成为内部能力,而不是让每个页面和任务各自接接口。订单系统只关心某个区域在某个时间窗口内的风险等级,通知系统只关心是否要触发提醒,运营后台只关心哪些城市需要处理。第三方 API 的参数、鉴权、错误码和字段差异,都应该收敛在天气服务层。
一个典型数据流可以拆成六步。第一步,订单或运营任务传入城市、区县、网点或经纬度。第二步,位置归一化服务把这些输入映射成内部 location_id。第三步,天气服务按 location_id 和时间窗口查询实时天气、未来预报和预警信息。第四步,规则引擎把降雨、风力、温度、能见度和预警等级映射为业务风险。第五步,把结果写入 weather_context。第六步,ETA、通知和运营系统按风险等级执行动作。
order_or_operation_task
-> normalize_location(city, district, station, lng, lat)
-> query_weather(location_id, time_window)
-> map_weather_risk(weather_fields)
-> save_weather_context(order_id, location_id, risk_level)
-> eta_engine / notification_center / operation_alert这个流程里,天气 API 位于第三步。它不直接决定是否延迟配送,也不直接决定是否推送消息;它负责提供结构化天气数据,内部规则再把数据转成业务动作。这样职责边界更清楚,也更容易做灰度和回滚。
生产系统里不建议让订单、门店、行程和通知模块直接依赖第三方接口的原始字段。更稳妥的做法,是定义内部 weather_context。它既保留必要天气字段,也保留调用来源、缓存命中、过期时间和风险等级,方便后续排查。
CREATE TABLE weather_context (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
biz_type VARCHAR(32) NOT NULL,
biz_id VARCHAR(64) NOT NULL,
location_id VARCHAR(64) NOT NULL,
city VARCHAR(64) NOT NULL,
weather_time DATETIME NOT NULL,
condition_text VARCHAR(64) NULL,
temperature DECIMAL(5,2) NULL,
wind_level VARCHAR(32) NULL,
precipitation_level VARCHAR(32) NULL,
alert_level VARCHAR(32) NULL,
risk_level VARCHAR(32) NOT NULL,
source VARCHAR(32) NOT NULL,
cache_hit TINYINT DEFAULT 0,
expires_at DATETIME NOT NULL,
created_at DATETIME NOT NULL,
INDEX idx_location_time (location_id, weather_time),
INDEX idx_biz (biz_type, biz_id)
);这里的核心字段是 risk_level。温度、风力、降雨和预警等级是气象字段,risk_level 是业务字段。业务系统真正消费的通常是 risk_level、expires_at 和说明文案,而不是每次都重新理解原始天气。
天气会影响 ETA,但它不应该成为唯一判断条件。物流 ETA 还要结合距离、仓库节点、承运商、历史履约、路况、节假日、骑手密度和订单类型。天气字段更适合作为一类影响因子,调整风险权重或时间窗口。
function mapWeatherRisk(weather) {
let score = 0;
if (weather.alertLevel === 'red') score += 50;
if (weather.alertLevel === 'orange') score += 35;
if (weather.precipitationLevel === 'heavy') score += 25;
if (Number(weather.windScale) >= 7) score += 20;
if (Number(weather.temperature) >= 38) score += 15;
if (score >= 60) return 'severe';
if (score >= 35) return 'medium';
if (score >= 15) return 'light';
return 'normal';
}
function adjustEtaMinutes(baseEtaMinutes, riskLevel) {
const extraMinutes = {
normal: 0,
light: 10,
medium: 25,
severe: 45
};
return baseEtaMinutes + (extraMinutes[riskLevel] || 0);
}这段逻辑不代表所有业务都应该使用同一套阈值。城市配送、干线物流、到店服务和出行产品的容忍度不同,风险映射必须结合自己的履约模型。稳定的工程做法是让阈值可配置、动作可回滚、规则命中可审计。
天气数据很适合缓存。实时天气可以按城市或区县缓存 5 到 15 分钟,多日预报可以缓存 30 到 60 分钟,预警信息可以设置更短 TTL 并由后台任务定期刷新。高频业务不要按用户维度缓存,也不要让用户每次打开页面都穿透到第三方接口。
降级策略要提前设计。天气接口超时时,订单详情页应该继续展示主体信息;ETA 引擎可以使用最近一次有效 weather_context,并把 stale 标记传给监控;运营后台可以展示数据更新时间和降级状态;通知系统在无法确认风险时,应避免重复发送高打扰提醒。
async function getWeatherContext(input) {
const cacheKey = `weather:${input.locationId}:${input.window}`;
const cached = await cache.get(cacheKey);
if (cached && !cached.expired) {
return { ...cached.value, cacheHit: true };
}
try {
const weather = await weatherApi.query(input, { timeoutMs: 1200 });
const context = normalizeWeatherContext(weather, input);
await cache.set(cacheKey, context, context.ttlSeconds);
return { ...context, cacheHit: false };
} catch (err) {
const stale = await cache.getStale(cacheKey);
if (stale) return { ...stale.value, stale: true };
return createEmptyWeatherContext(input, err.code);
}
}重试也要克制。天气查询属于外部 API 调用,适合短超时、有限重试和异步补偿,不适合在同步链路里长时间阻塞。对 ETA 这类体验链路来说,快速返回一个带置信度的结果,通常比长时间等待外部接口更稳定。
天气接口上线后,监控不要只看 HTTP 是否 200。至少要看调用量、超时率、错误码分布、缓存命中率、空字段率、降级次数、按城市的失败率、单位订单调用次数和单日成本。字段空值尤其容易被忽略:接口返回成功,但关键字段为空,业务规则仍然可能误判。
weather_api_requests_total
weather_api_latency_ms
weather_api_error_code_count
weather_context_cache_hit_ratio
weather_context_stale_total
weather_required_field_empty_total
weather_cost_per_order
weather_alert_trigger_total错误码治理的目标是让调用方知道下一步该怎么做。参数错误要返回可修正提示,鉴权失败要触发高优先级告警,超时要走缓存或降级,额度不足要通知运营和技术负责人,字段缺失要记录样本并进入质量观察。
天气 API 的成本治理核心不是简单减少调用,而是避免无效调用。热门城市可以后台预热,低频城市按需查询;已完成订单不再刷新天气;同一网点和时间窗口内的订单共享 weather_context;运营后台按城市维度聚合展示,不要按每一条订单重复查。
对物流 ETA 来说,可以把天气调用成本摊到区域和批次上,而不是每个订单独立调用一次。比如同一城市、同一配送站、未来 2 小时的订单,可以复用同一份 weather_context。这样既能保持业务判断一致,也能显著降低重复调用。
如果团队正在评估可用于生产系统的天气数据源,可以把第三方接口统一放到 weather-service 或 data-adapter 层。华霆数联的实时天气预报服务提供标准 RESTful API,适合以服务端统一封装的方式接入物流 ETA、出行提醒和运营预警链路。服务页可参考:实时天气预报 API。
需要注意的是,API 只提供上游数据能力。最终能否提升履约体验,取决于内部是否建立了位置归一化、天气上下文、风险等级、缓存降级、调用监控和成本治理。把这些工程能力做好后,天气数据才会从“页面信息”变成“业务系统的一类稳定输入”。
适合纯展示页面,但 Key 暴露、缓存和审计都难处理。
每个系统独立接入,短期灵活,长期会出现字段和错误码重复治理。
由统一服务处理鉴权、缓存、降级、字段标准化和成本监控。
[ ] API Key 只保存在服务端环境变量或密钥系统
[ ] 城市、区县、网点和经纬度已做统一 location_id
[ ] 第三方返回已转换为内部 weather_context
[ ] 实时天气、预报和预警分别设置缓存 TTL
[ ] 接口超时不会阻塞订单详情页和核心交易链路
[ ] stale 数据、空上下文和错误码都有明确标记
[ ] ETA 调整规则可配置、可审计、可回滚
[ ] 调用量、失败率、缓存命中率和单位订单成本可观测总结一下,天气 API 的价值不在于展示一个图标,而在于它能不能被稳定地转化成业务上下文。对物流 ETA 和运营预警来说,最重要的是统一封装、标准字段、缓存降级、错误码治理、监控告警和成本治理。只要这些工程环节成立,天气数据就能自然进入高频业务,而不是停留在页面装饰。
如果你准备把天气数据接进物流 ETA、出行提醒或运营预警,建议采用服务端统一封装,并按生产链路设计缓存、降级、监控和成本治理。