05.01.2018 Настройка тайлового кэширования MapServer с помощью модуля MapCache

Втупление

Думаю, настало время вернуться к старой доброй теме разработки веб-ГИС приложений, а именно - к MapServer. В этой статье пойдет речь о том, как настроить кэширование изображений, которые MapServer отрисовывает при каждом запросе. При этом мы убиваем сразу трех зайцев одним выстрелом - повышаем скорость ответа клиенту, увеличиваем количество обслуживаемых запросов в единицу времени, а также скрываем детали о структуре каталогов, которая частично раскрывалась в запросах к MapServer (например, http://localhost:8888/cgi-bin/mapserv.exe?map=../htdocs/mydemo/main.map&layer=world_poly&mode=map), что может спровоцировать определенных пользователей на некоторые не очень хорошие эксперименты. Если подсистема безопасности хорошо настроена, то это не несет никаких проблем, но все же на клиентскую сторону лучше не передавать те сведения, которые ей не нужны.

Итак, поскольку данная статья является продолжением цикла статей о MapServer, то я подразумеваю, что вы знакомы с начальной настройкой MapServer, умеете настраивать хранилище геоданных в СУБД MS SQL Server, знаете, как настроить WMS-сервис и имеете начальные знания о библиотеке OpenLayers. Если же что-то из вышеперечисленного вызывает у вас затруднения, то вы можете почитать об этом в предыдущих статьях на моем сайте в разделе MapServer - практика. А сейчас приступаем...

Что такое MapCache?

MapCache - это серверный модуль, который реализует кэширование тайлов для увеличения скорости доступа к слоям WMS.

Особенности MapCache:

  • Службы WMS, WMTS, TMS, VirtualEarth/Bing и запросы к Google Maps.
  • Возможность ответа на WMS запросы путем слияния тайлов из кэша или же перенаправления их на WMS службу.
  • Отвечать на запросы WMS/WMTS GetFeatureInfo (перенаправление на службу-источник).
  • Генерирование KML Superoverlay.
  • Данные, предоставляемые WMS-бэкэндами.
  • Виды кэширования:
    • Диск
    • SQLite
    • Memcached
    • Тайловый TIFF
    • REST (S3, Azure, Google)
    • Riak
    • Комбинированное кэширование
    • Berkeley DB
  • Настраиваемые метатайлы
  • Слияние тайлов "на лету" для совмещения нескольких тайлов в одно изображение.
  • Пост-обработка изображений (рекомпрессия и квантование), полученных от бэкэнда.
  • Интерпретация и создание заголовков управления кэшированием: Last-Modified, If-Modified-Since, Expires.
  • Мультипоточная утилита генерирования тайлов, которая может генерировать тайлы на указанный масштаб или экстент.
  • Возможность наложить водянок знак на сохраненные тайлы.
  • Исполняемый файл для использования с веб-серверами отличными от Apache
  • Настраиваемые символические ссылки пустых тайлов для экономии дискового пространства
  • Настраиваемые сообщения об ошибках: код ошибки HTTP простым текстом, текстовое сообщение или пустое изображение
  • Возможность указать параметры поставщика или экстент для перенаправления к WMS-бэкэнду (и построить кэш, который будет учитывать эти параметры)

Настройка модуля MapCache для Apache

В загружаемый архив MapServer включены модуль MapCache для Apache и утилита mapcache_seed.exe для предварительной генерации тайлов. Чтобы задействовать модуль Apache, необходимо открыть файл /ms4w/Apache/conf/httpd.conf в текстовом редакторе и раскоментировать следующую строку:

LoadModule mapcache_module "D:/ms4w/Apache/cgi-bin/mod_mapcache.dll"

При этом, если у вас путь к директории, куда установлен MapServer, отличается, то вам необходимо внести соответствующие изменения. Далее, в файле httpd.conf, найдите раздел <IfModule mapcache_module>. Отредактируйте этот раздел, чтобы он выглядел так, как показано ниже. Путь к файлу mapcache.xml при необходимости тоже нужно отредактировать.

<IfModule mapcache_module>
   <Directory "/ms4w/apps/mapcache/">
      AllowOverride None
      Options None
      Require all granted
   </Directory>
   MapCacheAlias /mapcache "D:/ms4w/apps/mapcache/mapcache.xml"
</IfModule>

Далее, откройте файл ms4w/apps/mapcache/mapcache.xml в текстовом редакторе и, при необходимости, отредактируйте пути к файлам и папкам согласно расположению каталога ms4w на вашем компьютере. У меня данный файл выглядит, следующим образом:

<?xml version="1.0" encoding="UTF-8"?>

<!-- see the accompanying mapcache.xml.sample for a fully commented configuration file -->

<mapcache>
   <cache name="disk" type="disk">
      <base>D:/ms4w/tmp/ms_tmp/cache</base>
      <!--<symlink_blank/>-->
   </cache>
   
   <cache name="berkeley" type="bdb">
      <base>D:/ms4w/tmp/ms_tmp/cache</base>
      <!--<symlink_blank/>-->
   </cache>  
   
   <cache name="tiff" type="tiff">
      <template>D:/ms4w/tmp/ms_tmp/cache/{tileset}/{grid}/L{z}/R{inv_y}/C{x}.tif</template>
      <xcount>64</xcount>
     <ycount>64</ycount>
     <!-- <format>myjpeg</format> -->
   </cache> 
   
   <cache name="sqlitetemplate" type="sqlite3">
      <dbfile>D:/ms4w/tmp/ms_tmp/cache/sqlitefile.db</dbfile>
      <pragma name="max_page_count">10000000</pragma>
   </cache>   

   <source name="vmap0" type="wms">
      <getmap>
         <params>
            <FORMAT>image/png</FORMAT>
            <LAYERS>basic</LAYERS>
         </params>
      </getmap>
      
      <http>
         <url>http://vmap0.tiles.osgeo.org/wms/vmap0</url>
      </http>
   </source>
   
   <tileset name="test">
      <source>vmap0</source>
      <cache>disk</cache>
      <grid>WGS84</grid>
      <grid>g</grid>
      <format>PNG</format>
      <metatile>5 5</metatile>
      <metabuffer>10</metabuffer>
      <expires>3600</expires>
   </tileset> 


   <default_format>JPEG</default_format>

   <service type="wms" enabled="true">
      <full_wms>assemble</full_wms>
      <resample_mode>bilinear</resample_mode>
      <format>JPEG</format>
      <maxsize>4096</maxsize>
   </service>
   <service type="wmts" enabled="true"/>
   <service type="tms" enabled="true"/>
   <service type="kml" enabled="true"/>
   <service type="gmaps" enabled="true"/>
   <service type="ve" enabled="true"/>
   <service type="demo" enabled="true"/>

   <errors>report</errors>
   <lock_dir>D:/ms4w/tmp/ms_tmp/cache</lock_dir>

</mapcache>

После внесения указанных изменений в файлы httpd.conf и mapcache.xml, сохраните их и перезапустите службу Apache. Для этого можно запустить файл /ms4w/apache-restart.bat.

Если модуль кэширования MapCache был успешно загружен, то в файле /ms4w/Apache/logs/error_log.txt вы найдете подобное сообщение:

[mpm_winnt:notice] [pid 5276:tid 436] AH00455: Apache/2.4.20 (Win32) mod-mapcache/1.4.1 configured -- resuming normal operations

Чтобы убедиться в правильной работе модуля кэширования MapCache, откройте в браузере следующий url: http://localhost:8888/mapcache/demo/. После загрузки страницы, вы должны увидеть список кликабельных ссылок:

  • tms
  • wmts
  • gmaps
  • kml
  • ve
  • wms

Кликните по одной из ссылок, например, http://localhost:8888/mapcache/demo/wmts. При этом должна загрузиться страница с картой, как показано на рисунке ниже:

Проверка модуля кэширования MapCache
Проверка модуля кэширования MapCache

Увеличьте масштаб и поперемещайте карту. Ваша директория для кэширования тайлов (в моем случае - D:/ms4w/tmp/ms_tmp/cache/) будет содержать сгенерированные тайлы, подобно тому, как показано на изображении ниже.

Директория для кэшированных тайлов MapCache
Директория для кэшированных тайлов MapCache

На этом настройку модуля кэширования MapCache можно считать законченной. Теперь рассмотрим, как можно использовать MapCache в своих приложениях.

Практическое применение модуля MapCache

Сейчас мы создадим простое ГИС веб-приложение, которое будет использовать модуль MapCache для получение тайлов от сервера. За основу я возьму статью Подключаемся к MapServer WMS из OpenLayers. Поэтому нам понадобится файл ms4w\Apache\htdocs\mydemo\wms_ol.map из указанной статьи. Теперь в катологе ms4w\Apache\htdocs\apps\ создадим новую директорию ol_mapcache и скопируем туда содержимое каталога ms4w\Apache\htdocs\apps\ol. У вас должна получиться такая структура:

Структура ГИС веб-приложения на OpenLayers для проверки MapCache
Структура ГИС веб-приложения на OpenLayers для проверки MapCache

Далее, откроем файл ms4w/apps/mapcache/mapcache.xml и внесем в него следующие изменения:

<?xml version="1.0" encoding="UTF-8"?>

<!-- see the accompanying mapcache.xml.sample for a fully commented configuration file -->

<mapcache>
   <cache name="disk" type="disk">
      <base>D:/ms4w/tmp/ms_tmp/cache</base>
      <!--<symlink_blank/>-->
   </cache>
   
   <cache name="berkeley" type="bdb">
      <base>D:/ms4w/tmp/ms_tmp/cache</base>
      <!--<symlink_blank/>-->
   </cache>  
   
   <cache name="tiff" type="tiff">
      <template>D:/ms4w/tmp/ms_tmp/cache/{tileset}/{grid}/L{z}/R{inv_y}/C{x}.tif</template>
      <xcount>64</xcount>
     <ycount>64</ycount>
     <!-- <format>myjpeg</format> -->
   </cache> 
   
   <cache name="sqlitetemplate" type="sqlite3">
      <dbfile>D:/ms4w/tmp/ms_tmp/cache/sqlitefile.db</dbfile>
      <pragma name="max_page_count">10000000</pragma>
   </cache>   

   <source name="vmap0" type="wms">
      <getmap>
         <params>
            <FORMAT>image/png</FORMAT>
            <LAYERS>basic</LAYERS>
         </params>
      </getmap>
      
      <http>
         <url>http://vmap0.tiles.osgeo.org/wms/vmap0</url>
      </http>
   </source>
   
   <source name="mywms" type="wms">
      <getmap>
         <params>
            <FORMAT>image/png</FORMAT>
            <LAYERS>pop_places</LAYERS>
            <TRANSPARENT>true</TRANSPARENT>
         </params>
      </getmap>
      
      <http>
         <url>http://localhost:8888/cgi-bin/mapserv.exe?map=../htdocs/mydemo/wms_ol.map</url>
      </http>
   </source>   
   
   <tileset name="test">
      <source>vmap0</source>
      <cache>disk</cache>
      <grid>WGS84</grid>
      <grid>g</grid>
      <format>PNG</format>
      <metatile>5 5</metatile>
      <metabuffer>10</metabuffer>
      <expires>3600</expires>
   </tileset>
   
   <tileset name="ol_test">
      <source>mywms</source>
      <cache>disk</cache>
      <grid>WGS84</grid>
      <grid>g</grid>
      <format>PNG</format>
      <metatile>5 5</metatile>
      <metabuffer>10</metabuffer>
      <expires>3600</expires>
   </tileset>   


   <default_format>JPEG</default_format>

   <service type="wms" enabled="true">
      <full_wms>assemble</full_wms>
      <resample_mode>bilinear</resample_mode>
      <format>JPEG</format>
      <maxsize>4096</maxsize>
   </service>
   <service type="wmts" enabled="true"/>
   <service type="tms" enabled="true"/>
   <service type="kml" enabled="true"/>
   <service type="gmaps" enabled="true"/>
   <service type="ve" enabled="true"/>
   <service type="demo" enabled="true"/>

   <errors>report</errors>
   <lock_dir>D:/ms4w/tmp/ms_tmp/cache</lock_dir>

</mapcache>

В этом файле добавлены два новых раздела:

   ...

   <source name="mywms" type="wms">
      <getmap>
         <params>
            <FORMAT>image/png</FORMAT>
            <LAYERS>pop_places</LAYERS>
            <TRANSPARENT>true</TRANSPARENT>
         </params>
      </getmap>
      
      <http>
         <url>http://localhost:8888/cgi-bin/mapserv.exe?map=../htdocs/mydemo/wms_ol.map</url>
      </http>
   </source>   

   ...
   
   <tileset name="ol_test">
      <source>mywms</source>
      <cache>disk</cache>
      <grid>WGS84</grid>
      <grid>g</grid>
      <format>PNG</format>
      <metatile>5 5</metatile>
      <metabuffer>10</metabuffer>
      <expires>3600</expires>
   </tileset>

   ...

Раздел source описывает источник геоданных типа WMS, в котором мы прописываем URL нашем WMS-службы. По данному URL модуль MapCache будет запрашивать тайлы, если таковые отсутствуют в кэше. Параметр FORMAT определяет тип изображения. В нашем случае - это формат png. Параметр LAYERS определяет слои, которые будут запрошены у WMS-службы. И, наконец, TRANSPARENT указывает, что для изображений должен использоваться прозрачный фон.

Раздел tileset - важная настройка, которая отвечает за набор тайлов, запрошенных у источника, сохраненных в кэше и возвращенных клиенту в указанном формате. В данной статье я не буду описывать все параметры раздела tileset, а отмечу только основные.

  • source - ссылка на имя раздела source, который был описан выше.
  • cache - ссылка на имя раздела cache. Раздел cache определяет расположение, где будут сохранены полученные от источника геоданных тайлы.
  • grid - ссылка на имя раздела grid. Grid - это матрица, которая отображает тайлы на область и содержит системы координат, географического экстента, разрешения и размера тайлов Существует три предопределенных элемента grid, которые можно использовать без объявления в файле mapcache.xml: "WGS84", "g" и "GoogleMapsCompatible".
  • format - формат, в котором изображение будет сохранено.
  • metatile - Количество столбцов и строк для использования в метатайле. Метатайл - это один большой тайл, который содержит несколько меньших тайлов. Метатайлы запрашиваются у источника геоданных, а затем разрезаются на меньшие тайлы, которые и будут кэшированы.
  • metabuffer - Область вокруг тайла или метатайла, которая будет отрезана во избежание некоторых краевых артефактов.
  • expires - значение окончания срока хранения тайлов, в секундах.

Далее, отредактируем содержимое файла ms4w\Apache\htdocs\apps\ol_mapcache\index.html таким образом, чтобы оно соответствовало следующему содержимому:

<!doctype html>
<html lang="ru">
  <head>
    <link rel="stylesheet" href="v4.0.1-dist/ol.css" type="text/css">
    <style>
    html, body { 
        margin:0; 
        padding:0; 
        height:100%; 
    }
    #map { 
        height:100%; 
    }
    </style>
    <script src="v4.0.1-dist/ol.js" type="text/javascript"></script>
    <title>Тест MapCache</title>
  </head>
  <body>
    <div id="map" class="map"></div>
	<script type="text/javascript">	
		var map = new ol.Map({
		target: 'map',
		layers: [
			new ol.layer.Tile({
				source: new ol.source.OSM()
			}),
			new ol.layer.Tile({
				source: new ol.source.TileWMS({
					projection: 'EPSG:4326',
					url: 'http://localhost:8888/mapcache/',
					params: { 'LAYERS': 'ol_test', 'TILED': true, 'VERSION': '1.1.1' },
				})
			})
		],
		view: new ol.View({
			center: ol.proj.fromLonLat([37.41, 8.82]),
			zoom: 4
			})
		});
	</script>
  </body>
