GeoServer 与 PostGIS:真正重要的 VPN 路径在服务器一侧
笔记本电脑能访问 GeoServer,并不能说明 GeoServer 能否访问 PostGIS。请比较两个源点、缓存边界以及数据存储自身的来源。
你在 QGIS 中打开图层,它渲染出来了。同一 VPN 上的同事打开同一图层却报错。有人由此断定 VPN 坏了,接下来的一小时就花在迁移数据库或暴露一个本不需要的端口上。桌面发出的请求和 GeoServer 发往 PostGIS 的查询来自不同的机器、不同的网络命名空间、不同的凭据。把这两条路径分开,就是诊断的大部分工作。
两个连接,两个源点
QGIS -> client's permitted path (often the VPN) -> GeoServer listener
GeoServer -> server's permitted path -> PostGIS listener
第二个箭头并不继承第一台机器的隧道。容器里的 GeoServer 拥有容器的网络栈,而不是宿主机的;桥接网络上的容器可能连得上宿主机连不上的数据库,反之亦然。所以同一个用户在同一次会话里可能既成功又失败,取决于答案是来自缓存还是来自一次新的查询。
| What you tested | What it proves |
|---|---|
Portal page or GetCapabilities | HTTP reachability to GeoServer only |
| A tile served from cache | nothing about the database |
GetMap for an uncached layer | a datastore query had to happen |
找出真正失败的那一步
服务层拒绝、取不到数据存储的图像请求,以及某一个图层的权限问题,在浏览器标签页里看起来很像,在服务器日志里却完全不同。请求具体的操作,然后读取同一时间戳下服务器自己的事件。
curl -s -o /dev/null -w '%{http_code}\n' \
"https://gis.example.com/geoserver/wms?service=WMS&version=1.3.0&request=GetCapabilities"
curl -s -o /tmp/tile.png -w '%{http_code} %{size_download}\n' \
"https://gis.example.com/geoserver/wms?service=WMS&version=1.3.0&request=GetMap&layers=corp:parcels&bbox=-13650000,4500000,-13600000,4550000&width=256&height=256&srs=EPSG:3857&format=image/png"
第二次请求返回 200 且图像合理,说明数据存储确实响应了。返回 200 但带着服务异常文档,说明它没有响应,而异常文本通常点名的是存储而不是客户端。
从服务器一侧读取数据存储
GeoServer 的 PostGIS 参考文档 列出了存储所需的东西:主机、端口、数据库和凭据。这些描述的都是 GeoServer 打开的连接。没有一项描述 桌面客户端的登录。把这四个字段理解为关于服务器网络环境的陈述,「在他们那儿能用」这一类工单就变得可处理了。
正因如此,localhost 出现在数据存储里才是如此常见的错误。它指的是 GeoServer 进程自身的网络环境。如果 GeoServer 跑在 Docker 里,而 PostGIS 跑在宿主机上,localhost 就指向容器内部,什么也找不到,再多的 VPN 配置也改变不了这一点。
在服务器上,按顺序检查路由、监听器和认证策略。PostgreSQL 的基于主机的认证比对的是它看到的源地址,而网关可能会改写这个地址,所以往 HBA 文件里加客户端 VPN 地址池,很少能修好服务器侧的连接。像服务器那样测试:同一主机、同一端口、同一用户。如果这个测试通过而 GeoServer 仍然失败,差别在于进程环境,而不是数据库。
ip route get 10.20.5.11
ss -tnp | grep 5432
psql "host=10.20.5.11 dbname=gis user=geoserver" -c 'select 1'
连接池和缓存在变更之间保留状态
数据存储的连接池会让套接字一直开着。连接池创建一小时之后才起来的隧道,未必给连接池一条新路径;空闲连接可能停在一条已经断掉的路上,直到校验或超时把它关掉。与其假设会自动恢复,不如检查已安装存储的校验设置;在弄清是哪个图层失败之前,也要克制住重启整个服务的冲动。
瓦片缓存制造了这个问题的一面镜子:数据库连接断开很久之后,它们仍能提供看起来正确的地图。为了「看看有没有用」而清空缓存,恰恰毁掉了唯一能告诉你哪条路径还活着的证据。
交接时把两个源点都写清楚
能换来快速修复的描述会写清两件事:到达 GeoServer 的客户端请求,以及 GeoServer 未能完成的后端操作。两者都有,正确的负责人才能修好失败的那条路径。只有前者,最自然的修法就是把数据库公开出去,那等于用更糟的问题换掉这张工单。
记下图层、响应码、服务器侧异常,以及产生它的容器或主机。就这四行,歧义便彻底消失。