fix(map): rate limit station reverse geocoding
This commit is contained in:
@@ -10,3 +10,5 @@ AMAP_REGEOCODE_KEY=replace-with-amap-web-service-key
|
||||
# 行政区结果按坐标落盘缓存 7 天,避免每次刷新重复调用高德。
|
||||
STATION_GEOCODE_CACHE_SECONDS=604800
|
||||
STATION_GEOCODE_CACHE_PATH=/opt/lingniu-vehicle-map/cache/station-geocode.json
|
||||
# 高德 Web 服务常见 QPS 配额较低;全局限速以避免冷缓存时触发 10021。
|
||||
AMAP_REGEOCODE_MIN_INTERVAL_SECONDS=0.25
|
||||
|
||||
@@ -32,7 +32,7 @@ python3 server.py
|
||||
- `POST /api/v1/vehicles/mileage/query`:全部授权车辆当日里程;
|
||||
- `POST /api/v1/hydrogen-stations/query`:资产库只读加氢站地图点位。
|
||||
|
||||
以上三个接口均使用开放平台的 `Authorization: Bearer <AppKey>` 鉴权。生产 AppKey 仅保存在 ECS 的 `/opt/lingniu-vehicle-map/env/vehicle-map.env`,文件权限为 `root:vehicle-map 0640`。同一配置文件中的 `AMAP_REGEOCODE_KEY` 仅在服务端使用:站点省、市、区按 GCJ-02 坐标调用高德逆地理生成,不能使用资产表的行政区字段;结果以坐标为键落盘缓存 7 天。详细地址仍直接保留资产原始字段。
|
||||
以上三个接口均使用开放平台的 `Authorization: Bearer <AppKey>` 鉴权。生产 AppKey 仅保存在 ECS 的 `/opt/lingniu-vehicle-map/env/vehicle-map.env`,文件权限为 `root:vehicle-map 0640`。同一配置文件中的 `AMAP_REGEOCODE_KEY` 仅在服务端使用:站点省、市、区按 GCJ-02 坐标调用高德逆地理生成,不能使用资产表的行政区字段;请求通过全局速率限制避免高德 QPS 限流,结果以坐标为键落盘缓存 7 天。详细地址仍直接保留资产原始字段。
|
||||
|
||||
本服务提供:
|
||||
|
||||
|
||||
@@ -38,12 +38,15 @@ STATION_GEOCODE_CACHE_SECONDS = int(os.getenv("STATION_GEOCODE_CACHE_SECONDS", "
|
||||
STATION_GEOCODE_CACHE_PATH = Path(os.getenv(
|
||||
"STATION_GEOCODE_CACHE_PATH", str(ROOT / ".station-geocode-cache.json")
|
||||
))
|
||||
AMAP_REGEOCODE_MIN_INTERVAL_SECONDS = float(os.getenv("AMAP_REGEOCODE_MIN_INTERVAL_SECONDS", "0.25"))
|
||||
_cache_lock = threading.Lock()
|
||||
_cache = {}
|
||||
_cache_load_locks = {}
|
||||
_station_geocode_cache_lock = threading.Lock()
|
||||
_station_geocode_cache = None
|
||||
_station_geocode_cache_dirty = False
|
||||
_station_geocode_rate_lock = threading.Lock()
|
||||
_station_geocode_next_request_at = 0.0
|
||||
|
||||
|
||||
class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
|
||||
@@ -142,8 +145,15 @@ def _persist_station_geocode_cache():
|
||||
|
||||
|
||||
def _reverse_geocode_station(longitude, latitude):
|
||||
global _station_geocode_next_request_at
|
||||
if not AMAP_REGEOCODE_KEY:
|
||||
raise RuntimeError("AMAP_REGEOCODE_KEY is not configured")
|
||||
with _station_geocode_rate_lock:
|
||||
now = time.monotonic()
|
||||
wait_seconds = max(0.0, _station_geocode_next_request_at - now)
|
||||
_station_geocode_next_request_at = max(now, _station_geocode_next_request_at) + AMAP_REGEOCODE_MIN_INTERVAL_SECONDS
|
||||
if wait_seconds:
|
||||
time.sleep(wait_seconds)
|
||||
query = urlencode({
|
||||
"key": AMAP_REGEOCODE_KEY,
|
||||
"location": "{:.6f},{:.6f}".format(longitude, latitude),
|
||||
|
||||
Reference in New Issue
Block a user