</html>

Главное изменение в этом файле - это смена url в объекте, который передается в конструктор объекта ol.source.TileWMS. Как можно заметить, теперь в новом url http://localhost:8888/mapcache/ не содержится никакой информации о файловой системе. Также обратите внимание, что объект params в свойстве LAYERS содержит значение ol_test. Это то самое имя, которое мы присвоили нашему разделу tileset в файле mapcache.xml. Запустим браузер и в адресной строке укажем url: http://localhost:8888/apps/ol_mapcache/index.html. В окне браузера увидим нечто подобное:

Запуск ГИС веб-приложения на OpenLayers для проверки MapCache
Запуск ГИС веб-приложения на OpenLayers для проверки MapCache

Можно немного поиграться с масштабом и перемещением карты. Если теперь обновить страницу, то можно заметить, что слой из WMS-службы отрисовывается гораздо быстрее. Ну и, наконец, давайте посмотрим, что же происходит в директории кэша.

Кэшированные изображения для ГИС веб-приложения на OpenLayers
Кэшированные изображения для ГИС веб-приложения на OpenLayers

24.02.2018 Видео о настройке модуля кеширования MapCache для MapServer (обновление)

В качестве бонуса решил дополнительно записать видеоролик по настройке кеширования. Если материал оказался Вам полезен, то ставьте лайк под видео, что в свою очередь будет мотивировать меня на написание других статей по теме разработке веб-ГИС приложений (и не только).


Предыдущие статьи по теме разработки веб-ГИС и настройки MapServer: