如何缓存 QGIS Server WMS?

How to cache QGIS Server WMS?

栅格图块似乎已经开始过时了,但我仍然需要一个解决方案来以某种方式为我的 QGIS Server 的 WMS 做到这一点。

到目前为止我已经尝试过TileCache,但我无法让它在OL3中工作,而且它似乎也有点"oldish"。

那么,如果以后我想在我的 OL3 应用程序中使用缓存层,我的最佳出价是多少? TileStache、Mapproxy、MapCache?

我的 QGIS 服务器 运行 在 CentOS 7 下。

它有点重量级,但我一直在使用 GeoServer (http://geoserver.org/) 来提供我的地图图块(它内置了 GeoWebCache)。您需要通过 J2EE 服务器(如 Jetty)运行 它,但目前它对我们来说工作正常。

QGIS 服务器与 MapProxy 配合良好。使用 QGIS Server+MapProxy,您将获得最佳的 QGIS 样式和切片缓存的速度。

MapProxy 是用 Python 编写的,您可能已经在服务器上安装了 Python。您可以(而且您应该)在虚拟环境中使用 运行 MapProxy。 MapProxy 的说明非常清楚,从 QGIS Server 获取数据 运行ning 真的是几分钟的问题。

  1. 它比 GeoWebCache 轻很多
  2. 它缓存并提供图块(只需在您的 WMS 请求中使用 tiled: true
  3. 它与 OpenLayers 配合得很好。安装后,您将获得一个演示页面,其中包含 OpenLayers 示例。
  4. 您可以针对缓存的源调用 GetFeatureInfo 请求
  5. 您可以针对缓存的源调用 GetLegendGraphic 请求
  6. 它可以处理自定义网格(只要您在 OpenLayers 中使用相同的网格)
  7. 您可以并行请求多个图块并利用 QGIS Server 并行渲染支持(如果启用)。
  8. 由于QGIS Server 可以将项目存储在Postgis 上,因此您无需上传任何内容即可轻松更新项目。 MapProxy 将使用 QGIS Server 的更新样式。

例子

MapProxy 文档中有非常好的小示例。

这是最复杂的示例之一,因为它使用自定义网格和 CRS 而不是 EPSG:3857。如果你使用通常的 GLOBAL_MERCATOR 网格,它会简单得多(在 MapProxy 端和 OpenLayers 端)。

这是 mapproxy.yaml 配置文件的一个小示例,带有自定义网格。来源是 QGIS 服务器。我在鼠标点击时添加了 GetFeatureInfo 请求,以显示如何将这些请求转发到 QGIS Server。我还添加了图层的图例(使用 service=WMS&REQUEST=GetLegendGraphic&VERSION=1.3.0)。

layers:
  - name: caop
    title: CAOP by QGIS Server
    sources: [caop_cache_continente]
caches:
  caop_cache_continente:
    meta_size: [4, 4]
    meta_buffer: 20
    # 20+4x256+20
    # width=1064&height=1064
    use_direct_from_level: 14
    concurrent_tile_creators: 2
    link_single_color_images: true
    grids: [continente]
    sources: [continente_wms]
sources:
  continente_wms:
    type: wms
    wms_opts:
      featureinfo: true
      legendgraphic: true
    req:
      url: http://continente.qgis.demo/cgi-bin/qgis_mapserv.fcgi
      layers: freguesia
      transparent: true
grids:
  continente:
    srs: 'EPSG:3763'
    bbox_srs: 'EPSG:3763'
    bbox: [-127104, -301712, 173088, 278544]
    origin: nw
    res: [ 1172.625, 586.3125, 293.15625, 146.578125, 73.2890625, 36.64453125, 18.322265625, 9.1611328125, 4.58056640625, 2.290283203125, 1.1451416015625, 0.57257080078125, 0.286285400390625, 0.1431427001953125, 0.07157135009765625 ]

以下 OpenLayers 文件能够从 MapProxy 获取图块。

<!DOCTYPE html>
<html>

<head>
  <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
  <link rel="stylesheet" href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css"
    type="text/css">
  <style>
    .map {
      height: 600px;
      width: 100%;
    }
  </style>
  <script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
  <script src="resources/js/proj4js/proj4.js"></script>
  <title>OpenLayers example using QGIS Server and MapProxy</title>
</head>

<body>
  <div id="map" class="map"></div>
  <p><image src="http://mapproxy.qgis.demo/mapproxy/service?service=WMS&REQUEST=GetLegendGraphic&VERSION=1.3.0&style=default&FORMAT=image/png&LAYER=caop&transparent=true"></image></p>
  <div id="nodelist"><em>Click on the map to get feature info</em></div>
  <script>
    proj4.defs("EPSG:3763", "+proj=tmerc +lat_0=39.66825833333333 +lon_0=-8.133108333333334 +k=1 +x_0=0 +y_0=0 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs");
    ol.proj.proj4.register(proj4);
    var projection = new ol.proj.Projection({
      code: 'EPSG:3763',
      extent: [-127104, -301712, 173088, 278544]
    });

    var projectionExtent = projection.getExtent();

    var size = ol.extent.getWidth(projectionExtent) / 256;
    var newresolutions = new Array(15);
    var newmatrixIds = new Array(15);
    for (var z = 0; z < 15; ++z) {
      newresolutions[z] = size / Math.pow(2, z);
      newmatrixIds[z] = z;
    }

    var tileGrid = new ol.tilegrid.WMTS({
      origin: ol.extent.getTopLeft(projectionExtent), // [ 270000, 3650000 ]
      resolutions: newresolutions,
      matrixIds: newmatrixIds,
      tileSize: [256, 256]
    });

    var caop = new ol.layer.Tile({
      source: new ol.source.TileWMS({
        url: 'http://mapproxy.qgis.demo/mapproxy/service?',
        params: { layers: 'caop', tiled: true, srs: "EPSG:3763" },
        format: 'image/png',
        projection: projection,
        tileGrid: tileGrid
      })
    });

    var map = new ol.Map({
      layers: [caop],
      target: 'map',
      view: new ol.View({
        projection: projection,
        center: [0, 0],
        zoom: 1
      })
    });

    map.on('singleclick', function (evt) {
      document.getElementById('nodelist').innerHTML = "Loading... please wait...";
      var view = map.getView();
      var viewResolution = view.getResolution();
      var url = caop.getSource().getGetFeatureInfoUrl(
        evt.coordinate, viewResolution, view.getProjection(),
        { 'INFO_FORMAT': 'text/html', 'FEATURE_COUNT': 50 });
      if (url) {
        document.getElementById('nodelist').innerHTML = '<iframe seamless src="' + url + '" style="width:100%"></iframe>';
      }
    });
  </script>
</body>

</html>