--- title: PostGIS 矢量瓦片 date: 2020-09-11 author: ac tags: - vector tile categories: - Database --- ![马丁](./images/logo.png) ### Martin - 基于PostGIS的矢量瓦片服务器 ### 1. 简介 目前流行的矢量瓦片的切图方案: - `mapbox gl` + [tippecanoe](https://github.com/mapbox/tippecanoe) :v2收费,tippecanoe是mapbox官方推荐的矢量瓦片静态生成工具 ,适用于大数据量场景,且不频繁更新的空间数据; - `openlayers` + `geoserver` :开源,使用geoserver的矢量瓦片扩展,增加矢量瓦片的输出格式; - `maplibre`+ `Martin` +[postgis](https://www.postgis.net/docs/manual-dev/en/ST_AsMVT.html) :开源,martin是矢量切片服务器,通过postgis的函数动态生成矢量瓦片。 - `maptiler`:收费 > mapbox v2 必须使用 access token 才能初始化 Map 对象。进行token计算,每月50000免费次数。 ### 2. Martin `Martin`是一个开源的PostGIS矢量切片服务器,可以从任何PostGIS表或视图中创建`MVT`矢量切片,也可以从 PMTile 和MBTile文件中动态生成矢量瓦片,是使用 `Rust`编写,针对切片速度和大流量进行了优化,是极快且轻量级的切片服务器。 #### 2.1 安装 > 如果将Martin和PostgreSQL一起使用,PostGIS版本必须为v3.0+ Martin支持Linux、macOS、windows平台和docker环境,本例采用windows环境。先从github上下载[martin-Windows-x86_64](https://github.com/maplibre/martin/releases/latest/download/martin-Windows-x86_64.zip) 。解压后会发现这两个exe: ```yaml ─martin-Windows-x86_64 ├─martin.exe └─mbtiles.exe ``` windows平台可以直接使用`martin.exe`来启动切片服务器,可以先在命令行查看一下参数: ```shell D:\tools\vectorTileTool\martin-Windows-x86_64>martin.exe --help Blazing fast and lightweight tile server with PostGIS, MBTiles, and PMTiles support Usage: martin.exe [OPTIONS] [CONNECTION]... Arguments: [CONNECTION]... Connection strings, e.g. postgres://... or /path/to/files Options: -c, --config Path to config file. If set, no tile source-related parameters are allowed --save-config Save resulting config to a file or use "-" to print to stdout. By default, only print if sources are auto-detected -s, --sprite Export a directory with SVG files as a sprite source. Can be specified multiple times -k, --keep-alive Connection keep alive timeout. [DEFAULT: 75] -l, --listen-addresses The socket address to bind. [DEFAULT: 0.0.0.0:3000] -W, --workers Number of web server workers -b, --disable-bounds Disable the automatic generation of bounds for spatial PG tables --ca-root-file Loads trusted root certificates from a file. The file should contain a sequence of PEM-formatted CA certificates -d, --default-srid If a spatial PG table has SRID 0, then this default SRID will be used as a fallback -p, --pool-size Maximum connections pool size [DEFAULT: 20] -m, --max-feature-count Limit the number of features in a tile from a PG table source -h, --help Print help -V, --version Print version ``` #### 2.2 使用 > 本例pg安装postgis是v3.3.3.1 `martin`连接pg可以用`connection_string`(命令行参数)和配置文件两种形式。 PostgreSQL连接字符串的形式: ```shell # martin.exe postgresql://user:password@host/db D:\tools\vectorTileTool\martin-Windows-x86_64>martin.exe postgresql://postgres:123@127.0.0.1:5433/postgres [2023-08-08T03:50:11Z INFO martin] Starting Martin v0.8.7 [2023-08-08T03:50:11Z INFO martin] Config file is not specified, auto-detecting sources [2023-08-08T03:50:11Z INFO martin::pg::pool] Connecting to postgresql://postgres:123@127.0.0.1:5433/postgres [2023-08-08T03:50:11Z INFO martin::pg::configurator] Discovered source zhujiang_river from table public.zhujiang_river with geom column (MULTIPOLYGON, SRID=4326) [2023-08-08T03:50:11Z INFO martin] Use --save-config to save or print Martin configuration. [2023-08-08T03:50:11Z INFO martin] Martin has been started on 0.0.0.0:3000. [2023-08-08T03:50:11Z INFO martin] Use http://0.0.0.0:3000/catalog to get the list of available sources. ``` 配置文件的形式 config.yaml: ```yaml # Connection keep alive timeout [default: 75] keep_alive: 75 # The socket address to bind [default: 0.0.0.0:3000] listen_addresses: '127.0.0.1:3000' # Number of web server workers worker_processes: 8 # Database configuration. This can also be a list of PG configs. postgres: # Database connection string. You can use env vars too, for example: # $DATABASE_URL # ${DATABASE_URL:-postgresql://postgres@localhost/db} connection_string: 'postgresql://postgres@localhost:5433/postgres?sslmode=disable&user=postgres&password=123' # Same as PGSSLCERT for psql #ssl_cert: './postgresql.crt' # Same as PGSSLKEY for psql #ssl_key: './postgresql.key' # Same as PGSSLROOTCERT for psql #ssl_root_cert: './root.crt' # If a spatial table has SRID 0, then this SRID will be used as a fallback default_srid: 4326 # Maximum connections pool size [default: 20] pool_size: 20 # Limit the number of table geo features included in a tile. Unlimited by default. max_feature_count: 1000 # Control the automatic generation of bounds for spatial tables [default: false] # If enabled, it will spend some time on startup to compute geometry bounds. disable_bounds: false ``` ```shell D:\tools\vectorTileTool\martin-Windows-x86_64>martin.exe -c config.yaml [2023-08-08T03:54:43Z INFO martin] Starting Martin v0.8.7 [2023-08-08T03:54:43Z INFO martin] Using config.yaml [2023-08-08T03:54:43Z INFO martin::pg::pool] Connecting to postgresql://postgres@localhost:5433/postgres?sslmode=disable&user=postgres&password=123 [2023-08-08T03:54:43Z INFO martin::pg::configurator] Discovered source zhujiang_river from table public.zhujiang_river with geom column (MULTIPOLYGON, SRID=4326) [2023-08-08T03:54:44Z INFO martin] Use --save-config to save or print Martin configuration. [2023-08-08T03:54:44Z INFO martin] Martin has been started on 127.0.0.1:3000. [2023-08-08T03:54:44Z INFO martin] Use http://127.0.0.1:3000/catalog to get the list of available sources. ``` 本例采用的是配置文件的形式启动服务器,服务地址是`http://127.0.0.1:3000`。 从启动的日志可以看到`Martin`将所连接的pg库中的`zhujiang_river`表发布为数据源。 > Martin 会将所有表发布为数据源(如果它们至少有一个几何列)。如果 SRID 为 0,则必须设置默认 SRID,否则该地理列/表将被忽略。所有非几何表列都将发布为矢量切片要素标签(属性)。 ![image-20230808134430612](./images/image-20230808134430612.png) 打开目录可以看到已发布的数据源: ![image-20230808135027306](./images/image-20230808135027306.png) ![image-20230809094825559](./images/image-20230809094825559.png) 数据表的元数据是符合`TileJSON 3.0.0`标准的JSON文件。 `Martin`为每张要素表都提供一个`TileJSON` endpoint。 > TileJSON是表示地图元数据的开放标准,endpoint这个词以前经常被用来描述进程间通信。 #### 2.3 mapbox 发布完数据源后,使用mapbox gl 来调用一下: ```html Document
``` 加载效果: ![image-20230808141517572](./images/image-20230808141517572.png) #### 2.4 openlayers > **由于postgis 切片生成的是mvt格式图片,所以只能使用web墨卡托坐标系** ### 3.应用 #### 3.1 docker安装 ```shell [root@localhost martin]# pwd /home/martin # 下载martin镜像 [root@localhost martin]# docker pull ghcr.io/maplibre/martin:main main: Pulling from maplibre/martin 7264a8db6415: Pull complete 8b9d286dcf48: Pull complete ada398a88aa0: Pull complete Digest: sha256:13b38133bc15fd1d8b9b9444ca28e0380146799f1faa4c1f418090f067d48474 Status: Downloaded newer image for ghcr.io/maplibre/martin:main ghcr.io/maplibre/martin:main ``` ### 4. 遇到的问题 局限性:只能连接一个pg库。 对于有分库的系统,可以使用Nginx来转发。 #### 4.1 表没有空间索引 `Table public.table_name has no spatial index on column geom` ```sql CREATE INDEX table_name_geom_idx ON table_name USING GIST (geom); ``` ### 参考文章 [1] Martin https://martin.maplibre.org/ [2] Martin Tile Server Documentation https://maplibre.org/martin/installation.html