Highlight
Apple Maps 一直以来都是客户端为中心的生态——MapKit 负责 iOS 端,MapKit JS 负责 Web 端,但服务端一直是空白。如果你想在后端做地理编码或者搜索周边商家,要么自己调 Google Maps API,要么在客户端做这些操作然后忍受大量的网络请求。
核心内容
做一个门店定位功能,最容易被低估的是“拼卡片”这一步。客户端先向业务服务器要门店地址,再用 MapKit 或 MapKit JS 把地址转成坐标,接着计算用户到门店的距离,最后把每个响应合并成一张联系卡片。网络好时只是多等一会儿;蜂窝网络延迟高时,每一次独立请求都增加失败和不完整响应的概率。
这场 session 把问题缩小到一个漫画书店 locator。屏幕上只需要三张卡片:门店地址、用户当前位置、距离。没有服务端地图 API 时,客户端必须和业务后端、Apple Maps 服务来回通信,还要在本地合并结果。用户看到的是 spinner,设备付出的是带宽和电量。
Apple 在 WWDC22 补上了 Apple Maps Server APIs。它提供四类服务端能力:Geocoding、Reverse Geocoding、Search、Estimated Time of Arrival(ETA)。业务服务器可以作为网关,先完成地址解析、ETA 计算和业务数据拼装,再把最适合 UI 展示的结果一次返回给客户端。
这样改完后,客户端只需要向自己的服务器发一次请求。后端负责把漫画书店地址交给 Geocode API,拿到经纬度后再交给 ETA API,最后把距离和门店营业时间等自有数据合并。MapKit、MapKit JS 和 Apple Maps Server APIs 形成同一套 Apple Maps stack,客户端保留展示能力,重复、可缓存、易聚合的工作移到服务端。
详细内容
四个服务端 API 解决四类地图问题
(01:01)Apple Maps Server APIs 首次包含四个 API:Geocoding、Reverse Geocoding、Search 和 ETA。它们覆盖从地址解析到到达时间估算的基础地图工作流。
Geocoding: 地址 -> latitude / longitude
Reverse Geocoding: latitude / longitude -> 地址
Search: 搜索字符串 -> business / point of interest 等地点
ETA: origin + destination -> 每个 destination 的 estimated time of arrival / distanceMeters
关键点:
- Geocoding 把门店地址转换成 latitude 和 longitude,后续计算都依赖这两个值。
- Reverse Geocoding 走反向路径,适合把用户选中的坐标还原成地址。
- Search 允许用户输入查询字符串,发现商家、兴趣点等地点。
- ETA 接收 origin 和 destination,返回每个目的地对应的 ETA;session 的示例用
distanceMeters计算到店距离。
把客户端的多次请求收束到后端网关
(03:41)没有 Apple Maps Server APIs 时,客户端拿到门店地址后还要继续调用地图能力。session 明确指出,这种 client 与 back end 之间的 chattiness 会影响性能和扩展性;在高延迟蜂窝网络上,独立请求还可能造成连接中断或 incomplete requests。
旧流程:
Client -> Business Server: 请求门店地址列表
Business Server -> Client: 返回地址
Client -> Apple Maps service: 为每个地址做地图相关请求
Client: 等待多个响应,并在本地合并
新流程:
Client -> Business Server: 请求可展示的门店列表
Business Server -> Apple Maps Server APIs: Geocoding / ETA 等请求
Business Server: 合并地图响应和自有门店信息
Business Server -> Client: 返回 UI 可直接使用的数据
关键点:
- 新流程没有让客户端直接编排多个地图请求。
- 业务服务器可以把重复地址查询“只在后端做一次”,减少不同设备上的重复请求。
- 后端返回的是更接近 UI 的结果,客户端少做网络等待和响应合并。
- 这正是 session 中“reduce network calls”和“power efficient”的来源:带宽与处理从用户设备转移到了服务器。
门店 locator:先 Geocode,再 ETA
(06:16)示例功能用 Geocoding 和 ETA 算出用户到门店的距离。第一步先 URL encode 漫画书店地址,把它作为 Geocode API 的 query parameter。响应里包含 latitude 和 longitude。用户地址也做同样处理。
1. URL encode comic book store address
2. Call Geocode API with the encoded address as a query parameter
3. Read latitude and longitude from the response
4. Repeat the same process for the customer address
5. Pass origin and destination query parameters to ETA API
6. Read distanceMeters from the ETA response
关键点:
- session 没有给出具体 endpoint 路径,所以这里保留为调用顺序,不虚构 URL。
- Geocode API 的输出是 ETA API 的输入:门店坐标和用户坐标分别成为 destination 与 origin。
- ETA API 可以指定最多 10 个 destinations,适合一次比较多家门店。
- 示例只传一个 destination,因此响应里只有一个 ETA;实际 locator 可以把多个门店批量放入同一次计算。
- 业务服务器还能把结果和自有信息合并,例如门店营业时间。
鉴权:Maps auth token 换 30 分钟 access token
(08:29)所有 Apple Maps Server APIs 都需要鉴权。它使用和 MapKit JS 相同的机制:先从开发者账号下载 private key,用它生成 JWT 格式的 Maps auth token,再调用 token API 换取 Maps access token。
Private key from developer account
-> generate Maps auth token (JWT)
-> call token API with Maps auth token in a header
-> receive Maps access token (JWT)
-> use Maps access token in Apple Maps Server API calls
-> refresh every 30 minutes
关键点:
- Maps auth token 和 Maps access token 是两个不同的 token。
- Maps auth token 用来交换 access token,不直接代表后续所有 API 调用都已完成授权。
- Maps access token 是 JWT,响应里包含 expiry、issuedAt 和
expiresInSeconds等字段。 - session 明确说 access token 每 30 分钟刷新一次;后端应负责刷新,不要把 private key 下发给客户端。
配额和 429:把失败路径也设计出来
(10:47)Apple Maps Server APIs 每天共有 25,000 次 service calls 配额,并且和 MapKit JS service usage 共享。Maps developer dashboard 会把 server API usage 归类到 Services。
Daily quota: 25,000 service calls
Shared with: MapKit JS service usage
Quota exceeded: HTTP 429 Too Many Requests
Retry strategy: exponential backoff, not a tight retry loop
关键点:
- 如果超过每日配额,新 service calls 会被拒绝,并返回 HTTP 429。
- 异常流量也可能触发 429,例如代码或基础设施 bug 导致请求量异常。
- 收到 429 后不要循环重试;session 建议使用 exponential backoff,逐次拉长重试间隔。
- 门店 locator 的后端应该在 429 时返回可降级的数据,例如只展示地址和营业时间,稍后再补充距离。
核心启发
-
做什么:把门店 locator 的地址解析和距离计算移到后端。
为什么值得做:session 的漫画书店示例说明,后端可以用 Geocode API 和 ETA API 合并地图响应,客户端只收一次业务响应。
怎么开始:后端先对门店地址和用户地址做 URL encode,再调用 Geocoding;拿到坐标后调用 ETA,并把distanceMeters写入门店卡片数据。 -
做什么:为地图搜索结果增加业务数据 overlay。
为什么值得做:Search API 能返回商家和兴趣点,session 也提到可以 overlay your own data。
怎么开始:在后端把 Search 结果和自有数据库中的营业时间、库存、会员权益做匹配,再返回给 MapKit 或 MapKit JS 展示。 -
做什么:给常见地址查询做服务端缓存。
为什么值得做:Apple 特别指出,不同用户设备反复 lookup 同一个地址会造成重复请求和带宽浪费。
怎么开始:以规范化地址作为缓存 key,缓存 Geocoding 的 latitude / longitude;ETA 保留实时调用,因为它和用户 origin 相关。 -
做什么:为 Apple Maps Server APIs 做配额仪表盘和降级策略。
为什么值得做:服务端 API 每日 25,000 次配额与 MapKit JS 共享,超过后会返回 429。
怎么开始:定期查看 Maps developer dashboard 的 Services 使用量;后端捕获 429 后使用 exponential backoff,并返回不含距离的门店列表作为兜底。 -
做什么:把 token 刷新封装成后端基础能力。
为什么值得做:Maps access token 每 30 分钟过期,多个地图 API 共用同一套鉴权流程。
怎么开始:后端保存 private key,只在服务器生成 Maps auth token;用 token API 换 access token,并在expiresInSeconds结束前刷新。
关联 Session
- What’s new in MapKit — 客户端地图展示和交互的更新,和 Apple Maps Server APIs 组成完整地图架构。
- Meet WeatherKit — 同属 Maps & Location 的服务型数据 API,可和位置、路线、门店场景结合。
- Reduce networking delays for a more responsive app — 深入网络延迟对响应性的影响,解释为什么减少客户端请求数能改善体验。
- Q&A: Maps technologies — 围绕 MapKit、MapKit JS、Apple Maps Server APIs 的工程答疑入口。
评论
GitHub Issues · utterances