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 testedWhat it proves
Portal page or GetCapabilitiesHTTP reachability to GeoServer only
A tile served from cachenothing about the database
GetMap for an uncached layera 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 が完了できなかったバックエンド操作という二つを名指しします。両方あれば、正しい担当者が失敗した経路を直せます。最初の一つだけなら、自然な修正はデータベースを公開することで、それはより悪い問題を作ってチケットを閉じるだけです。

レイヤー、応答コード、サーバー側の例外、それを生んだコンテナまたはホストを記録します。四行であり、曖昧さは完全に消えます。

関連記事