如何缓存QGIS服务器WMS?

7
似乎栅格瓦片已经开始过时了,但是我仍然需要一种解决方案来为我的 QGIS 服务器的 WMS 进行操作。到目前为止,我尝试了 TileCache,但我无法使其在 OL3 中工作,并且它似乎有点“老旧”。那么,如果以后我想在我的 OL3 应用程序中使用缓存图层,哪种方式最好?TileStache、Mapproxy 还是 MapCache?我在 CentOS 7 下运行我的 QGIS 服务器。

1
我正在使用WMS-->Tilecache(仅限tilecache cgi模块)-->OL3(EPSG:3857)。实际上运行良好。 - MichaelJS
2个回答

4

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

MapProxy使用Python编写,您可能已经在服务器上安装了Python。您可以(也应该)在虚拟环境中运行MapProxy。MapProxy的说明非常清楚,只需要几分钟就可以让它运行起来,并从QGIS服务器获取数据。

  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文档中有非常好的小例子。

这是最复杂的例子之一,因为它使用了自定义网格和EPSG:3857以外的CRS。如果使用通常的GLOBAL_MERCATOR网格,则简单得多(在MapProxy和OpenLayers方面都是如此)。

这是一个小例子,展示了一个自定义网格的配置文件。源是QGIS Server。我添加了一个请求,以显示如何将这些请求转发到QGIS Server,并且添加了图层的图例(使用)。
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>

0

这个方案可能有点重量级,但我一直在使用GeoServer(http://geoserver.org/)来提供我的地图瓦片(它内置了GeoWebCache)。您需要通过J2EE服务器(如Jetty)运行它,但目前对我们来说运行良好。


4
谢谢,我知道Geoserver,但那是一种不同的地图服务器软件。我之所以使用QGIS Server,是因为它能够提供与您在QGIS桌面设计的完全相同的符号化。而且我有大约300个符号/图层。 - Benedek Simo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接