地图服务选型 2026:GeoServer、MapServer、pg_tileserv 与云原生架构
传统 GIS 服务器和现代瓦片微服务的差别,不只是性能,是整个成本结构的差别。
两种范式
传统路线是 GeoServer / MapServer:连 PostGIS,用 XML(SLD)配样式,生成 WMS/WFS 端点。它们功能极其强大,能处理复杂的企业级数据架构,但在现代云原生环境里偏重、资源消耗大、扩缩容麻烦。
现代路线是瓦片微服务:Martin(Rust)、pg_tileserv(Go)这类轻量工具只做一件事——连 PostGIS,执行 ST_AsMVT,把生成的矢量瓦片发出去。配置极少,内存占用可忽略,可以在负载均衡后面水平扩展。
选哪条路,取决于你的架构约束,不取决于哪个更"先进"。
延迟与成本对照
这张表是选型的核心依据:
架构方式 | 关键技术 | 延迟 | 基础设施成本 | 扩展性 | 最适合 |
|---|
静态 XYZ 瓦片 | S3/CDN + 预生成瓦片 | <50ms | 极低(仅存储) | 无上限 | 底图、固定参考图层 | 动态 COG 切片 | TiTiler + COG on S3 | 200–500ms | 低(Serverless) | 自动扩缩 | 卫星影像、分析产品 | 矢量瓦片(PMTiles) | CDN + HTTP Range 请求 | <50ms | 极低 | 无上限 | 行政边界、叠加图层 | PostGIS + 瓦片服务 | Martin / pg_tileserv | 50–200ms | 中(数据库常驻) | 中等 | 动态空间查询、用户数据 | 传统瓦片服务器 | GeoServer / MapServer | 100–400ms | 高(常驻 VM) | 手动扩缩 | 传统 WMS/WFS、内网部署 | Serverless 分析 | Lambda / Cloud Functions | 1–10s(冷启动) | 极低(按量付费) | 无上限 | 时序计算、按需统计 | 客户端 COG 渲染 | GeoTIFF.js + WebGL | 取决于文件大小 | 无(服务端零成本) | 受限于客户端 | 交互式波段运算、自定义配色 |
成本差异的真正来源在这里:传统瓦片服务器必须按峰值负载配置并持续付费,不管有没有人在看地图;缓存层也要按同样的峰值来配。 而"对象存储 + Serverless 切片"的设计没有空闲成本:存储按字节计费,计算按请求计费。 对卫星数据平台——这类场景的用量是突发型的、归档数据巨大——这个结构性差异(而不是单请求效率)是迁移到云原生架构的主要原因。 代价:冷启动延迟和高负载下的单请求成本。这也是为什么被高频访问的底图图层通常仍然是预生成 + CDN 分发。 GeoServer vs MapServer两者都是历史悠久的 OGC 服务实现。 GeoServer(Java)优势: 通过 OGC 认证,实现 WFS、WMS、WCS、WMTS 支持 GeoTIFF、WorldImage、ImageMosaic、GeoPackage 等栅格源 生态插件丰富(OGC API - Features、WPS 通过扩展提供) 与 OpenLayers、Leaflet、Mapbox、ArcGIS 前端都有成熟对接 REST API 管理数据,配置可在运行时调整
代价: MapServer(C)优势: 代价: 配置驱动,可编程性弱于 GeoServer 生态规模小于 GeoServer
怎么选:需要运行时动态改配置、需要丰富插件、团队是 Java 背景 → GeoServer。资源受限、只要稳定出图、部署环境简陋 → MapServer。 现代瓦片服务pg_tileservCrunchy Data 出品的 Go 工具。核心理念是配置即用:每张 PostGIS 表自动暴露 ST_AsMVT 端点,不需要写 SQL 模板。 # 大致的使用形态
pg_tileserv /path/to/config.toml
新手友好度最高。适合"我有一张表,我要快速把它变成瓦片服务"的场景。 MartinMapLibre 生态的主力,Rust 编写。性能强,支持函数源(PostGIS 函数查询)和文件源(PMTile、MBTile),配置灵活。 Martin 附带 CLI 工具,可以生成、比较、提取、合并 MBTiles 文件,这对瓦片生产流水线很实用。 TegolaGo 编写,自带 SQL 模板系统,支持多数据源(含 PostGIS),提供 Web 端配置界面。适合不想直接编辑配置文件、希望可视化管理的团队。 tippecanoeC++ 写的离线生产工具,与 PostGIS 实时方案互补。从 GeoJSON 等数据源生成完整的瓦片金字塔,支持按 zoom 动态简化。 tippecanoe 的动态简化做得很好:它在生成时就按目标 zoom 层级做了几何简化,从源头避免了"低 zoom 发全精度数据"的浪费。 选型决策路径你的数据源是什么?
│
├─ PostGIS(动态数据)
│ │
│ ├─ 想要零 SQL、开箱即用 ────────► pg_tileserv
│ ├─ 追求极致性能和灵活配置 ──────► Martin
│ └─ 需要可视化配置 ─────────────► Tegola
│
├─ 文件(GeoJSON / Shapefile / PMTiles)
│ ├─ 能预生成 ───────────────────► tippecanoe
│ └─ 服务现成文件 ───────────────► Martin
│
├─ 必须支持 WMS / WFS / WCS 完整 OGC 栈
│ ├─ 插件丰富、动态配置 ──────────► GeoServer
│ └─ 资源受限、启动快 ───────────► MapServer
│
└─ 遥感影像 / 时序数据
└─ COG on 对象存储 + TiTiler ───► 云原生方案
一个务实的组合策略实践中很少只用一个工具。常见的生产组合是: 图层 | 生成方式 | 分发 |
|---|
底图 | tippecanoe 预生成 | CDN(PMTiles 或静态瓦片) | 行政区划 | tippecanoe 预生成 | CDN | 业务动态图层 | PostGIS 实时 | Martin / pg_tileserv | 用户上传数据 | PostGIS 实时 | Martin | | | |
| 遥感影像 | COG | TiTiler / 服务端读 COG |
|---|
原则:能用预生成的一律预生成,把实时能力留给真正动态的数据。 这既省钱又省心。
COG:被低估的格式
Cloud Optimized GeoTIFF 是遥感领域近年最重要的格式改进。它把 GeoTIFF 的内部结构改成瓦片金字塔形式,支持HTTP Range 请求——意味着浏览器或服务可以只读取所需的部分,而不必下载整个文件。
带来的直接后果:GeoTIFF.js 可以在浏览器里直接打开 COG,不需要任何服务端参与:
// 浏览器端读取 COG 并渲染
const geotiff = await GeoTIFF.fromUrl('https://example.com/scene.tif');
这让"交互式波段运算、自定义配色"这类操作可以在客户端完成,完全不消耗服务端资源。这对分析型应用是结构性优势。
安全与合规
不要忽略这一块。多用户 WebGIS 平台必须处理:
最后一条经常出事故。第三方地图服务的密钥暴露在前端是常态,但如果不做域名限制和配额管理,密钥会被盗用,然后你收到天价的账单或收到封禁通知。
发布前把这份清单过一遍。
参考资料
GeoServer 官方 — https://geoserver.org/
MapServer 官方 — https://mapserver.org/
Martin — https://github.com/maplibre/martin
pg_tileserv — https://github.com/CrunchyData/pg_tileserv
Tegola — https://github.com/go-spatial/tegola
tippecanoe — https://github.com/felt/tippecanoe
TiTiler — https://github.com/developmentseed/titiler
Cloud Optimized GeoTIFF 规范 — https://www.ogc.org/standards/cloud-optimized-geotiff