GitHub 项目 OpenFreeMap

image-20250317110433259

1. 项目是什么?(What is OpenFreeMap?)

OpenFreeMap 是一个免费、开源的地图托管解决方案,基于 OpenStreetMap (OSM) 数据。它允许你在网站或应用程序中显示自定义样式的地图。你可以选择自己托管(self-host)或者直接使用他们提供的公共实例。

  • 核心特点:
    • 完全免费,没有地图浏览次数或请求次数限制。
    • 无需注册、API 密钥或 cookies,隐私友好。
    • 开源,不搞“开放核心”(open-core)那一套,所有代码和生产环境配置都公开。
    • 提供每周更新的全球地图数据下载(Btrfs 和 MBTiles 格式)。
    • 通过捐款维持公共实例的运营。
  • 目标: 为开发者提供一个高质量的矢量瓦片(vector-tile)托管方案,利用现有工具(比如 OpenStreetMap、Planetiler、MapLibre 等),无需自己从头开发复杂的地图服务。

2. 它能做什么?不能做什么?(Scope and Limitations)

能做什么:

  • 显示基于 OpenStreetMap 数据的自定义样式地图。
  • 提供生产级别的瓦片托管(tile hosting)。
  • 支持自托管或使用公共实例。
  • 每周生成并提供全球地图数据。

不能做什么(限制):

  • 不提供搜索、导航、路径规划、静态图片生成、卫星图像、标高查询等功能。
  • 不适合本地轻松安装(不是开箱即用的工具,而是针对 Ubuntu 服务器的部署脚本)。
  • 自托管时,自动更新需要你自己监控(不保证无忧运行)。

3. 技术栈(Tech Stack)

这个项目的实现很有意思,它避免了传统复杂的瓦片服务器,而是用了一些创新方法。让我们分解一下:

数据来源:

  • OpenStreetMap (OSM):全球开源地图数据。
  • Natural Earth 和 Wikidata:补充地理信息。

核心工具:

  • Planetiler:快速生成矢量瓦片(5小时 vs. 5周,效率惊人!)。
  • MapLibre:用于前端显示地图(类似 Mapbox 的开源替代品)。
  • OpenMapTiles:提供瓦片生成的基础。

托管方式:

  • 没有传统瓦片服务器:不运行专门的 tile server,而是直接用 Btrfs 文件系统镜像 存储 3 亿个小文件(平均每个文件 450 字节)。
  • Nginx:高性能 Web 服务器,直接从文件系统提供瓦片。
  • Btrfs:一种高效文件系统,通过硬链接(hard links)和镜像存储瓦片,配合 Linux 内核的文件缓存,提供超高性能。

部署:

  • Fabric + SSH:通过脚本在 Ubuntu 服务器上远程部署。
  • 无 Docker:故意避免 Docker,保持简单和直接控制。

其他:

  • Cloudflare R2:存储每周生成的全球地图数据。
  • Round-Robin DNS:负载均衡方案,配合 Let’s Encrypt 证书。

创新点:

  • 用 Btrfs 镜像 + Nginx 取代传统瓦片服务器,性能极高(测试能达到 30 Gbit/s 的吞吐量)。
  • 不依赖云服务,而是用专用服务器,降低成本并保持免费。

4. 项目结构(Code Structure)

项目分为几个模块,每个模块有明确分工:

  1. 部署服务器 (deploy server):
    • 文件:ssh_lib 和 init-server.py
    • 功能:通过 SSH 在全新 Ubuntu 服务器上配置一切。
  2. HTTP 托管 (http_host):
    • 文件:modules/http_host/http_host.py
    • 功能:
      • 下载 Btrfs 镜像和资源。
      • 挂载 Btrfs 镜像。
      • 运行自动同步任务(每分钟检查更新)。
    • 用法:运行 ./http_host.py —help 查看选项。
  3. 瓦片生成 (tile_gen):
    • 文件:modules/tile_gen
    • 功能:
      • 下载 OSM 全球数据。
      • 用 Planetiler 生成 MBTiles 文件。
      • 用自定义脚本(extract_mbtiles 和 shrink_btrfs)转为 Btrfs 镜像。
      • 上传到 Cloudflare R2。
    • 备注:可选步骤,因为官方已提供每周更新的镜像。
  4. 样式 (styles):
    • 独立仓库:styles repo
    • 功能:定义地图的显示样式(道路、图标、标签等),是长期开发的重点。
  5. 负载均衡 (loadbalancer):
    • 文件:modules/loadbalancer
    • 功能:基于 Round-Robin DNS 的健康检查和记录更新,通过 Telegram 机器人推送状态。

5. 如何使用?(How to Use It)

方法 1:使用公共实例

  • 直接访问:https://openfreemap.com
  • 无需配置,直接在你的网站或应用中引用瓦片 URL。
  • 示例(假设用 MapLibre):
const map = new maplibregl.Map({
    container: 'map',
    style: 'https://openfreemap.com/styles/default.json', // 样式文件
    center: [0, 0],
    zoom: 2
});

方法 2:自托管

  1. 准备:
    • 一台干净的 Ubuntu 服务器。
    • SSH 访问权限。
  2. 部署:
    • 克隆仓库:git clone https://github.com/hyperknot/openfreemap
    • 安装 Fabric(Python 工具):pip install fabric
    • 编辑配置文件(指定服务器 IP 等)。
    • 运行部署脚本:python init-server.py
  3. 运行 HTTP 托管:
    • 执行:./http_host.py
    • Nginx 会启动并提供瓦片服务。
  4. 可选:生成瓦片:
    • 如果不想用官方提供的镜像,自己运行 tile_gen 生成。

详细步骤见 self hosting docs


6. 学习建议(How to Study It)

初学者:

  • 目标:理解概念并使用公共实例。
  • 步骤:
    1. 访问 openfreemap.com,试试他们的地图。
    2. 阅读 README,尤其是“Goals”和“What is the tech stack?”部分。
    3. 用 MapLibre 在本地写个简单网页,加载 OpenFreeMap 的瓦片。

中级:

  • 目标:尝试自托管。
  • 步骤:
    1. 在云服务器(比如 DigitalOcean)上装 Ubuntu。
    2. 按照“Self hosting”文档部署。
    3. 修改 styles repo 中的样式,定制地图外观。

高级:

  • 目标:深入技术细节或贡献代码。
  • 步骤:
    1. 研究 Btrfs 和 Nginx 的实现,看看 extract_mbtiles 和 shrink_btrfs 脚本。
    2. 跑一次 tile_gen,生成自己的瓦片。
    3. 看看“Contributing”部分的待办任务,尝试提交 PR。

7. 常见问题(FAQ)

  • 数据多久更新一次?
    • 全球数据每周更新(周三生成,周六发布)。
    • 小范围测试区域(如摩纳哥)每天或每小时更新。
  • 为什么不用云服务?
    • 云服务的延迟高(Range 请求慢),成本也可能失控(比如 AWS 流量费)。
  • 怎么下载全球数据?