<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Via SIG</title>
	<atom:link href="https://blog.viasig.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.viasig.com</link>
	<description>Um blog sobre SIG, focado na tecnologia, programação e gestão.</description>
	<lastBuildDate>Wed, 12 Mar 2025 22:43:11 +0000</lastBuildDate>
	<language>pt-PT</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.7.5</generator>
	<item>
		<title>Docker e backups</title>
		<link>https://blog.viasig.com/2024/08/docker-e-backups/</link>
					<comments>https://blog.viasig.com/2024/08/docker-e-backups/#respond</comments>
		
		<dc:creator><![CDATA[duarte]]></dc:creator>
		<pubDate>Sun, 04 Aug 2024 20:15:18 +0000</pubDate>
				<category><![CDATA[Avançado]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[sysadmin]]></category>
		<guid isPermaLink="false">http://192.168.1.84:8000/?p=1329</guid>

					<description><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 8</span> <span class="rt-label rt-postfix">min</span></span>Introdução O Docker tornou-se essencial hoje em dia&#8230; quase todos os produtos são distribuídos como containers e até muitas vezes nem há outra opção (os scripts de instalação começam a ser raros). O Docker Compose leva isto ainda mais longe, permitindo instalar e executar aplicações constituídas por múltiplos containers. E qual é o problema com &#8230; <a href="https://blog.viasig.com/2024/08/docker-e-backups/" class="more-link">Continuar a ler<span class="screen-reader-text">Docker e backups</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 8</span> <span class="rt-label rt-postfix">min</span></span>
<h3 class="wp-block-heading">Introdução</h3>



<p>O Docker tornou-se essencial hoje em dia&#8230; quase todos os produtos são distribuídos como containers e até muitas vezes nem há outra opção (os scripts de instalação começam a ser raros). O Docker Compose leva isto ainda mais longe, permitindo instalar e executar aplicações constituídas por múltiplos containers. </p>



<p>E qual é o problema com isto?</p>



<p>Bem, o problema é que quando um upgrade docker compose falha já numa fase avançada, por exemplo quando falham as migrações da base de dados, ficamos sem forma de voltar à versão anterior&#8230; se alguma coisa nos dados foi alterada pela nova versão, como fazemos para voltar à versão anterior que até funcionava tão bem!???</p>



<p>Este post discute o problema, fornece uma solução manual utilizando funcionalidades padrão do Docker, e apresenta uma solução mais avançada e automatizada para fazer backup de stacks Docker Compose. Aviso &#8211; este é o 1º artigo que escrevi com a ajuda do meu assistente pessoal virtual (neste artigo usei o chatgpt, e penso usar outros no futuro para comparar). Fiz alterações no texto, mas acho que se nota bem as secções que são 100% artificiais porque parecem anúncios e o português é um pouco &#8220;abrasileirado&#8221;.</p>



<span id="more-1329"></span>



<h3 class="wp-block-heading">Por Que o Docker Compose é Tão Popular</h3>



<p>O Docker Compose ganhou popularidade significativa devido a várias razões principais:</p>



<ol class="wp-block-list">
<li><strong>Configuração Simplificada de Multi-Containers</strong>: O Docker Compose permite definir e executar aplicações Docker multi-container usando um único ficheiro <code>docker-compose.yml</code>. Isso simplifica o processo de gerir aplicações complexas com múltiplos serviços.</li>



<li><strong>Facilidade de Uso</strong>: Com o Docker Compose, você pode facilmente iniciar, parar e configurar todos os seus serviços de aplicação usando comandos simples. Isso reduz a complexidade envolvida na gestão de containers individuais.</li>



<li><strong>Replicação de Ambiente</strong>: O Docker Compose facilita a replicação do mesmo ambiente em diferentes estágios de desenvolvimento, teste e produção. Isso garante consistência e reduz a probabilidade de problemas específicos do ambiente.</li>



<li><strong>Networking</strong>: O Docker Compose configura automaticamente a rede entre containers, permitindo que eles se comuniquem sem problemas. Isso é particularmente útil para arquiteturas de microserviços.</li>



<li><strong>Escalabilidade</strong>: O Docker Compose suporta a escalabilidade dos serviços para cima e para baixo com um único comando, facilitando o gerenciamento de cargas de trabalho variáveis.</li>
</ol>



<h3 class="wp-block-heading">O Problema</h3>



<p>O problema é simples: como podemos fazer um backup de todos os volumes usados por todos os containers num docker-compose.yml? Vamos tentar resolver estas 4 questões:</p>



<ol class="wp-block-list">
<li><strong>Consistência de Dados</strong>: Garantir que os dados sejam guardados num estado consistente , que é crucial especialmente para bases de dados e outros serviços em que o estado em disco é relevante na recuperação. O que isto quer dizer é que temos de parar os containers antes de fazer o backup. Vamos fazer stop em vez de down &#8211; explicação mais adiante.</li>



<li><strong>Recuperação de Desastres</strong>: Ter backups confiáveis é essencial para a recuperação de desastres. Em caso de perda ou corrupção de dados, você pode restaurar rapidamente seus serviços. &#8220;Obviously&#8221;&#8230;</li>



<li><strong>Rastreamento de Versões</strong>: Manter o controle das versões exatas das imagens Docker e das configurações usadas nos seus serviços garante que você possa recriar o mesmo ambiente se necessário. Ou seja, para voltarmos à &#8220;versão anterior&#8221; temos de guardar os ids das imagens que estavam em uso em cada container quando fizemos o backup.</li>



<li><strong>Eficiência</strong>: Usar compressão multi-thread acelera o processo de backup, economizando tempo e recursos. Isto porque hoje em dia, toda a gente que usa docker tem multi-cores&#8230; fazer uma compressão do backup usando apenas 1 thread é esperar mais tempo desnecessariamente.</li>
</ol>



<h3 class="wp-block-heading">O Processo Manual</h3>



<p>Tanto quanto sei o Docker não fornece uma solução abrangente out-of-the-box (OOTB) para funcionalidades avançadas de backup, mas tem os blocos de construção básicos necessários para criar backups. Vamos ver este processo passo-a-passo&#8230;</p>



<p>Se alguém souber de um processo &#8220;oficial&#8221; backup-restore ou snapshot por favor deixe aqui um comentário.</p>



<h4 class="wp-block-heading">Passo 1: Parar os Serviços</h4>



<p>Primeiro, paramos os serviços para garantir a consistência dos dados.</p>



<p><code>docker compose stop</code></p>



<p>Também podemos fazer docker compose down. A diferença do comando stop é que não destrói os containers&#8230; ou seja, ao fazermos stop/start os containers mantém o estado. Por exemplo, se alterámos alguma coisa num container como instalar um pacote, essa alteração mantém-se ao fazer start. Se fizermos down/up os containers são recriados no seu estado inicial, perdendo-se todas as alterações que tenhamos feito (exceto claro o que estiver guardado em volumes).</p>



<h4 class="wp-block-heading">Passo 2: Backup dos Volumes</h4>



<p>Em seguida, usamos os comandos <code>docker run</code> e <code>tar</code> para criar backups dos seus volumes. </p>



<p>Dado que os containers Docker são como máquinas temporárias, em cada reinicio voltam ao seu estado inicial e tudo o que lá pusemos de novo ou atualizado desaparece. Os Volumes são áreas de ficheiros onde podemos guardar dados que são mantidos mesmo quando reiniciamos os containers.</p>



<p>Ora, como explica a AI o que são volumes?</p>



<p>&#8220;Volumes são áreas de armazenamento persistente usadas por containers Docker para armazenar dados. Eles permitem que os dados sejam armazenados fora do ciclo de vida dos containers, garantindo que as informações permaneçam intactas mesmo após reinicializações ou recriações dos containers.&#8221;</p>



<p>Por exemplo,  os Volumes têm de ser usados em containers de bases de dados. De outra forma, quando se reinicializasse esse container a bd voltava ao 0.</p>



<p>Ou seja, um backup de um container é na verdade apenas o backup dos seus volumes. Fazer backup de um container não faz sentido algum&#8230;</p>



<p><code># Listar volumes </code><br><code>docker volume ls </code><br><code># Fazer backup de cada volume </code><br><code>docker run --rm -v &lt;nome_do_volume&gt;:/data -v &lt;pasta_local_para_backup&gt;:/backup busybox tar czf /backup/volume_name.tar.gz -C /data .</code></p>



<p>Aqui temos muito sumo para analisar&#8230; usamos 2 capacidades do docker: i) corremos um container temporário que é apagado assim que for terminado (opção -rm) e ii) ligamos este container temporário ao volume que queremos copiar (opção -v). Este é um truque elegante que tem várias coisas importantes: </p>



<ol class="wp-block-list">
<li>montamos o volume queremos guardar à pasta interna /data no container temporário;</li>



<li>montamos a pasta local onde queremos guardar o backup na pasta interna /backup</li>



<li>vamos usar o comando tar para comprimir a pasta interna /data para a pasta /backup;</li>



<li>os ficheiros na pasta interna /backup vão aparecer na &lt;pasta_local_para_backup&gt; fora do container, no próprio host.</li>
</ol>



<p>Pois é&#8230; um comando tão simples e afinal cheio de truques&#8230;</p>



<p>No script final, mais à frente, vamos fazer algumas coisas adicionais &#8211; vamos listar os volumes de cada container referido no docker-compose, incluindo volumes anónimos (sem nome). Isto permite automatizar o backup do grupo de containers.</p>



<h4 class="wp-block-heading">Passo 3: Guardar o Ficheiro Docker Compose</h4>



<p>Copiamos manualmente o ficheiro Docker Compose para o local do backup.</p>



<p><code>cp docker-compose.yml &lt;pasta_local_para_backup&gt;docker-compose_&lt;data&gt;.yml</code></p>



<p>Num processo de recriação do estado funcional anterior ao desastre vamos precisar do docker-compose.yml tal como estava antes de qualquer alteração. Também vamos precisar de saber a versão exata de cada container que estava em uso&#8230;</p>



<h4 class="wp-block-heading">Passo 4: Registrar as Versões das Imagens</h4>



<p>Registamos manualmente as versões das imagens usadas nos seus containers.</p>



<p><code># Listar todos os containers em execução docker ps </code><br><code># Para cada container, obter o ID da imagem </code><br><code>docker inspect --format='{{.Name}} {{.Image}}' container_id</code></p>



<p>Isto é fundamental&#8230; há containers com um ritmo acelerado de lançamento de novas versões. Para voltarmos ao estado inicial temos de saber as versões exatas, e alterar o docker-compose.yml para &#8220;tagar&#8221; essas versões, garantindo que puxamos as mesmas versões que estavam em uso no momento do backup (em geral são puxadas as versões mais recentes). Isto obrigará à edição do .yml antes de o usar.</p>



<h4 class="wp-block-heading">Passo 5: Reiniciar os Serviços</h4>



<p>Finalmente, voltamos a iniciar os containers:</p>



<p><code>docker-compose start </code></p>



<p>Isto serve apenas para voltar a ter os containers a funcionar. Uma vez que já fizemos o backup, podemos então prosseguir com o update dos containers.</p>



<h3 class="wp-block-heading">Solução Automatizada com Script</h3>



<p>Obviamente fazer isto tudo antes de fazermos um update aos nossos containers é absurdo&#8230; e a mim irrita-me ligeiramente que o docker não tenha um comando docker compose snapshot&#8230; mas enfim&#8230;</p>



<p>Já que vamos criar um script então mais vale usar compressão multi-thread e uma opção de dry run. Além disso procuramos volumes com e sem nome (anonymous). O nosso script vai chamar-se <code>compose_snapshot.sh</code>.</p>



<h4 class="wp-block-heading">Funcionalidades do Script</h4>



<ol class="wp-block-list">
<li><strong>Análise de Argumentos</strong>: O script aceita argumentos para o ficheiro Docker Compose, pasta de saída, número de threads para compressão e uma opção de dry run.</li>



<li><strong>Consistência de Dados</strong>: O script para todos os containers em execução antes de realizar o backup para garantir a consistência dos dados.</li>



<li><strong>Compressão Multi-Thread</strong>: O script usa <code>pigz</code> para compressão multi-thread, tornando o processo de backup mais rápido e eficiente.</li>



<li><strong>Rastreamento de Versões</strong>: O script salva os IDs exatos das imagens e o ficheiro Docker Compose usado para o backup, permitindo a recriação precisa do ambiente.</li>



<li><strong>Funcionalidade de Dry Run</strong>: O script inclui uma opção de dry run para listar os volumes que seriam backupados sem realizar o backup real.</li>
</ol>



<h4 class="wp-block-heading">O Script</h4>



<p>Aqui está o script <code>compose_snapshot.sh</code>, escrito a meias por mim e pelo meu novo assistente virtual (<s>tenho de lhe arranjar um nome&#8230;</s> ART (Asshole Research Transport)*):</p>



<pre class="wp-block-code"><code>#!/bin/bash

# Função para exibir informações de uso
usage() {
  echo "Uso: $0 -f &lt;compose_file&gt; -o &lt;output_folder&gt; -p &lt;num_threads&gt; &#91;--dry-run]"
  exit 1
}

DRY_RUN=false
NUM_THREADS=4

# Analisar argumentos
while getopts ":f:o:p:-:" opt; do
  case ${opt} in
    f )
      COMPOSE_FILE=$OPTARG
      ;;
    o )
      OUTPUT_FOLDER=$OPTARG
      ;;
    p )
      NUM_THREADS=$OPTARG
      ;;
    - )
      case "${OPTARG}" in
        dry-run)
          DRY_RUN=true
          ;;
        *)
          usage
          ;;
      esac
      ;;
    \? )
      usage
      ;;
  esac
done

# Verificar se todos os argumentos necessários são fornecidos
if &#91; -z "$COMPOSE_FILE" ] || &#91; -z "$OUTPUT_FOLDER" ] || &#91; -z "$NUM_THREADS" ]; then
  usage
fi

# Verificar se o ficheiro Docker Compose existe
if &#91; ! -f "$COMPOSE_FILE" ]; then
  echo "Erro: Ficheiro Compose $COMPOSE_FILE não encontrado."
  exit 1
fi

# Criar pasta de saída se não existir
mkdir -p "$OUTPUT_FOLDER"

# Obter o timestamp atual
timestamp=$(date +%Y%m%d%H%M%S)

# Copiar o ficheiro Docker Compose para a pasta de saída com o timestamp
cp "$COMPOSE_FILE" "$OUTPUT_FOLDER/$(basename "$COMPOSE_FILE" .yml)_${timestamp}.yml"

# Verificar se os serviços Docker Compose estão ativos
if ! docker compose -f "$COMPOSE_FILE" ps | grep -q "Up"; then
  echo "Erro: Serviços Docker Compose não estão em execução. Por favor, inicie os serviços usando 'docker compose -f $COMPOSE_FILE up -d' e tente novamente."
  exit 1
fi

# Obter todos os IDs dos containers do projeto Docker Compose
CONTAINER_IDS=$(docker compose -f "$COMPOSE_FILE" ps -q)

# Função para fazer backup de um volume
backup_volume() {
  local volume_name=$1
  local output_folder=$2
  local timestamp=$3
  local num_threads=$4
  local backup_file="$output_folder/${volume_name}_${timestamp}.tar.gz"

  if &#91; "$DRY_RUN" = true ]; then
    echo "Faria backup do volume $volume_name para $backup_file"
  else
    echo "Fazendo backup do volume $volume_name para $backup_file"
    docker run --rm -v "$volume_name:/mnt/volume" -v "$output_folder:/backup" alpine \
      sh -c "apk add --no-cache pigz &amp;&amp; tar cvf - -C /mnt/volume . | pigz -p $num_threads &gt; /backup/${volume_name}_${timestamp}.tar.gz"
  fi
}

if &#91; "$DRY_RUN" = false ]; then
  # Parar containers
  echo "Parando todos os containers..."
  docker compose -f "$COMPOSE_FILE" stop
fi

# Fazer backup dos volumes de cada container
for container_id in $CONTAINER_IDS; do
  # Obter os volumes montados de cada container
  VOLUMES=$(docker inspect --format '{{ range .Mounts }}{{ .Name }} {{ end }}' $container_id)

  for volume in $VOLUMES; do
    # Ignorar nomes de volumes vazios (montagens não de volumes)
    if &#91; -n "$volume" ]; then
      backup_volume "$volume" "$OUTPUT_FOLDER" "$timestamp" "$NUM_THREADS"
    fi
  done

  # Listar o ID da imagem de cada container
  IMAGE_ID=$(docker inspect --format '{{.Image}}' $container_id)
  CONTAINER_NAME=$(docker inspect --format '{{.Name}}' $container_id | cut -c2-)

  echo "Container $CONTAINER_NAME está a usar a imagem ID $IMAGE_ID" &gt;&gt; "$OUTPUT_FOLDER/image_ids_${timestamp}.txt"
done

if &#91; "$DRY_RUN" = false ]; then
  # Reiniciar containers
  echo "Iniciando todos os containers..."
  docker compose -f "$COMPOSE_FILE" start
fi

if &#91; "$DRY_RUN" = true ]; then
  echo "Dry run concluído. Nenhum volume foi backupado e nenhum container foi parado."
else
  echo "Backup concluído. IDs das imagens salvos em $OUTPUT_FOLDER/image_ids_${timestamp}.txt."
  echo "Ficheiro Docker Compose salvo em $OUTPUT_FOLDER/$(basename "$COMPOSE_FILE" .yml)_${timestamp}.yml."
fi</code></pre>



<h3 class="wp-block-heading">Conclusão</h3>



<p>O script <code>compose_snapshot.sh</code> é uma ferramenta para facilitar o backup de stacks Docker Compose de forma rápida, com garantia de consistência dos dados, compressão multi-thread, rastreamento de versões e com uma opção de dry run. Implementar uma solução de backup como esta não só protege os seus dados, mas também garante que você pode rapidamente recuperar e recriar o seu ambiente quando necessário. Mas pessoalmente é algo que quero fazer sempre e rapidamente antes de qualquer update a um stack docker-compose.</p>



<p>Nota 1: falta o script de restore! Que pretendo em breve publicar&#8230;</p>



<p>Nota 2: o método que uso atualmente é colocar o docker dentro de um container LXD. Antes de fazer um update aos containers, faço apenas 1 comando: lxc snapshot &lt;container&gt; &lt;nome_do_snapshot&gt;. Fácil e rápido. <br>Mas há coisas que não funcionam bem nesta abordagem, como usar GPUs. Daí o script&#8230;</p>



<p>Nota 3: há ferramentas que devem fazer backup de containers, como o portainer. Mas mascaram a mecânica das coisas, impedindo que aprendamos como a tecnologia funciona, e substituindo essa aprendizagem por outra que me parece menos útil.</p>



<p>*ART dos fantásticos <a href="https://en.wikipedia.org/wiki/The_Murderbot_Diaries">livros do MurderBot</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.viasig.com/2024/08/docker-e-backups/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Altimetria Portugal 25m</title>
		<link>https://blog.viasig.com/2021/11/altimetria-portugal-25m/</link>
					<comments>https://blog.viasig.com/2021/11/altimetria-portugal-25m/#comments</comments>
		
		<dc:creator><![CDATA[duarte]]></dc:creator>
		<pubDate>Sun, 21 Nov 2021 19:53:32 +0000</pubDate>
				<category><![CDATA[Dados]]></category>
		<category><![CDATA[Intermédio]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[SIG]]></category>
		<category><![CDATA[altimetria]]></category>
		<category><![CDATA[GDAL]]></category>
		<category><![CDATA[MDS]]></category>
		<category><![CDATA[MDT]]></category>
		<category><![CDATA[QGIS]]></category>
		<guid isPermaLink="false">http://192.168.1.84:8000/?p=1255</guid>

					<description><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 9</span> <span class="rt-label rt-postfix">min</span></span>Introdução Há alguns anos publiquei um artigo sobre a conversão de um modelo digital do terreno global para o sistema de coordenadas português e também cortado aos limites de Portugal Continental (https://blog.viasig.com/2010/03/mdt-30m-para-portugal/). Depois coloquei-o numa partilha online. Até hoje continua a ser procurado, embora tenha já feito várias referências para novos dados &#8211; melhores e &#8230; <a href="https://blog.viasig.com/2021/11/altimetria-portugal-25m/" class="more-link">Continuar a ler<span class="screen-reader-text">Altimetria Portugal 25m</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 9</span> <span class="rt-label rt-postfix">min</span></span>
<h2 class="wp-block-heading">Introdução</h2>



<p>Há alguns anos publiquei um artigo sobre a conversão de um modelo digital do terreno global para o sistema de coordenadas português e também cortado aos limites de Portugal Continental (<a href="https://blog.viasig.com/2010/03/mdt-30m-para-portugal/" target="_blank" rel="noreferrer noopener">https://blog.viasig.com/2010/03/mdt-30m-para-portugal/</a>). Depois coloquei-o numa partilha online. Até hoje continua a ser procurado, embora tenha já feito várias referências para novos dados &#8211; melhores e mais atuais.</p>



<p>Os dados que recomendo são da Agência Europeia do Ambiente &#8211; o EU-DEM &#8211; que pode ser obtido aqui: <a rel="noreferrer noopener" href="https://www.eea.europa.eu/data-and-maps/data/copernicus-land-monitoring-service-eu-dem" target="_blank">https://land.copernicus.eu/imagery-in-situ/eu-dem/eu-dem-v1.1?tab=metadata</a>. Estes dados são baseados no SRTM, melhorados com uma série de correções que estão documentadas.</p>



<p>Este mdt tem 25m de resolução, com um erro médio quadrático de +-7m!! O que me parece excelente. </p>



<p>Nota técnica &#8211; na realidade estes dados não são um mdt, mas sim um mds &#8211; modelo digital da superfície, ou seja, não representam a cota do terreno e sim o topo dos objetos na superfície, como árvores e edifícios e outras estruturas. Mas mesmo isto não é bem correto no caso do eu-dem&#8230; Aparentemente, estes dados podem representar o topo de objetos, como árvores e estruturas, mas, por outro lado, como sinais radar (usados na missão original) podem penetrar a canópia das árvores, também não há certeza que os dados representem a cota do topo das árvores.</p>



<p>Este artigo é muito simples &#8211; pretende disponibilizar uma versão pronta a usar para Portugal. Nada de especial &#8211; vamos apenas derivar uma versão que estará projetada para o nosso sistema de coordenadas, e cortada à extensão do nosso país (continente), usando apenas o QGIS. No fim do artigo há um link para descarregar os dados finais preparados para Portugal.</p>



<span id="more-1255"></span>



<h2 class="wp-block-heading">Obter os dados</h2>



<p>Os dados são fáceis de obter &#8211; estão divididos em quadrículas de 1.000km de lado, em formato tiff, 32bit, e Portugal abrange 2 destas quadrículas. Podemos vê-las usando o visualizador que encontramos no link acima:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><a href="https://blog.viasig.com/wp-content/uploads/2021/11/image.png"><img fetchpriority="high" decoding="async" width="414" height="440" src="https://blog.viasig.com/wp-content/uploads/2021/11/image.png" alt="" class="wp-image-1257" style="width:563px;height:auto" srcset="https://blog.viasig.com/wp-content/uploads/2021/11/image.png 414w, https://blog.viasig.com/wp-content/uploads/2021/11/image-282x300.png 282w" sizes="(max-width: 414px) 100vw, 414px" /></a><figcaption class="wp-element-caption">Portugal abrange 2 quadrículas de dados do EU-DEM</figcaption></figure></div>


<p>Como vemos, temos de descarregar as quadrículas E10N10 e E20N20. Vamos ao separador Download, e escolhemos estas quadrículas. Descarregamos e passamos ao processamento em QGIS.</p>



<h2 class="wp-block-heading">Visualizar em QGIS</h2>



<p>Os dados estão zipados. Descomprimimos e obtemos 1 tif por quadrícula que podemos carregar no QGIS:</p>



<figure class="wp-block-image size-full"><a href="https://blog.viasig.com/wp-content/uploads/2021/11/image-1.png"><img decoding="async" width="679" height="401" src="https://blog.viasig.com/wp-content/uploads/2021/11/image-1.png" alt="" class="wp-image-1258" srcset="https://blog.viasig.com/wp-content/uploads/2021/11/image-1.png 679w, https://blog.viasig.com/wp-content/uploads/2021/11/image-1-300x177.png 300w" sizes="(max-width: 679px) 100vw, 679px" /></a><figcaption class="wp-element-caption">As 2 quadrículas originais visualizadas no QGIS</figcaption></figure>



<p>Abrimos as propriedades dos 2 ficheiros e vemos a seguinte informação sobre os ficheiros:</p>



<ul class="wp-block-list">
<li>Projeção &#8211; IGNF:ETRS89LAEA &#8211; ETRS89 Lambert Azimutal Equal Area</li>



<li>Resolução espacial: 25m</li>



<li>Largura e Altura: 40.000&#215;40.000 pixeis (1.000kmx1.000km)</li>



<li>Tipo de pixel: 32bit</li>



<li>Compressão: LZW</li>



<li>Pirâmides: Sim</li>



<li>Valor &#8220;nulo&#8221; (no data): -3.40282e+38</li>



<li>Tamanho total em disco: 983.45MB + 956.04 MB</li>
</ul>



<h2 class="wp-block-heading">Plano de Ação</h2>



<p>Então qual é o nosso plano de ação?</p>



<ol class="wp-block-list">
<li>Vamos juntar os 2 ficheiros num mosaico virtual, que praticamente não ocupa espaço em disco,  mas representa todos os dados como um só conjunto;</li>



<li>Vamos cortar este mosaico virtual pelos limites de portugal;</li>



<li>E vamos reprojetar para o sistema de coordenadas português. Vamos também escolher uma compressão eficiente e que conserve os dados sem alterações;</li>



<li>E no fim, zipamos e colocamos algures online para a malta usar.</li>
</ol>



<p>Para o corte vamos usar a Carta Administrativa Oficial Portuguese disponível no site da DGT.</p>



<h2 class="wp-block-heading">1. Unir 2 ficheiros raster num mosaico virtual</h2>



<p>Isto é um truque &#8211; criar ficheiros virtuais que são apenas pequenos ficheiros de texto que descrevem as operações que queremos fazer, mas sem as fazer realmente. Isto permite criar novas representações dos nossos dados sem ocupar espaço em disco, mas em troca, ocupamos mais o processador e a memória. Já falei várias vezes sobre este fantástico formato VRT, e pode-se <a href="https://gdal.org/drivers/raster/vrt.html">ler mais sobre ficheiros VRT aqui</a>.</p>



<p>Para criar um ficheiro VRT a partir de outros ficheiros, usamos a ferramenta &#8220;Criar raster virtual&#8221; nas ferramentas de processamento do QGIS. Aqui, indicamos os 2 ficheiros que queremos incluir no VRT. A vantagem é que em vez de esperarmos que quase 2GB de dados sejam mastigados para criar um novo ficheiro de mais 2GB, vamos apenas criar muito rapidamente um pequeno ficheiro de texto com 2kb:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img decoding="async" width="656" height="751" src="/wp-content/uploads/2021/11/criar_raster_virtual.jpg" alt="" class="wp-image-1281" srcset="https://blog.viasig.com/wp-content/uploads/2021/11/criar_raster_virtual.jpg 656w, https://blog.viasig.com/wp-content/uploads/2021/11/criar_raster_virtual-262x300.jpg 262w" sizes="(max-width: 656px) 100vw, 656px" /></figure></div>

<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="572" height="290" src="https://blog.viasig.com/wp-content/uploads/2021/11/criar_raster_virtual_2.jpg" alt="" class="wp-image-1282" srcset="https://blog.viasig.com/wp-content/uploads/2021/11/criar_raster_virtual_2.jpg 572w, https://blog.viasig.com/wp-content/uploads/2021/11/criar_raster_virtual_2-300x152.jpg 300w" sizes="auto, (max-width: 572px) 100vw, 572px" /><figcaption class="wp-element-caption">Na imagem de cima vemos a ferramenta &#8220;Criar raster virtual&#8221; (VRT). Na imagem de baixo vemos a seleção das imagens para incluir neste VRT.</figcaption></figure></div>


<p>O resultado é um ficheiro que se comporta como uma só imagem, que no fundo serve apenas de apontador para 2 ficheiros TIF originais:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><a href="https://blog.viasig.com/wp-content/uploads/2021/11/vrt_no_qgis.jpg"><img loading="lazy" decoding="async" width="513" height="750" src="/wp-content/uploads/2021/11/vrt_no_qgis.jpg" alt="" class="wp-image-1284" srcset="https://blog.viasig.com/wp-content/uploads/2021/11/vrt_no_qgis.jpg 513w, https://blog.viasig.com/wp-content/uploads/2021/11/vrt_no_qgis-205x300.jpg 205w" sizes="auto, (max-width: 513px) 100vw, 513px" /></a><figcaption class="wp-element-caption">Como aparece o VRT no QGIS &#8211; um só ficheiro que mostra os dados dos 2 ficheiros TIF.</figcaption></figure></div>


<p>De seguida, vamos reprojetar este mosaico virtual para o sistema de coordenadas português.</p>



<h2 class="wp-block-heading">2. e 3. Cortar e Reprojetar</h2>



<p>Bom, reprojetar em QGIS é facílimo. Mas para complicar um bocadinho, vamos cortar e reprojetar num só passo! ahpoisé&#8230;</p>



<p>Podemos usar a ferramenta de corte para reprojetar porque tem lá a opção para escolher um sistema de coordenadas diferente para o ficheiro de saída. Assim, é escusado executar depois outra ferramenta só para a reprojeção.</p>



<p>Em primeiro lugar, temos de arranjar o polígono de Portugal continental para cortar o nosso mosaico virtual. A <a href="https://www.dgterritorio.gov.pt/cartografia/cartografia-tematica/caop" target="_blank" rel="noreferrer noopener">CAOP está disponível para download no site da DGT</a>.</p>



<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2021/11/portugal_e_mdt.jpg"><img loading="lazy" decoding="async" width="720" height="678" src="/wp-content/uploads/2021/11/portugal_e_mdt.jpg" alt="" class="wp-image-1286" srcset="https://blog.viasig.com/wp-content/uploads/2021/11/portugal_e_mdt.jpg 720w, https://blog.viasig.com/wp-content/uploads/2021/11/portugal_e_mdt-300x283.jpg 300w" sizes="auto, (max-width: 720px) 100vw, 720px" /></a><figcaption class="wp-element-caption">CAOP alterada no QGIS com o mdt que queremos cortar.</figcaption></figure>



<p>Vê-se bem que dei um toquezinho nos limites de Portugal &#8211; o que fiz foi aumentar um pouco a parte litoral para que não deixe nada de fora &#8211; é que o eu-dem não tem exatamente os mesmos contornos que a nossa CAOP, como seria de esperar. Por isso, ao aumentar a parte litoral quis evitar deixar de fora algumas partes do eu-dem.</p>



<p>Para fazer o corte do raster com um ficheiro vetorial, usamos a ferramenta &#8220;Recortar raster pela camada de máscara&#8221;. Aqui vamos usar alguns truques que explico a seguir:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><a href="/wp-content/uploads/2021/11/recortar_reprojetar_por_portugal2_inteiro.jpg"><img loading="lazy" decoding="async" width="611" height="1024" src="/wp-content/uploads/2021/11/recortar_reprojetar_por_portugal2_inteiro-611x1024.jpg" alt="" class="wp-image-1287" srcset="https://blog.viasig.com/wp-content/uploads/2021/11/recortar_reprojetar_por_portugal2_inteiro-611x1024.jpg 611w, https://blog.viasig.com/wp-content/uploads/2021/11/recortar_reprojetar_por_portugal2_inteiro-179x300.jpg 179w, https://blog.viasig.com/wp-content/uploads/2021/11/recortar_reprojetar_por_portugal2_inteiro.jpg 659w" sizes="auto, (max-width: 611px) 100vw, 611px" /></a><figcaption class="wp-element-caption">Ferramenta de corte, onde aproveitamos para reprojetar e comprimir o resultdo.</figcaption></figure></div>


<p>A maioria das opções usadas não têm nada de especial: escolhemos o ficheiro a cortar (mdt), o ficheiro de corte (portugal), uma compressão elevada, e o ficheiro de saída. Mas algumas opções são menos óbvias:</p>



<ul class="wp-block-list">
<li>Na compressão elevada, podemos mudar o parâmetro <strong>&#8220;PREDICTOR&#8221; para o valor 3</strong>, que é mais eficiente com valores decimais (que é o nosso caso);</li>



<li>Nos parâmetros adicionais, vamos incluir &#8220;<strong>-co tiled=yes</strong>&#8221; para produzir um ficheiro organizado por blocos comprimidos (isto é importante porque permite melhor compressão e desempenho);</li>



<li>Nos parâmetros adicionais vamos também aproveitar para dar mais memória ao processamento (é isso que fazem os parâmetros GDAL_CACHEMAX e o WM).</li>
</ul>



<p>Estas opções em conjunto fazem o processo mais rápido e permitem obter um ficheiro mais pequeno.</p>



<p>O ficheiro resultante tem as seguintes características:</p>



<ul id="block-4e2b302d-4274-47a7-a963-4545d6295288" class="wp-block-list">
<li>Projeção &#8211; ETRS89 PT TM06 (3763)</li>



<li>Resolução espacial: 24,99m</li>



<li>Largura e Altura: 11.633&#215;23.220 pixeis (290kmx580km)</li>



<li>Tipo de pixel: 32bit</li>



<li>Compressão: Deflate, Level 9, Predictor 3</li>



<li>Pirâmides: Não</li>



<li>Valor &#8220;nulo&#8221; (no data): -3.40282e+38</li>



<li>Tamanho total em disco: 346,39 MB</li>
</ul>



<p>E pronto, o resultado é um mds/mdt para Portugal, já no nosso sistema de coordenadas. Para visualizar, alteramos o sistema de coordenadas do projeto para ETRS89 PT TM06, e vemos que a forma e orientação já é familiar:</p>



<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2021/11/image-8.png"><img loading="lazy" decoding="async" width="514" height="506" src="/wp-content/uploads/2021/11/image-8.png" alt="" class="wp-image-1288" srcset="https://blog.viasig.com/wp-content/uploads/2021/11/image-8.png 514w, https://blog.viasig.com/wp-content/uploads/2021/11/image-8-300x295.png 300w" sizes="auto, (max-width: 514px) 100vw, 514px" /></a><figcaption class="wp-element-caption">XXXaarãã &#8211; modelo de elevação para Portugal, com 25m de resolução e erro EMQ de +-7m.</figcaption></figure>



<p>Podemos melhorar um pouco o estilo e clareza da visualização alterando a simbologia, e também podemos criar pirâmides/overviews/&#8221;vistas gerais&#8221; para acelerar a visualização a qualquer escala.</p>



<h2 class="wp-block-heading">Pirâmides/overviews/&#8221;vistas gerais&#8221;</h2>



<p>As &#8220;vistas gerais&#8221;, tradução de pirâmides ou overviews, também são referidas neste blog <a href="/2020/03/overviews-gdal-em-modo-turbo/" target="_blank" rel="noreferrer noopener">exaustivamente</a>&#8230; são versões de resoluções cada vez menores e rápidas (pixel cada vez maior), que tornam a visualização dos dados extremamente rápida &#8211; o software escolhe automaticamente que resolução mostra para cada escala.</p>



<p>O costume é usar compressão jpeg, mas neste caso não é possível porque não é compatível com dados 32 bit. Isto foi um pretexto para ir ver as novidades em termos de compressão, e há muitas. Um artigo excelente que compara os novos métodos LERC e ZSTD é o &#8220;<a rel="noreferrer noopener" href="https://kokoalberti.com/articles/geotiff-compression-optimization-guide/" data-type="URL" data-id="https://kokoalberti.com/articles/geotiff-compression-optimization-guide/" target="_blank">Guide to GeoTIFF compression and optimization with GDAL</a>&#8221; do Koko Alberti &#8211; tem no blog mais gemas preciosas que vale a pena ler&#8230;</p>



<p>Então, olhando para este artigo vemos que a compressão mais compacta e mais rápida para ficheiros de 32bit é o ZSTD com predictor 3, muitíssimo superior à compressão Deflate e ainda por cima muito mais rápida de visualizar!! Mas mais à frente neste artigo o Koko olha para uma compressão que degrada os dados, a LERC (Limited Error Raster Compression), que rebenta com a escala de compressão&#8230; claro que perde dados, e por isso compara-se diretamente com jpeg. Mas tem a vantagem de podermos definir o erro máximo que queremos tolerar. Sendo para pirâmides que servem apenas para visualizar, será uma excelente opção! Qual é o problema?? O GDAL permite criar pirâmides neste formato mas não permite que se defina os parâmetros de compressão, e por isso, não conseguimos definir o erro admissível&#8230; para já está fora de ação&#8230;</p>



<p>Então, podemos criar as vistas gerais (não me habituo a esta tradução&#8230;) usando a compressão ZSTD com predictor=3:</p>



<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2021/11/criar_vistatasgerais_zstd.jpg"><img loading="lazy" decoding="async" width="684" height="559" src="/wp-content/uploads/2021/11/criar_vistatasgerais_zstd.jpg" alt="" class="wp-image-1292" srcset="https://blog.viasig.com/wp-content/uploads/2021/11/criar_vistatasgerais_zstd.jpg 684w, https://blog.viasig.com/wp-content/uploads/2021/11/criar_vistatasgerais_zstd-300x245.jpg 300w" sizes="auto, (max-width: 684px) 100vw, 684px" /></a><figcaption class="wp-element-caption">Criar vistas gerais na nova compressão zstd.</figcaption></figure>



<p>É produzido um ficheiro .ovr com o tamanho de 126MB. Para os dados em causa, esta compressão foi praticamente igual à &#8220;High compression&#8221; do QGIS&#8230; não sei se vale a pena.</p>



<p>E terminámos&#8230; o restante é só para nerds&#8230; o link para download está no fim do artigo.</p>



<p>Só por carolice, tentei comprimir este ovr com compressão <strong>LERC_DEFLATE </strong>e um erro de 0,5m, depois adicionei-lhe pirâmides, e <strong>obtive um tamanho de 66MB, perto de metade</strong>!!!! Como é apenas para visualização, é uma opção incrível quando não conseguimos usar JPEG. (Mas não se esqueçam que ao fazer identify no mdt, vão obter o valor visível, logo se querem ver a cota &#8220;verdadeira&#8221; têm de fazer zoom até verem a imagem base e não as pirâmides!)</p>



<h2 class="wp-block-heading">Converter de 32bit para inteiros 16bit</h2>



<p>Como sou do século passado e acho que espaço em disco é valioso, vou converter de 32bit para 16bit, porque as elevações no nosso território variam de -5 a 2000 e qualquer coisa metros. Estes valores cabem perfeitamente em 16bit. Mas como 16bit têm de ser inteiros (porque no qgis não há reais de 16bit), também vamos deitar fora as casas decimais… para um erro médio quadrático de 7m, e para os usos em causa, parece-me que não é grave deitar fora ou ganhar até 0,5m de elevação.</p>



<p>Sendo sincero, eu costumo fazer isto na linha de comando, com o GDAL. Mas o desafio aqui era fazer tudo em QGIS, que tem funções próprias e também acesso a todas as ferramentas do GDAL, disponibilizando uma interface de utilizador simpática.</p>



<p>Há várias formas de fazer esta conversão, mas temos de ter cuidado porque não queremos alterar os valores. No nosso caso, queremos preservar os valores de altimetria e passá-los apenas a inteiros de 16bit. Isto porque em 16bit os valores podem variar entre -32768 e +32767 , portanto mais que suficiente para guardar os nossos valores. O único valor que será convertido será o valor nulo que passará automaticamente a -32768. É que há vários algoritmos que recalculam os valores para que fiquem proporcionalmente na mesma &#8220;posição&#8221; dentro do novo domínio de valores possíveis. Por exemplo, se passarmos de 32bit para 16bit estes algoritmos partem do princípio que existem dados fora do intervalo válido de 16bit e por isso usam uma interpolação linear para os colocar neste intervalo. Assim, um valor de 2147483647 passaria a 32768, e por aí fora.</p>



<p>Então para manter os valores, a ferramenta que usei foi a Converter (Translate): <a rel="noreferrer noopener" href="https://docs.qgis.org/3.22/en/docs/user_manual/processing_algs/qgis/rasteranalysis.html#round-raster" target="_blank">https://docs.qgis.org/3.22/en/docs/user_manual/processing_algs/qgis/rasteranalysis.html#round-raster</a>. Esta ferramenta é apenas uma interface para o comando GDAL &#8211; gdal_translate, que permite uma imensidão de parâmetros, mas nós queremos apenas fazer 2 coisas: passar a 16bit e manter a compressão do original:</p>



<figure class="wp-block-image size-large"><a href="https://blog.viasig.com/wp-content/uploads/2021/11/image-2.png"><img loading="lazy" decoding="async" width="778" height="846" src="https://blog.viasig.com/wp-content/uploads/2021/11/image-2.png" alt="" class="wp-image-1263" srcset="https://blog.viasig.com/wp-content/uploads/2021/11/image-2.png 778w, https://blog.viasig.com/wp-content/uploads/2021/11/image-2-276x300.png 276w, https://blog.viasig.com/wp-content/uploads/2021/11/image-2-768x835.png 768w" sizes="auto, (max-width: 778px) 100vw, 778px" /></a><figcaption class="wp-element-caption">Convertendo de 32bit para 16bit, com compressão, só com opções na interface (Tipo de dados de saída=Int16).</figcaption></figure>



<p>Produzimos assim um ficheiro de apenas 68MB&#8230; Mais as pirâmides com apenas 30MB. Faz alguma diferença&#8230; como apenas removemos a parte decimal das cotas, o erro máximo é inferior +-0,5m:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="640" height="455" src="https://blog.viasig.com/wp-content/uploads/2021/11/dem-eu_16bit_vs_original32bit-1.jpg" alt="" class="wp-image-1294" srcset="https://blog.viasig.com/wp-content/uploads/2021/11/dem-eu_16bit_vs_original32bit-1.jpg 640w, https://blog.viasig.com/wp-content/uploads/2021/11/dem-eu_16bit_vs_original32bit-1-300x213.jpg 300w" sizes="auto, (max-width: 640px) 100vw, 640px" /><figcaption class="wp-element-caption">Comparando valores inteiros 16bit com valores reais 32bit. Neste caso o erro foi de 0,406m.</figcaption></figure>



<h2 class="wp-block-heading">Conclusão</h2>



<p>Bem, aquilo que era para ser um simples artigo para disponibilizar um ficheiro de altimetria para Portugal, acabou por ficar um bocadinho extenso <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>O ficheiro zipado 32bit está aqui: <a href="https://blog.viasig.com/wp-content/uploads/2021/11/eu-dem_portugal_32bit.zip">https://blog.viasig.com/eu-dem_portugal_32bit.zip</a>.</p>



<p>E para quem quiser algo mais pequeno e não se importar de usar cotas inteiras (sem parte decimal) tem aqui a versão 16bit: <a href="https://blog.viasig.com/wp-content/uploads/2021/11/eu-dem-portugal-16bit.zip">https://blog.viasig.com/eu-dem-portugal-16bit.zip</a>.</p>



<p>Até breve, e qualquer coisa deixem comentário.</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.viasig.com/2021/11/altimetria-portugal-25m/feed/</wfw:commentRss>
			<slash:comments>13</slash:comments>
		
		
			</item>
		<item>
		<title>Overviews GDAL em modo Turbo</title>
		<link>https://blog.viasig.com/2020/03/overviews-gdal-em-modo-turbo/</link>
					<comments>https://blog.viasig.com/2020/03/overviews-gdal-em-modo-turbo/#comments</comments>
		
		<dc:creator><![CDATA[duarte]]></dc:creator>
		<pubDate>Mon, 02 Mar 2020 19:40:43 +0000</pubDate>
				<category><![CDATA[Avançado]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[SIG]]></category>
		<category><![CDATA[GDAL]]></category>
		<category><![CDATA[Mosaicos]]></category>
		<category><![CDATA[QGIS]]></category>
		<guid isPermaLink="false">http://192.168.1.84:8000/?p=1136</guid>

					<description><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 7</span> <span class="rt-label rt-postfix">min</span></span>TLDR:  Neste post discutimos formas de acelerar o processo, e no fim usamos um script que reduz o tempo de processamento em 20%-50%. O script é apresentado abaixo e está no github.]]></description>
										<content:encoded><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 7</span> <span class="rt-label rt-postfix">min</span></span>
<p>TLDR:  Neste post discutimos formas de acelerar o processo de criação de overviews, e no fim usamos um script que reduz o tempo de processamento em 20%-50%. O script é apresentado abaixo e está no github.</p>



<p>Na visualização de rasters é obrigatório construir as overviews ou pirâmides, para conseguirmos uma visualização rápida. </p>



<p>As overviews são uma série de cópias do nosso raster com resoluções cada vez menores (pixeis maiores), e geralmente cada nível aplica uma redução de 50% na resolução. Por exemplo, numa resolução original de 0,30m/pixel, as overviews são imagens com resoluções de 0,60 &#8211; 1,20 &#8211; 2,40m/pixel e assim sucessivamente até que não faz sentido reduzir mais a imagem.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><a href="https://eurogeographics.org/wp-content/uploads/2018/04/WCS-NLSS.pdf" target="_blank" rel="noreferrer noopener"><img loading="lazy" decoding="async" width="448" height="358" src="https://blog.viasig.com/wp-content/uploads/2020/03/image-6.png" alt="" class="wp-image-1122" srcset="https://blog.viasig.com/wp-content/uploads/2020/03/image-6.png 448w, https://blog.viasig.com/wp-content/uploads/2020/03/image-6-300x240.png 300w" sizes="auto, (max-width: 448px) 100vw, 448px" /></a><figcaption>Overviews ou pirâmides permitem uma visualização rápida de rasters, através de imagens de resolução reduzida. (Obitdo em: https://eurogeographics.org/wp-content/uploads/2018/04/WCS-NLSS.pdf.)</figcaption></figure></div>



<p>Em geral, a construção destas pirâmides é feito com o comando <a href="https://gdal.org/programs/gdaladdo.html" target="_blank" rel="noreferrer noopener" aria-label="gdaladdo (opens in a new tab)">gdaladdo</a>, e é o processo mais moroso quando processamos grandes áreas. Nem a conversão com compressão, nem a união de muitos rasters leva tanto tempo.</p>



<p>Actualmente, com discos SSD rapidíssimos e memória super-abundante, e processadores multi-core, o comando gdaladdo que constrói overviews continua a usar apenas 1 core&#8230; por outro lado, é mais lento que outros comandos, como o gdal_translate.</p>



<p>Recentemente processei novos mosaicos para o Alentejo, desta vez com ortofotomapas com 0,30m de resolução, rgb+nir. E, claro, construir overviews foi uma tortura&#8230; mais de 8h para cada metade (dividi a área em 2 blocos este/oeste). O processador nunca passou dos 17% (i7 de 4 cores/8threads), e o disco SSD nunca passou de uns miseráveis 5MB/s (quando o disco é capaz de 1000MB/s). Muito frustrante&#8230;</p>



<p>O processo que uso consiste sempre em manter os ficheiros independentes, e criar um mosaico .vrt. Por hábito não crio mosaicos tif enormes. Este processo é descrito em <a rel="noreferrer noopener" aria-label="artigos anteriores (opens in a new tab)" href="https://blog.viasig.com/2013/12/mosaicos-com-areas-transparentes/" target="_blank">artigos anteriores</a>.</p>



<p>Depois de pesquisar online, vi 3 sugestões para melhorar o tempo de criar overviews: </p>



<ul class="wp-block-list"><li>Criar uma escada de vrt&#8217;s e construir um nível de overviews diferente para cada um em paralelo usando o gdal_translate, e depois configurá-los para que o 1º referencie o 2º, e este o 3º, e por ai fora. Mais info aqui: <a href="http://osgeo-org.1560.x6.nabble.com/gdal-dev-Scale-dependent-VRT-for-overviews-td4966814.html">http://osgeo-org.1560.x6.nabble.com/gdal-dev-Scale-dependent-VRT-for-overviews-td4966814.html</a>.</li><li>Ter 2 cópias iguais do vrt,  construir níveis diferentes de overviews para cada vrt com 2 comandos simultâneos, e depois juntá-los num só overview usando o comando tiffcp!! Mais info aqui: <a href="https://gis.stackexchange.com/questions/281890/how-to-add-other-images-as-tiff-overviews">https://gis.stackexchange.com/questions/281890/how-to-add-other-images-as-tiff-overviews</a>.</li><li>Criar imagens de resolução reduzida, usando o gdal_translate, e renomear estas imagens com extensão .ovr repetida, ou seja, mosaico.vrt.ovr, depois mosaico.vrt.ovr.ovr, e sucessivamente. Embora com ficheiros a mais, pareceu-me muito rápido.</li></ul>



<p>Isto ensinou-me uma série de coisas novas:</p>



<ol class="ticss-0bfc864e wp-block-list"><li>Os ficheiros .ovr são na verdade ficheiros TIFF multi-página (herança do tempo dos faxes!), onde um tiff é &#8220;colado&#8221; a outro dentro do mesmo ficheiro. Eu não sabia isto sobre os  .ovr. Ou seja, cada resolução é um tiff, dentro do ovr, que é também um tiff (matrioska?).</li><li>É possível juntar vários tiff num só tiff multi-página usando o comando &#8220;tiffcp tiff1 tiff2 tiffunido&#8221;.</li><li>O OSGEO4W inclui uma versão &#8220;geo-activada&#8221; dos comandos tiff, mantendo as características SIG dos ficheiros.</li><li>Podemos ter overviews de overviews, juntando a extensão .ovr ao ficheiro .ovr anterior, numa sucessão que funciona em gdal, qgis, e arcgis. Deve funcionar nos restantes programas, como geoserver, mapserver, etc.</li></ol>



<span id="more-1136"></span>



<h2 class="wp-block-heading">Teste</h2>



<p>Vamos fazer um teste com uma série mais pequena de ortofotomapas, para vermos qual é a melhoria no tempo de criação de overviews: vamos usar 3 processos simultânos de gdal_translate, onde cada processo constrói um resample diferente (x2, x4, x8), e renomeando-os para terem extensão .ovr acrescida.</p>



<p>A nossa coleção de ortos de testes é constituída por:</p>



<ul class="wp-block-list"><li>29 ficheiros 3 bandas x 8 bit, num total de 276MB, já comprimidos em tiff/jpeg, com 5km de lado, e 0,30m de resolução.</li><li>Um mosaico virtual .vrt com todos os 29 ortos, &#8220;teste_script.vrt&#8221;, com dimensão de 166.667 x 100.000 pixeis.</li></ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="991" height="513" src="https://blog.viasig.com/wp-content/uploads/2020/03/image.png" alt="" class="wp-image-1111" srcset="https://blog.viasig.com/wp-content/uploads/2020/03/image.png 991w, https://blog.viasig.com/wp-content/uploads/2020/03/image-300x155.png 300w, https://blog.viasig.com/wp-content/uploads/2020/03/image-768x398.png 768w" sizes="auto, (max-width: 991px) 100vw, 991px" /><figcaption>Quadrículas dos 29 ortofotomapas do nosso teste.</figcaption></figure>



<p>O método consiste em executar 3 comandos em simultâneo:</p>



<ul class="wp-block-list"><li>Processo 1: resample para 0,6m/pixel</li><li>Processo 2: resample para 1,2m/pixel</li><li>Processo 3: resample para 2,4m/pixel, mais construção de pirâmides para este resample apenas</li></ul>



<p>Assim, no processo 1 teremos este comando:</p>



<pre class="wp-block-preformatted">gdal_translate -of gtiff -tr 0.6 0.6 -ro -r average --config GDAL_CACHEMAX 1024 -co photometric=ycbcr -co interleave=pixel -co tiled=yes -co compress=jpeg teste_script.vrt teste_script.vrt.ovr</pre>



<p>Ou seja, construimos uma cópia do mosaico, em formato tiff, com 2x o tamanho do pixel original (0,6m/pixel) e damos o nome certo para que seja automaticamente reconhecido como overviews do original -&gt; teste_script.vrt.ovr.</p>



<p>No processo 2, construímos um resample com 4x o tamanho do pixel (1,2m/pixel), e damos o nome que o faz ser reconhecido como overviews do 1º processo:</p>



<pre class="wp-block-preformatted">gdal_translate -of gtiff -tr 1.2 1.2 -ro -r average --config GDAL_CACHEMAX 1024 -co photometric=ycbcr -co interleave=pixel -co tiled=yes -co compress=jpeg teste_script.vrt teste_script.vrt.ovr.ovr  </pre>



<p>No processo 3, construímos o 3º nível, com 8x a resolução (2,4m/pixel), e com um nome que o marque como as overviews do 2º nível:</p>



<pre class="wp-block-preformatted">gdal_translate -of gtiff -tr 2.4 2.4 -ro -r average --config GDAL_CACHEMAX 1024 -co photometric=ycbcr -co interleave=pixel -co tiled=yes -co compress=jpeg teste_script.vrt teste_script.vrt.ovr.ovr.ovr</pre>



<p>Já que sabemos que este resample é muitíssimo mais rápido que o 1º, terminando por isso muito cedo, podemos aproveitar para criar pirâmides para este 3º nível. Isto permitirá termos a série completa de overviews no final:</p>



<pre class="wp-block-preformatted">gdaladdo -ro -r average --config GDAL_CACHEMAX 1024 --config COMPRESS_OVERVIEW JPEG --config PHOTOMETRIC_OVERVIEW YCBCR --config INTERLEAVE_OVERVIEW PIXEL  teste_script.vrt.ovr.ovr.ovr</pre>



<p>O script faz uma série de correções aos nomes dos ficheiros caso detecte uma máscara externa, que é o caso do nosso teste (ficheiro .msk). Ficamos assim com os seguintes ficheiros:</p>



<pre class="wp-block-preformatted">      50&nbsp;194 teste_script.vrt
  12&nbsp;434&nbsp;020 teste_script.vrt.msk
   6&nbsp;003&nbsp;920 teste_script.vrt.msk.ovr
   1&nbsp;525&nbsp;126 teste_script.vrt.msk.ovr.ovr
     395&nbsp;087 teste_script.vrt.msk.ovr.ovr.ovr
     267&nbsp;858 teste_script.vrt.msk.ovr.ovr.ovr.ovr
 466&nbsp;889&nbsp;237 teste_script.vrt.ovr
 116&nbsp;024&nbsp;726 teste_script.vrt.ovr.ovr
  32&nbsp;529&nbsp;152 teste_script.vrt.ovr.ovr.ovr
  11&nbsp;135&nbsp;760 teste_script.vrt.ovr.ovr.ovr.ovr
               10 File(s)    647&nbsp;255&nbsp;080 bytes</pre>



<p>O tempo de execução foi de 06:47,4 min. E podemos ver a ocupação de CPU, disco e memória muito mais altos:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="437" src="https://blog.viasig.com/wp-content/uploads/2020/03/image-12-1024x437.png" alt="" class="wp-image-1140" srcset="https://blog.viasig.com/wp-content/uploads/2020/03/image-12-1024x437.png 1024w, https://blog.viasig.com/wp-content/uploads/2020/03/image-12-300x128.png 300w, https://blog.viasig.com/wp-content/uploads/2020/03/image-12-768x328.png 768w, https://blog.viasig.com/wp-content/uploads/2020/03/image-12-1536x655.png 1536w, https://blog.viasig.com/wp-content/uploads/2020/03/image-12.png 1800w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>E funciona? Vamos a ver&#8230;</p>



<pre class="wp-block-preformatted">gdalinfo teste_script.vrt
 Driver: VRT/Virtual Raster
 Files: teste_script.vrt
        teste_script.vrt.ovr
        teste_script.vrt.ovr.ovr
        teste_script.vrt.ovr.ovr.ovr
        teste_script.vrt.ovr.ovr.ovr.ovr
        teste_script.vrt.msk
        230_060_irg.tif
        230_065_irg.tif
...  ...  ...  ...  ...
Size is 166667, 100000
 Coordinate System is:
... ... ... ... ...
Band 1 Block=128x128 Type=Byte, ColorInterp=Red
   Min=0.000 Max=255.000
   Minimum=0.000, Maximum=255.000, Mean=109.688, StdDev=100.399
   <strong>Overviews: 83334x50000, 41667x25000, 20833x12500, 10417x6250, 5209x3125, 2605x1563, 1303x782, 652x391, 326x196, 163x98</strong>
   Mask Flags: PER_DATASET
 ...  ...  ...  ...  ... </pre>



<p>O gdalinfo reconhe todas as pirâmides. E o QGIS?</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="404" src="https://blog.viasig.com/wp-content/uploads/2020/03/image-13-1024x404.png" alt="" class="wp-image-1147" srcset="https://blog.viasig.com/wp-content/uploads/2020/03/image-13-1024x404.png 1024w, https://blog.viasig.com/wp-content/uploads/2020/03/image-13-300x118.png 300w, https://blog.viasig.com/wp-content/uploads/2020/03/image-13-768x303.png 768w, https://blog.viasig.com/wp-content/uploads/2020/03/image-13.png 1237w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Identificação das overviews pelo QGIS.</figcaption></figure>



<p>Pequeno à parte: Já em artigos anteriores referi que o QGIS tem de ser &#8220;convencido&#8221; a ler máscaras externas. Isto não causa problemas ao processo. Aparentemente, o GDAL tem um comportamento diferente com máscaras externas, em que as expõe com valores 0/1, em vez de valores 0/255 como acontece com máscaras internas. Sem esta correção a máscara não é detectadas correctamente pelo QGIS, e temos de a ignorar, aparecendo as zonas pretas sem dados. Se corrigirmos  editando o vrt, tudo aparece correctamente. Mas em qualquer dos casos as overviews funcionam:</p>



<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Overviews no QGIS" width="604" height="340" src="https://www.youtube.com/embed/mBtz0iBTIN0?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div><figcaption>QGIS e overviews em ação, velocidade real.</figcaption></figure>



<h2 class="wp-block-heading">Com o gdaladdo &#8220;normal&#8221;</h2>



<p>Para compararmos, vamos criar overviews com o processo normal:</p>



<pre class="wp-block-preformatted">timing "gdaladdo --config GDAL_CACHEMAX 1024 --config COMPRESS_OVERVIEW JPEG --config PHOTOMETRIC_OVERVIEW YCBCR --config INTERLEAVE_OVERVIEW PIXEL teste_gdaladdo.vrt"<br>
14:52:45,10<br>
a executar o comando indicado: "gdaladdo --config GDAL_CACHEMAX 1024 --config COMPRESS_OVERVIEW JPEG --config PHOTOMETRIC_OVERVIEW YCBCR --config INTERLEAVE_OVERVIEW PIXEL teste_gdaladdo.vrt"<br>
0…10…20…30…40…50…60…70…80…90…100 - done.<br>
0…10…20…30…40…50…60…70…80…90…100 - done.<br>
15:01:17,19</pre>



<p>Assim, o processo normal demorou 08:32,1 min. </p>



<p>E os ficheiros deste processo normal são:</p>



<pre class="wp-block-preformatted">      50&nbsp;194 teste_gdaladdo.vrt
  23&nbsp;195&nbsp;175 teste_gdaladdo.vrt.msk
 827&nbsp;911&nbsp;591 teste_gdaladdo.vrt.ovr
 <code> 3 File(s)    851 156 960 bytes</code></pre>



<p>Nota: este vrt tem uma máscara externa .msk. Como me esqueci do parâmetro -ro (readonly), as overviews da máscara foram adicionadas ao próprio msk. Também me esqueci do método resample average, que seria mais lento&#8230;</p>



<h2 class="wp-block-heading">Comparação</h2>



<p>O processo de construir overviews em paralelo, divido em 3 processos simultâneos, é 20% mais rápido, e ainda com um bónus de ocupar menos 23% em disco! (não sei porquê) </p>



<figure class="wp-block-table is-style-stripes ticss-14c8e7ab"><table><tbody><tr><td>Método</td><td>Tempo</td><td>Tamanho</td><td>Disco</td><td>CPU</td><td>RAM</td></tr><tr><td>gdaladdo normal</td><td> 08:32,1 </td><td>850MB</td><td>5MB/s</td><td>15%</td><td>1GB</td></tr><tr><td>gdal_translate x3</td><td>  06:47,4 </td><td>647 MB</td><td>19MB/s</td><td>45%</td><td>3GB</td></tr></tbody></table></figure>



<p>Ou seja, conseguimos subir o uso do CPU para 45%, e o disco para 19MB/s. Nada mau. A memória ocupada pelo processo depende do uso que fizermos da flag &#8211;config GDAL_CACHEMAX. No nosso caso, definimo-la como 1GB. Logo 3 processos ocupam obviamente 3x esta quantidade.</p>



<p>O ganho de velocidade resulta do processamento em simultâneo &#8211; enquanto se processa o 1º nível, processam-se logo os restantes e as máscaras também desses níveis caso exista máscara no raster original.</p>



<h2 class="wp-block-heading">Script</h2>



<p>Numa tentativa de automatizar o processo, criei um script bat para windows. Pode ser obtido aqui:  <a href="https://github.com/dncpax/Turbo_GDAL_Overviews">https://github.com/dncpax/Turbo_GDAL_Overviews</a> .</p>



<p>Algumas notas interessantes sobre o bat:</p>



<ul class="wp-block-list"><li>É possível imitar uma execução em background usando &#8220;start /b&#8221; dentro do bat.</li><li> A shell DOS só faz aritmética de inteiros, por isso temos de indicar as 3 resoluções que queremos &#8211; x2, x4 e x8 &#8211; porque em geral não são inteiros e não os conseguimos calcular no bat. </li><li>Usamos DELAYEDEXPANSION porque precisamos de mostrar o tempo de execução.</li><li>Temos de renomear os ficheiros resultantes da máscara externa (.msk) porque ficam com nomes que impedem o seu reconhecimento. O script trata disso com uma série de renames.</li></ul>



<p>A migração para Linux deve ser fácil, porque 80% do script é só validação de argumentos. O que interessa são comandos gdal. Voluntários procuram-se&#8230;</p>



<p>Para executar indicamos o raster e as 3 resoluções iniciais das overviews:</p>



<pre class="wp-block-preformatted">turbo_overviews.bat teste_script.vrt 0.6 1.2 2.4  
Inicio em: 13:29:24,69  
Input file size is 166667, 100000  
Input file size is 166667, 100000  00
Input file size is 166667, 100000  
0…10…20…30…40…50….60…70…..80…..9010….100 - done.  
..0…10…20…30….40…50…60…70…80…90.20..100 - done.  
0…10…20…30…40…50…60…70…80…90….100 - done.  
10..30…..40…20..50…..6030…..70…40.80…..90…50.100 - done.  
…60…70…80…90…100 - done.  
Fim em: 13:36:12,07</pre>



<h2 class="wp-block-heading">Conclusões</h2>



<p>Se calhar este post é optimista: só fiz 1 teste sério&#8230; pode ser o caso de não funcionar mais vez nenhuma ;)&#8230;</p>



<p>Para mim é realmente estranho a falta de processamento multi-core no GDAL. Talvez seja uma questão de tempo, mas já se sente a falta. O que existe é muito incipiente e apenas funciona em cenários que não me são aplicáveis (e.g. compressão DEFLATE).</p>



<p>Há mais alternativas a este processo, mas nos testes que fiz não tive tão bons resultados.</p>



<p>Há outros programas que podem fazer resample de imagens e com processamento multi-core, como o imagemagick. Isto obrigará a copiar a georeferenciação para as imagens resultantes porque estes programas não reconhecem a componente SIG das imagens. Mas pode ser interessante.</p>



<p>De qualquer forma, por agora, este processo parece funcionar bem. Falta testar com um mosaico &#8220;à séria&#8221;. Pode ser que os 20% de maior rapidez se confirmem!</p>



<p>Até breve!</p>



<h2 class="wp-block-heading">Adenda</h2>



<p>Teste com um mosaico um pouco maior&#8230;</p>



<p>Este mosaico é similar mas maior: tem uma dimensão de 233.334 x 383.334 pixeis, em 258 ficheiros, num total de 10,3GB. Demorou 41:38,2 min, em vez de 01:35 h com o GDAL v.3.0.4 (na v2.3.0 tinha demorado 08:42:33 h) do gdaladdo&#8230; Ou seja, um ganho de 56%!</p>



<p>Observámos uma ocupação do disco interessante: mais de 60MB/s&#8230; </p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="493" src="https://blog.viasig.com/wp-content/uploads/2020/03/image-15-1024x493.png" alt="" class="wp-image-1152" srcset="https://blog.viasig.com/wp-content/uploads/2020/03/image-15-1024x493.png 1024w, https://blog.viasig.com/wp-content/uploads/2020/03/image-15-300x144.png 300w, https://blog.viasig.com/wp-content/uploads/2020/03/image-15-768x370.png 768w, https://blog.viasig.com/wp-content/uploads/2020/03/image-15-1536x740.png 1536w, https://blog.viasig.com/wp-content/uploads/2020/03/image-15.png 1634w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption> <em>Mosaico maior em construção&#8230;</em> </figcaption></figure>



<p>Os tamanhos foram similares: 4.4GB vs 4.9GB.</p>



<p>E correctamente visualizado em QGIS:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="835" height="931" src="https://blog.viasig.com/wp-content/uploads/2020/03/image-16.png" alt="" class="wp-image-1155" srcset="https://blog.viasig.com/wp-content/uploads/2020/03/image-16.png 835w, https://blog.viasig.com/wp-content/uploads/2020/03/image-16-269x300.png 269w, https://blog.viasig.com/wp-content/uploads/2020/03/image-16-768x856.png 768w" sizes="auto, (max-width: 835px) 100vw, 835px" /><figcaption>Mosaico de 10GB com overviews criadas em 40min&#8230;</figcaption></figure>



<p>Neste mosaico mais encorpado, a melhoria é enorme&#8230; Curioso em ver a aplicação em mosaicos muito maiores.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.viasig.com/2020/03/overviews-gdal-em-modo-turbo/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>SentinelPT WMS Time Machine</title>
		<link>https://blog.viasig.com/2019/09/sentinelpt-wms-time-machine/</link>
					<comments>https://blog.viasig.com/2019/09/sentinelpt-wms-time-machine/#respond</comments>
		
		<dc:creator><![CDATA[duarte]]></dc:creator>
		<pubDate>Fri, 06 Sep 2019 23:51:58 +0000</pubDate>
				<category><![CDATA[Avançado]]></category>
		<category><![CDATA[Dados]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[WebGIS]]></category>
		<category><![CDATA[Satélite]]></category>
		<category><![CDATA[Sentinel]]></category>
		<category><![CDATA[WMS]]></category>
		<guid isPermaLink="false">http://192.168.1.84:8000/?p=1073</guid>

					<description><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 9</span> <span class="rt-label rt-postfix">min</span></span>Versão abreviada&#8230; Podem aceder aqui a um motor de mosaicos de imagens Sentinel-2 RGB e IRG para Portugal, com serviço WMS, com suporte temporal&#8230; O serviço WMS está funcional, mas para usar em QGIS é preciso algumas definições (ler abaixo, muuuito abaixo). http://sentinelpt.viasig.com/ Alguns avisos: isto é um projecto pessoal, de carolice, tem muitos defeitos, &#8230; <a href="https://blog.viasig.com/2019/09/sentinelpt-wms-time-machine/" class="more-link">Continuar a ler<span class="screen-reader-text">SentinelPT WMS Time Machine</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 9</span> <span class="rt-label rt-postfix">min</span></span>
<h2 class="wp-block-heading">Versão abreviada&#8230;</h2>



<p><img loading="lazy" decoding="async" width="150" height="127" class="wp-image-1074" style="width: 150px;" src="https://blog.viasig.com/wp-content/uploads/2019/09/too-long-didnt.jpg" alt=""> </p>



<p>Podem aceder aqui a um motor de mosaicos de imagens Sentinel-2 RGB e IRG para Portugal, com serviço WMS, com suporte temporal&#8230;  O serviço WMS está funcional, mas para usar em QGIS é preciso algumas definições (ler abaixo, muuuito abaixo). </p>



<p><a href="http://sentinelpt.viasig.com/">http://sentinelpt.viasig.com/</a></p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="913" height="515" src="https://blog.viasig.com/wp-content/uploads/2019/09/image-3.png" alt="" class="wp-image-1083" srcset="https://blog.viasig.com/wp-content/uploads/2019/09/image-3.png 913w, https://blog.viasig.com/wp-content/uploads/2019/09/image-3-300x169.png 300w, https://blog.viasig.com/wp-content/uploads/2019/09/image-3-768x433.png 768w" sizes="auto, (max-width: 913px) 100vw, 913px" /></figure>



<p>Alguns avisos: isto é um projecto pessoal, de carolice, tem muitos defeitos, eu sei, que podem ou não vir a ser resolvidos&#8230; Estou muito interessado em ouvir sugestões, e para isso nada melhor que o twitter ou os comentários aqui no blog.</p>



<p>Se a carga for demasiada no servidor, os pedidos são &#8220;desacelerados&#8221;, por forma a manter o servidor equilibrado. Por favor, não usem scripts de download&#8230; Pretendo incluir a função de download em breve. Entretanto, se precisarem de alguma imagem é só dizer, eu farei os possíveis para responder atempadamente. </p>



<p>E pronto, agora quem tem curiosidade e paciência pode continuar a ler&#8230;</p>



<span id="more-1073"></span>



<h2 class="wp-block-heading">Introdução</h2>



<p>Acho as imagens Sentinel um prodígio, a sério. Temos imagens de 10m de resolução, 7 em 7 dias, para grande parte do planeta, gratuitas! É espantoso&#8230;</p>



<p>Tenho usado imagens que pesquiso e descarrego a partir dos sites de distribuição da ESA.  Mas é um processo moroso obter as imagens &#8211; cada uma é 1GB num zip com 13 ficheiros jpeg2000, e mais uma dezena de outros ficheiros de metadados. Ainda mais moroso se quiser juntar algumas imagens. Mas é tudo gratuito. </p>



<p>Também consulto visualizadores web com imagens processadas, com equilibrio de cores, e sem nuvens, e com várias combinações de bandas. É só pesquisar&#8230; também é gratuito.</p>



<p>Agora, se subirmos um pouco o grau de exigência e quisermos sobrepor a nossa informação às imagens, podemos usar um serviço WMS. Mas aqui já é pago, e começa nos 20€/mês por utilizador particular ou académico. Se for empresa o preço já sobe. E é completamente justificado. Mas também é um pouco contraditório em relação ao que se pretende do programa Copernicus, que seria disseminar o mais possível os resultados do programa na sociedade civil&#8230; 20€/mês parece-me um pouco contraditório.</p>



<p>Na mais recente incursão pelos sites de descarga das imagens, comecei a fazer alguns scripts, muito simples. Mas a coisa foi-se alongando, e acabei por automatizar grande parte do que seria um servidor wms, com dados processados periodicamente. Foi assim que nasceu este projecto &#8211; WMS Time Machine!</p>



<div class="wp-block-image"><figure class="aligncenter is-resized"><a href="https://player.theplatform.com/p/HNK2IC/vPUdRgYktZD4/select/media/guid/2474312077/2DF68F7B-EFE6-6F1D-A96A-FA12E29723C2?autoPlay=true&amp;fwsitesection=rotten_tomatoes_tveverywhere_vod_hub&amp;adobe_mc=MCMID%3D48401926897406033973372615667806285556%7CMCORGID%3D8CF467C25245AE3F0A490D4C%2540AdobeOrg%7CTS%3D1567814521&amp;params=manifest%3Dm3u%26sst%3Dtrue%26debug%3Dtrue%26policy%3D9369485#playerurl=https%3A//www.rottentomatoes.com/tv/rick_and_morty/s03" target="_blank" rel="noreferrer noopener"><img loading="lazy" decoding="async" src="https://blog.viasig.com/wp-content/uploads/2019/09/rickandmorty_amelhorseriedetodosostempos.gif" alt="Rick and Morty a melhor série de todos os tempos!" class="wp-image-1102" width="282" height="158"/></a><figcaption>Melhor invenção de todos os tempos</figcaption></figure></div>



<p>Isto não é bem uma invenção&#8230; Os nossos vizinhos aqui ao lado do Institut Cartogràfic i Geològic de Catalunya têm um servidor WMS-T de imagens Sentinel *do caraças!*&#8230; </p>



<pre class="wp-block-preformatted"><a href="http://www.icgc.cat/en/Public-Administration-and-Enterprises/Services/Online-services-Geoservices/WMS-Ortoimatges/WMS-Sentinel-2-orthoimages" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">http://www.icgc.cat/en/Public-Administration-and-Enterprises/Services/Online-services-Geoservices/WMS-Ortoimatges/WMS-Sentinel-2-orthoimages</a></pre>



<p>É pena ser só para a Catalunha&#8230;</p>



<h2 class="wp-block-heading">Componentes e Processo geral</h2>



<p>Os passos do processo e os componentes de software usado são:</p>



<ol class="wp-block-list"><li>Pesquisa e descargas de imagens &#8211; <a rel="noreferrer noopener" aria-label="Sentinelsat (opens in a new tab)" href="https://sentinelsat.readthedocs.io/en/stable/index.html" target="_blank">Sentinelsat</a></li><li>Processamento das imagens &#8211; <a rel="noreferrer noopener" aria-label="GDAL/OGR (opens in a new tab)" href="https://gdal.org/" target="_blank">GDAL/OGR</a></li><li>Manutenção da BD de imagens &#8211; GDAL/OGR</li><li>Serviço WMS Time &#8211; <a rel="noreferrer noopener" aria-label="MapServer (opens in a new tab)" href="https://mapserver.org/" target="_blank">MapServer</a></li><li>Visualizar o serviço em <a rel="noreferrer noopener" aria-label="QGIS (opens in a new tab)" href="https://qgis.org" target="_blank">QGIS</a></li><li>Visualizador Web &#8211; <a href="https://openlayers.org" target="_blank" rel="noreferrer noopener" aria-label="OpenLayers  (opens in a new tab)">OpenLayers </a>(Feito à pressa! No futuro, talvez um de jeito <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></li></ol>



<h3 class="wp-block-heading">Pesquisa e descarga das imagens &#8211; Sentinelsat</h3>



<p>A pesquisa das imagens e a filtragem das que interessam é feita usando a biblioteca python SentinelSat, que também inclui uma CLI. São apenas usadas imagens <a href="https://earth.esa.int/web/sentinel/technical-guides/sentinel-2-msi/products-algorithms" target="_blank" rel="noreferrer noopener" aria-label="Sentinel-2, nível 2A (opens in a new tab)">Sentinel-2, nível 2A</a> (significa que têm já correção atmosférica).</p>



<p>O esquema de pesquisa é muito simples, e estou a procurar formas de o melhorar. É indicada uma data, e são pesquisadas 16 quadrículas ou tiles ou grânulos (não tenho paciência para ler o dicionário do Sentinel) que correspondem a Portugal, que tenham sido obtidas até 5 dias atrás, com nuvens até 70%. Também são recusadas imagens com menos de 75% do seu tamanho normal para evitar imagens com grandes áreas sem dados.   Alguns mosaicos podem ter sido construídos manualmente com nuvens até 90%&#8230;  </p>



<p>Um exemplo de pesquisa com Sentinelsat:</p>



<pre class="wp-block-preformatted"> sentinelsat  --start 20190818 --end 20190819 --sentinel 2 --instrument MSI  --producttype S2MSI2A --cloud 40 --query "filename=/.+29S(N|P)C.+/"  --user bla --password blabla </pre>



<p>Este comando procura ficheiros com nomes que incluam &#8220;29SNC&#8221; ou &#8220;29SPC&#8221; entre os dias 18 e 19-08-2019, com cobertura de nuvens até 40%. A facilidade de usar expressões regulares é muito flexível. Os <a rel="noreferrer noopener" aria-label="docs do Sentinelsat (opens in a new tab)" href="https://sentinelsat.readthedocs.io/en/stable/" target="_blank">docs do Sentinelsat</a> e da interface de <a href="https://scihub.copernicus.eu/twiki/do/view/SciHubUserGuide/FullTextSearch?redirectedfrom=SciHubUserGuide.3FullTextSearch" target="_blank" rel="noreferrer noopener" aria-label="pesquisa da ESA (opens in a new tab)">pesquisa da ESA</a> são muito bons.</p>



<p>Só são descarregadas 4 bandas das 13 disponíveis: B02 (Red), B03 (Green), B04 (Blue), e B08 (Infrared). Isto significa que para uma data são descarregados 64 ficheiros .jp2 (16 tiles x 4 bandas), cerca de 7GB no total. As 4 bandas são depois combinadas em combinações RGB e IRG.</p>



<p>O processo de pesquisa deveria ser melhorado&#8230; Gostava de evitar mosaicos com partes significativas sem dados (neste momento há tiles com 25% de área sem dados).  Estou a pensar numa pesquisa sobre um maior período, ordenar as imagens por qualidade, e detectar que datas apresentam melhores coberturas. Ou seja, um processo quase inverso do actual&#8230; Outra opção é usar o footprint de cada imagem e analisar geometricamente qual a combinação com menores vazios, ou mesmo só fazer o mosaico se não houver vazios.</p>



<figure class="wp-block-gallery columns-2 is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex"><ul class="blocks-gallery-grid"><li class="blocks-gallery-item"><figure><img loading="lazy" decoding="async" width="456" height="423" src="https://blog.viasig.com/wp-content/uploads/2019/09/image-4.png" alt="" data-id="1085" data-link="https://blog.viasig.com/?attachment_id=1085" class="wp-image-1085" srcset="https://blog.viasig.com/wp-content/uploads/2019/09/image-4.png 456w, https://blog.viasig.com/wp-content/uploads/2019/09/image-4-300x278.png 300w" sizes="auto, (max-width: 456px) 100vw, 456px" /><figcaption class="blocks-gallery-item__caption">Bom tile</figcaption></figure></li><li class="blocks-gallery-item"><figure><img loading="lazy" decoding="async" width="463" height="426" src="https://blog.viasig.com/wp-content/uploads/2019/09/image-5.png" alt="" data-id="1086" data-link="https://blog.viasig.com/?attachment_id=1086" class="wp-image-1086" srcset="https://blog.viasig.com/wp-content/uploads/2019/09/image-5.png 463w, https://blog.viasig.com/wp-content/uploads/2019/09/image-5-300x276.png 300w" sizes="auto, (max-width: 463px) 100vw, 463px" /><figcaption class="blocks-gallery-item__caption">Mau tile</figcaption></figure></li></ul></figure>



<h3 class="wp-block-heading">Processamento das imagens &#8211; GDAL</h3>



<p>Depois de descarregados, os ficheiros são processados com GDAL e OGR. As 4 bandas de cada quadrícula ou grânulo são convertidas para 8bit, sendo criadas  uma imagem virtual RGB e outra IRG para cada Tile. Depois é aplicado um stretch &#8220;virtual&#8221; para melhorar o contraste. São criados tileindexes para reunir todas as imagens RGB  e IRG do país para uma data. Em seguida tento explicar melhor&#8230;</p>



<figure class="wp-block-gallery columns-2 is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex"><ul class="blocks-gallery-grid"><li class="blocks-gallery-item"><figure><img loading="lazy" decoding="async" width="425" height="382" src="https://blog.viasig.com/wp-content/uploads/2019/09/image-6.png" alt="" data-id="1088" data-link="https://blog.viasig.com/?attachment_id=1088" class="wp-image-1088" srcset="https://blog.viasig.com/wp-content/uploads/2019/09/image-6.png 425w, https://blog.viasig.com/wp-content/uploads/2019/09/image-6-300x270.png 300w" sizes="auto, (max-width: 425px) 100vw, 425px" /><figcaption class="blocks-gallery-item__caption">Imagem IRG</figcaption></figure></li><li class="blocks-gallery-item"><figure><img loading="lazy" decoding="async" width="516" height="404" src="https://blog.viasig.com/wp-content/uploads/2019/09/image-7.png" alt="" data-id="1089" data-link="https://blog.viasig.com/?attachment_id=1089" class="wp-image-1089" srcset="https://blog.viasig.com/wp-content/uploads/2019/09/image-7.png 516w, https://blog.viasig.com/wp-content/uploads/2019/09/image-7-300x235.png 300w" sizes="auto, (max-width: 516px) 100vw, 516px" /><figcaption class="blocks-gallery-item__caption">Imagem RGB</figcaption></figure></li></ul></figure>



<p>A compressão faz com que o tamanho das bandas passe de ~100MB (jp2000, 16bit) para ~6MB (tiff/jpeg, 8bit). E assim os 64 ficheiros tif só ocupam 600MB para todo Portugal Continental, numa data.</p>



<p>É importante referir que para passar de 16bit para 8bit usei a forma mais simples do <a rel="noreferrer noopener" aria-label="parâmetro -scale (opens in a new tab)" href="https://gdal.org/programs/gdal_translate.html" target="_blank">parâmetro -scale</a>, que efectivamente passa os valores min-max dos 16bits da imagem, para valores entre 0-255. Isto efectivamente já provoca uma alteração à cor e contraste da imagem. E, obviamente, alguma perda de informação. Estas imagens são apenas para visualização e não se recomendam para análise.</p>



<p>Foi necessário melhorar ainda mais o contraste para que as imagens não fiquem demasiado escuras. Como o MapServer não suporta grande coisa na simbologia de rasters, tive de resolver ao nível dos dados. </p>



<p>Encontrei muita <a rel="noreferrer noopener" aria-label="informação sobre a opção scale (opens in a new tab)" href="https://gis.stackexchange.com/questions/217743/scale-16-bit-to-8-bit-within-range-using-gdal" target="_blank">informação sobre a opção scale</a>, mas poucas soluções para ajuste do contraste. Algumas <a rel="noreferrer noopener" aria-label="óptimas soluções  (opens in a new tab)" href="https://github.com/gina-alaska/dans-gdal-scripts/wiki/Gdal-contrast-stretch" target="_blank">óptimas soluções </a>permitem criar novas imagens melhoradas, mas obrigam a mais espaço em disco e mais tempo de processamento&#8230;</p>



<p>A solução foi criar um .vrt que faz um ajuste ao contraste dinamicamente através da opção -scale. É usado o método de ajuste pelo desvio padrão, aplicando-o a cada banda. Ou seja, em cada banda é obtida a média e o desvio padrão, e o ajuste é feito calculando novos mínimos e máximos (fazendo o mesmo que uma das opções de <a rel="noreferrer noopener" aria-label="Contrast Enhancement do QGIS (opens in a new tab)" href="https://docs.qgis.org/3.4/en/docs/user_manual/working_with_raster/raster_properties.html#minmaxvalues" target="_blank">Contrast Enhancement do QGIS</a>):</p>



<pre class="wp-block-preformatted">-scale 0 255 media-2.8*stdev media+2.8*stddev</pre>



<p>Funciona muito bem, desde que não existam nuvens na imagem:</p>



<figure class="wp-block-gallery columns-2 is-cropped wp-block-gallery-3 is-layout-flex wp-block-gallery-is-layout-flex"><ul class="blocks-gallery-grid"><li class="blocks-gallery-item"><figure><img loading="lazy" decoding="async" width="505" height="393" src="https://blog.viasig.com/wp-content/uploads/2019/09/image-1.png" alt="" data-id="1078" data-link="https://blog.viasig.com/?attachment_id=1078" class="wp-image-1078" srcset="https://blog.viasig.com/wp-content/uploads/2019/09/image-1.png 505w, https://blog.viasig.com/wp-content/uploads/2019/09/image-1-300x233.png 300w" sizes="auto, (max-width: 505px) 100vw, 505px" /><figcaption class="blocks-gallery-item__caption">Original 8bit</figcaption></figure></li><li class="blocks-gallery-item"><figure><img loading="lazy" decoding="async" width="481" height="395" src="https://blog.viasig.com/wp-content/uploads/2019/09/image.png" alt="" data-id="1077" data-link="https://blog.viasig.com/?attachment_id=1077" class="wp-image-1077" srcset="https://blog.viasig.com/wp-content/uploads/2019/09/image.png 481w, https://blog.viasig.com/wp-content/uploads/2019/09/image-300x246.png 300w" sizes="auto, (max-width: 481px) 100vw, 481px" /><figcaption class="blocks-gallery-item__caption">Contraste melhorado</figcaption></figure></li></ul></figure>



<p>Com nuvens, e respectivas sombras, tudo piora, como é de esperar&#8230; será necessário melhorar o processo para evitar estas áreas brancas e negras:</p>



<div class="wp-block-image"><figure class="aligncenter is-resized"><img loading="lazy" decoding="async" src="https://blog.viasig.com/wp-content/uploads/2019/09/image-2.png" alt="" class="wp-image-1079" width="392" height="307" srcset="https://blog.viasig.com/wp-content/uploads/2019/09/image-2.png 524w, https://blog.viasig.com/wp-content/uploads/2019/09/image-2-300x235.png 300w" sizes="auto, (max-width: 392px) 100vw, 392px" /><figcaption>Falta de contraste na presença de nuvens</figcaption></figure></div>



<h3 class="wp-block-heading">Criar base de dados das datas e imagens &#8211; OGR</h3>



<p>Numa data temos assim 16 imagens RGB, e 16 imagens IRG. Todas são virtuais (.vrt), apens combinam 3 das 4 bandas, e não ocupam espaço. Agora queremos criar uma listagem que indique que datas já recolhemos, e quais as imagens que constituem cada data.</p>



<p>A base de de dados é apenas um shapefile com as quadrículas de todas as imagens vrt&#8230; o processo é simples e consiste em criar <a rel="noreferrer noopener" aria-label="tileindexes (opens in a new tab)" href="https://gdal.org/programs/gdaltindex.html" target="_blank">tileindexes</a>&#8230; uma forma anciã de ver mosaicos de imagens e que <a href="https://mapserver.org/optimization/tileindex.html" target="_blank" rel="noreferrer noopener" aria-label="ainda funciona em Mapserver (opens in a new tab)">ainda funciona em Mapserver</a>.</p>



<p>Começamos por criar um tileindex das imagens numa data. Simples comando de <a rel="noreferrer noopener" aria-label="gdaltindex (opens in a new tab)" href="https://gdal.org/programs/gdaltindex.html" target="_blank">gdaltindex</a>. Um exemplo de índice rgb do mosaico para o dia 30/06/2019:</p>



<figure class="wp-block-gallery aligncenter columns-2 is-cropped wp-block-gallery-4 is-layout-flex wp-block-gallery-is-layout-flex"><ul class="blocks-gallery-grid"><li class="blocks-gallery-item"><figure><img loading="lazy" decoding="async" width="473" height="675" src="https://blog.viasig.com/wp-content/uploads/2019/09/image-8.png" alt="" data-id="1091" data-link="https://blog.viasig.com/?attachment_id=1091" class="wp-image-1091" srcset="https://blog.viasig.com/wp-content/uploads/2019/09/image-8.png 473w, https://blog.viasig.com/wp-content/uploads/2019/09/image-8-210x300.png 210w" sizes="auto, (max-width: 473px) 100vw, 473px" /><figcaption class="blocks-gallery-item__caption">Índice com datas</figcaption></figure></li><li class="blocks-gallery-item"><figure><img loading="lazy" decoding="async" width="426" height="657" src="https://blog.viasig.com/wp-content/uploads/2019/09/Pasted.png" alt="" data-id="1092" data-link="https://blog.viasig.com/?attachment_id=1092" class="wp-image-1092" srcset="https://blog.viasig.com/wp-content/uploads/2019/09/Pasted.png 426w, https://blog.viasig.com/wp-content/uploads/2019/09/Pasted-195x300.png 195w" sizes="auto, (max-width: 426px) 100vw, 426px" /><figcaption class="blocks-gallery-item__caption">Índice com ficheiros</figcaption></figure></li></ul></figure>



<p>Na verdade, os índices são geograficamente todos iguais, porque uso sempre as mesmas 16 tiles. Mas o ideal seria pesquisar pela área de Portugal, e ver que tiles têm melhor cobertura na data escolhida.</p>



<p>A única coisa que varia entre datas são os ficheiros de imagem que são descarregados.</p>



<p>Bom, já temos um tileindex para cada dia descarregado, que é um shapefile com um atributo a indicar o caminho para cada imagem.</p>



<p>Como fazer uma base de dados de todos os mosaicos que já foram descarregados e existem no servidor? A resposta é simples: copiamos estes registos para um shapefile global usando ogr2ogr com a opção -update. E sempre que se constrói um mosaico para uma data nova, vamos inserir estes registos no shapefile global.</p>



<p>Aqui é usada a <a href="https://github.com/clhenrick/OGR-SQL" target="_blank" rel="noreferrer noopener" aria-label="função SQL do OGR (opens in a new tab)">função SQL do OGR</a>, que é absolutamente fantástica&#8230; permite executar SQL ao carregar dados para um shapefile, ou qualquer outro formato.</p>



<p>Assim, ao copiar as quads de um mosaico para o índice global aproveitamos para actualizar alguns campos extra:</p>



<ul class="wp-block-list"><li>data do mosaico (campo time)</li><li>data da imagem (campo dataimg)</li><li>nome do ficheiro (campo location)</li><li>nome do ficheiro com contraste melhorado (campo localviz)</li></ul>



<div class="wp-block-image"><figure class="aligncenter"><img loading="lazy" decoding="async" width="802" height="425" src="https://blog.viasig.com/wp-content/uploads/2019/09/image-9.png" alt="" class="wp-image-1095" srcset="https://blog.viasig.com/wp-content/uploads/2019/09/image-9.png 802w, https://blog.viasig.com/wp-content/uploads/2019/09/image-9-300x159.png 300w, https://blog.viasig.com/wp-content/uploads/2019/09/image-9-768x407.png 768w" sizes="auto, (max-width: 802px) 100vw, 802px" /><figcaption>Exemplo de identify no Índice de imagens RGB</figcaption></figure></div>



<p>Significa que sabemos as datas todas que recolhemos, e as imagens que as compõem. Tudo com shapefile!! (<a rel="noreferrer noopener" aria-label="o shapefile nunca morrerá! (opens in a new tab)" href="https://twitter.com/shapefiie" target="_blank">o shapefile é eterno!</a>)</p>



<p>E é compatível com MapServer&#8230; </p>



<p>Só um exemplo do comando ogr para apagar imagens que já existam de uma data:</p>



<pre class="wp-block-preformatted">ogrinfo -dialect SQLITE tileindex_global_irg.shp -sql "DELETE FROM tileindex_global_irg where location like '%_20190830%_irg_%.vrt'"</pre>



<h3 class="wp-block-heading">Publicar as imagens num serviço WMS-Time</h3>



<p>Usei o MapServer como servidor WMS com <a rel="noreferrer noopener" aria-label="suporte do parâmetro Time (opens in a new tab)" href="https://mapserver.org/ogc/wms_time.html" target="_blank">suporte do parâmetro Time</a>. </p>



<p>O MapServer é fácil de configurar e manipular apenas com ficheiros de texto. A sua arquitectura é tão simples que apenas é necessário um nginx para o colocar na net. A exigência de memória é também muito reduzida. E claro, é um óptimo amigo do GDAL/OGR. Tudo o que era preciso&#8230;</p>



<p>Assim, foi criado um mapfile único com 4 layers:</p>



<ol class="wp-block-list"><li>Índice das imagens, com label mostrando a data de cada imagem</li><li>Índice das imagens, com label mostrando o nome do ficheiro (para vermos a tile respectiva se quisermos obter o original no site da ESA)</li><li>Mosaico RGB</li><li>Mosaico IRG</li></ol>



<p>Todos apontam para o tileindex RGB ou para o tileindex IRG. Os índices são vectoriais, e os mosaicos são rasters. Simples.</p>



<p>O parâmetro TIME permite filtrar os dados para só mostrar aqueles que cumprem essa query. Ou seja, passamos uma data e o servidor devolve uma imagem onde todos os layers com TIME definido são filtrados por essa data.</p>



<p>No nosso caso, o campo usado para o filtro de data é o campo time, que indica a data de construção do mosaico. Por exemplo, este request mostra só imagens do mosaico RGB com data de 2019-06-30:</p>



<pre class="wp-block-preformatted"><a href="http://sentinelpt.viasig.com/wms/sentinelpt/?SERVICE=WMS&amp;VERSION=1.3.0&amp;REQUEST=GetMap&amp;FORMAT=image%2Fjpeg&amp;TRANSPARENT=true&amp;LAYERS=SentinelPT_RGB%2CIndice&amp;TIME=2019-06-30&amp;CRS=EPSG%3A3857&amp;STYLES=&amp;WIDTH=866&amp;HEIGHT=538&amp;BBOX=-868964.8014314906%2C4637845.355088675%2C-860690.4931196203%2C4642985.745240854" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">http://sentinelpt.viasig.com/wms/sentinelpt/?SERVICE=WMS&amp;VERSION=1.3.0&amp;REQUEST=GetMap&amp;FORMAT=image%2Fjpeg&amp;TRANSPARENT=true&amp;LAYERS=SentinelPT_RGB%2CIndice&amp;TIME=2019-06-30&amp;CRS=EPSG%3A3857&amp;STYLES=&amp;WIDTH=866&amp;HEIGHT=538&amp;BBOX=-868964.8014314906%2C4637845.355088675%2C-860690.4931196203%2C4642985.745240854</a></pre>



<p>Há uma limitação ainda por resolver no serviço WMS: as datas disponíveis podem ser anunciadas pelo serviço. Mas neste momento estão fixadas:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="741" height="129" src="https://blog.viasig.com/wp-content/uploads/2019/09/image-11.png" alt="" class="wp-image-1098" srcset="https://blog.viasig.com/wp-content/uploads/2019/09/image-11.png 741w, https://blog.viasig.com/wp-content/uploads/2019/09/image-11-300x52.png 300w" sizes="auto, (max-width: 741px) 100vw, 741px" /><figcaption>Período anunciado no WMS-Time é fictício&#8230;</figcaption></figure>



<h2 class="wp-block-heading">Como ver no QGIS</h2>



<p>Pois é&#8230; o QGIS não tem grande suporte para usar WMS-Time&#8230; mas funciona com alguns truques &#8211; basta indicar a data que queremos no url do serviço, e ligar as opções para ignorar os url&#8217;s devolvidos no capabilities doc:</p>



<div class="wp-block-image"><figure class="aligncenter"><img loading="lazy" decoding="async" width="450" height="608" src="https://blog.viasig.com/wp-content/uploads/2019/09/image-10.png" alt="" class="wp-image-1096" srcset="https://blog.viasig.com/wp-content/uploads/2019/09/image-10.png 450w, https://blog.viasig.com/wp-content/uploads/2019/09/image-10-222x300.png 222w" sizes="auto, (max-width: 450px) 100vw, 450px" /><figcaption>Usar o serviço WMS-Time no QGIS</figcaption></figure></div>



<h2 class="wp-block-heading">Visualizador web</h2>



<p>Bom, este visualizador é muito básico. Foi feito com base neste viewer baseado em OpenLayers:<a href="https://www.earder.com/tutorials/timeseries-with-geoserver-and-openlayers/" target="_blank" rel="noreferrer noopener" aria-label=" https://www.earder.com/tutorials/timeseries-with-geoserver-and-openlayers/ (opens in a new tab)"> https://www.earder.com/tutorials/timeseries-with-geoserver-and-openlayers/</a>.</p>



<p>Permite selecionar a data, tema RGB ou IRG, com ou  sem labels. E ver o link WMS correspondente à data selecionada:</p>



<pre class="wp-block-preformatted"><a href="http://sentinelpt.viasig.com/" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">http://sentinelpt.viasig.com/</a></pre>



<h2 class="wp-block-heading">Melhorias??</h2>



<p>Tantas, tantas&#8230;</p>



<ul class="wp-block-list"><li>Criar transparência onde não há dados (zonas negras)</li><li>Criar serviço de download (WCS)?</li><li>Melhorar o ajuste de contraste automático  actual, de acordo com cada imagem ou fazendo um match dos histogramas  (neste momento, é feito um stretch de desvio padrão em todas as bandas)</li><li>Excluir as nuvens do ajuste de contraste</li><li>Criar serviço de tiles (WMTS)?</li><li>Usar um visualizador web como deve ser (TerriaJS?)</li><li>Obter dados para 2017</li><li>Download dos footprints das imagens e usá-los na pesquisa e processamento</li><li>Selecionar entre tiles disponíveis com menor área sem dados</li><li>Reduzir a compressão dos ficheiros, aumentando a qualidade</li></ul>



<p>Acho que nem eu próprio li isto tudo&#8230; mas fica para cábula futura.</p>



<h4 class="wp-block-heading">Legalidades                 </h4>



<p>Este é um projecto pessoal, sem qualquer garantia. Portanto, use por sua própria conta e risco. Contém dados de imagem de satélite  Copernicus Sentinel-2 para vários anos, processados para efeitos de  visualização e arquivo. Os dados originais são disponibilizados  gratuitamente pela União Europeia para todos os fins. Mais informação  pode ser consultada aqui: <a href="https://scihub.copernicus.eu/" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">https://scihub.copernicus.eu</a>.</p>



<p>Os dados deste projecto são disponibilizados sob a licença Atribuição 4.0 Internacional (CC BY 4.0)(<a rel="noreferrer noopener" href="https://creativecommons.org/licenses/by/4.0/deed.pt" target="_blank">link</a>). Em resumo, esta licença permite qualquer uso dos  dados, mesmo comercialmente, desde que seja indicada a sua fonte e  não sejam impostas restrições adicionais aos dados.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.viasig.com/2019/09/sentinelpt-wms-time-machine/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PostgreSQL &#8211; mover tablespaces</title>
		<link>https://blog.viasig.com/2019/02/postgresql-mover-tablespaces/</link>
					<comments>https://blog.viasig.com/2019/02/postgresql-mover-tablespaces/#respond</comments>
		
		<dc:creator><![CDATA[duarte]]></dc:creator>
		<pubDate>Fri, 01 Feb 2019 19:13:53 +0000</pubDate>
				<category><![CDATA[Avançado]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<guid isPermaLink="false">http://192.168.1.84:8000/?p=1030</guid>

					<description><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 4</span> <span class="rt-label rt-postfix">min</span></span>É totalmente desaconselhado criar tablespaces na directoria DATA do pgsql. Podem ver-se vários avisos e explicações na net: https://hunleyd.github.io/posts/Where-Not-To-Put-Your-Tablespaces/ Este post resulta de eu ter cometido este erro há muito tempo atrás (v8.4) e só agora estar a pagar por ele&#8230; Como funcionam os tablespaces no postgres? Tablespaces em pgsql são pastas onde são colocados &#8230; <a href="https://blog.viasig.com/2019/02/postgresql-mover-tablespaces/" class="more-link">Continuar a ler<span class="screen-reader-text">PostgreSQL &#8211; mover tablespaces</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 4</span> <span class="rt-label rt-postfix">min</span></span>
<p>É totalmente desaconselhado criar tablespaces na directoria DATA do pgsql. Podem ver-se vários avisos e explicações na net:<br> <a href="https://hunleyd.github.io/posts/Where-Not-To-Put-Your-Tablespaces/" target="_blank" rel="noreferrer noopener" aria-label="https://hunleyd.github.io/posts/Where-Not-To-Put-Your-Tablespaces/ (opens in a new tab)">https://hunleyd.github.io/posts/Where-Not-To-Put-Your-Tablespaces/</a></p>



<p>Este post resulta de eu ter cometido este erro há muito tempo atrás (v8.4) e só agora estar a pagar por ele&#8230;</p>



<h3 class="wp-block-heading">Como funcionam os tablespaces no postgres?</h3>



<p>Tablespaces em pgsql são pastas onde são colocados os ficheiros de dados, e a teoria é que permitem espalhar os dados em diferentes discos para equilibrar os acessos e o desempenho. Também dão flexibilidade para gerir falta de espaço em disco, p.e. colocando um tablespace noutro disco que tem espaço, e que receberá determinados dados (todos os novos dados, só algumas tabelas, etc.).<br>Esta divisão também pode ser feita quando temos só um disco, ficando a bd preparada para um cenário futuro com mais discos.</p>



<span id="more-1030"></span>



<p>O postgres tem 2 tablespaces iniciais: pg_default e pg_global.<br>O pg_global é destinado aos objectos de sistema, e o pg_default é obviamente onde são gravados os nossos dados.<br> A grande questão é:  no disco, onde está  o pg_default? Está na pasta DATA\base!</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="815" height="529" src="https://blog.viasig.com/wp-content/uploads/2019/02/pg_default_no_disco.png" alt="" class="wp-image-1031" srcset="https://blog.viasig.com/wp-content/uploads/2019/02/pg_default_no_disco.png 815w, https://blog.viasig.com/wp-content/uploads/2019/02/pg_default_no_disco-300x195.png 300w, https://blog.viasig.com/wp-content/uploads/2019/02/pg_default_no_disco-768x498.png 768w" sizes="auto, (max-width: 815px) 100vw, 815px" /><figcaption>Localização em disco do tablespace pg_default</figcaption></figure>



<p>Existe uma directoria que baralha isto tudo: DATA\pg_tablespace. E que está vazia. É aqui que os utilizadores costumam baralhar o sistema (como eu), e pensando que esta pasta é onde está o tablespace default, vão raciocinar que podem criar os seus tablespaces ao &#8220;lado&#8221;, por exemplo DATA\meu_tablespace.</p>



<div class="wp-block-image"><figure class="aligncenter is-resized"><img loading="lazy" decoding="async" src="https://blog.viasig.com/wp-content/uploads/2019/02/pg_tblspc_no_disco.png" alt="" class="wp-image-1032" width="461" height="299" srcset="https://blog.viasig.com/wp-content/uploads/2019/02/pg_tblspc_no_disco.png 614w, https://blog.viasig.com/wp-content/uploads/2019/02/pg_tblspc_no_disco-300x195.png 300w" sizes="auto, (max-width: 461px) 100vw, 461px" /><figcaption>pg_tblspc &#8211; não mexer, não imitar. A pasta DATA é off-limits!</figcaption></figure></div>



<p>Lição &#8211; <a href="https://www.postgresql.org/message-id/flat/4B4C07FB.6040006%40hogranch.com#06db7dd4abc04824400004ba4ff5bcae" target="_blank" rel="noreferrer noopener" aria-label="a directoria DATA não é para o user mexer (opens in a new tab)">a directoria DATA não é para o user mexer</a>! É de sistema, é gerida pelo postgres, está off-limits!<br>Pois mas eu não sabia… e vai daí, criei uma série de tablespaces aqui mesmo:</p>



<pre class="wp-block-preformatted">CREATE TABLESPACE meu_tablspc LOCATION 'C:\Program Files\PostgreSQL\9.3\data\meusdadosgeo';</pre>



<p>Na versão actual, o postgres vai avisar que isto não se deve fazer. Eu já fiz isto há muito tempo (comecei na 8.4), e não me lembro de aviso nenhum.<br>Anos mais tarde, ao fazer upgrades com pg_upgrade comecei a ter os problemas respectivos…</p>



<h3 class="wp-block-heading">Como funcionam os tablespaces e a directoria pg_tblspc?</h3>



<p>Para criar um tablespace novo, temos de criar previamente a directoria onde queremos que o tablespace se localize.<br>Depois executamos o sql de criação do tablespace, e o postgres vai criar um <em>link </em>(ou <em>junction </em>no Windows) na pasta DATA\pg_tblspc.<br>Quer isto dizer que não são criadas sub-dirs &#8211; são criados apontadores para a pasta de cada tablespace.<br>Em Windows, podemos verificar que são junctions usando a linha de comando e fazendo um simples dir:</p>



<pre class="wp-block-preformatted">dir "D:\Program Files\PostgreSQL\9.3\data\pg_tblspc"<br>
 Directory of D:\Program Files\PostgreSQL\9.3\data\pg_tblspc<br>
22/01/2019  13:23              .<br>
22/01/2019  13:23              ..<br>
22/01/2019  13:23         12493007 [D:\Program Files\PostgreSQL\tables<br>
paces_digc\sisma_tblspc]<br>
22/01/2019  13:23         18357 [D:\Program Files\PostgreSQL\tablespac<br>
es_digc\always_tblspc]
</pre>



<p>Podemos ver que a sub-dir 18357 é na realidade um junction que aponta para uma dir noutro local.</p>



<p>Ao criarmos os tablespaces dentro da pasta DATA estão a <a href="https://momjian.us/main/writings/pgsql/pg_upgrade.pdf" target="_blank" rel="noreferrer noopener" aria-label="ver a confusão (opens in a new tab)">ver a confusão</a>, certo? Estamos efectivamente a alterar a forma como o postgres gere os tablespaces, criando links/junctions que apontam para a pasta DATA. Quando quiserem usar o pg_upgrade, que vai tentar perceber a estrutura dos tablespaces, e não vai conseguir&#8230; resultando em erro de upgrade.</p>



<p>Se está nesta situação terá de a corrigir. Não é difícil mas como temos de alterar a estrutura e localização dos ficheiros de dados da bd é arriscado, e basta um erro para arruinar a bd. Portanto, antes de mais nada faça um snapshot da vm do postgres, ou se não é vm, faça um backup integral da bd. (<a rel="noreferrer noopener" aria-label=" (opens in a new tab)" href="https://straightpathsql.com/archives/2009/06/paranoid-control-freak-have-i-got-a-career-for-you/" target="_blank">better paranoid than dead</a>)</p>



<h3 class="wp-block-heading">Como corrigir?</h3>



<p>Os tablespaces, <a href="https://www.postgresql.org/docs/9.5/manage-ag-tablespaces.html" target="_blank" rel="noreferrer noopener" aria-label="dizem os docs (opens in a new tab)">dizem os docs</a>, devem ser criados numa pasta cujo dono é a conta do sistema operativo que controla o serviço do postgres. No meu caso é &#8220;Network Service&#8221;.<br> Assim, optei por criar uma pasta para todos os meus tablespaces na dir de instalação do postgres. Isto porque em Windows, o postgres instala as versões como sub-dirs desta:</p>



<pre class="wp-block-preformatted">C:\Program Files\PostgreSQL\9.3<br>C:\Program Files\PostgreSQL\9.5</pre>



<p>Assim, a minha pasta será criada desta forma:<br> C:\Program Files\PostgreSQL\meus_tablespaces</p>



<p>Fica à prova de apagar acidentalmente… ou pelo menos parece fazer parte da instalação o que fará pensar 2x…</p>



<pre class="wp-block-preformatted">C:\Program Files\PostgreSQL\9.3<br>C:\Program Files\PostgreSQL\9.5<br>C:\Program Files\PostgreSQL\tablespaces_adicionais</pre>



<p>Depois, paramos a bd, e vamos apagar os junctions e recriá-los apontando para subpastas correctas.</p>



<h3 class="wp-block-heading">Receita</h3>



<p>A seguir apresento, em jeito de resumo, uma sequência de passos para corrigir a situação. Os exemplos consideram que existem 2 tablespaces para corrigir.  (Será, naturalmente, melhor exportar os comandos para ficheiros de texto e criar pequenos scripts para ajudar&#8230;)</p>



<p>1) parar o serviço do postgres</p>



<p>2) vamos anotar as pastas dos nossos tablespaces, e os números dos junctions/links, vendo o conteúdo da pasta DATA\pg_tblspc:</p>



<pre class="wp-block-preformatted"> dir "D:\Program Files\PostgreSQL\9.3\data\pg_tblspc"<br>       12493007 [D:\Program Files\PostgreSQL\9.3\data\sisma_tblspc]<br>       18357 [D:\Program Files\PostgreSQL\9.3\data\always_tblspc]</pre>



<p>3) vamos mover as dirs dos nossos tablespaces para a nova localização saudável</p>



<pre class="wp-block-preformatted">move "D:\Program Files\PostgreSQL\9.3\data\sisma_tblspc"   "D:\Program Files\PostgreSQL\tablespaces_adicionais"<br>move "D:\Program Files\PostgreSQL\9.3\data\always_tblspc"   "D:\Program Files\PostgreSQL\tablespaces_adicionais" </pre>



<p>4) vamos apagar os junctions todos na pasta DATA\pg_tablspc</p>



<pre class="wp-block-preformatted">rd D:\Program Files\PostgreSQL\9.3\data\pg_tblspc\12493007<br>rd D:\Program Files\PostgreSQL\9.3\data\pg_tblspc\18357</pre>



<p>5) vamos recriar os junctions apontando-os para as dir correctas</p>



<pre class="wp-block-preformatted">mklink /J "D:\Program Files\PostgreSQL\9.3\data\pg_tblspc\12493007" "D:\Program Files\PostgreSQL\tablespaces_adicionais\sisma_tblspc"<br>mklink /J "D:\Program Files\PostgreSQL\9.3\data\pg_tblspc\18357" "D:\Program Files\PostgreSQL\tablespaces_adicionaisc\always_tblspc"</pre>



<p>6) iniciamos o serviço do postgres</p>



<p>E testamos, com diversas queries, e verificamos se no log surgem erros. Mas em principio se a bd iniciou não haverá problemas.<br>Se ocorrer um erro ao iniciar o serviço e não conseguir perceber a razão, terá de repor a situação, usando o snapshot da vm, ou restaurando toda a bd a partir do backup que fez.</p>



<p>A partir daqui, podemos ver que a estrutura dos tablespaces em disco ficou:</p>



<pre class="wp-block-preformatted">dir "D:\Program Files\PostgreSQL\tablespaces_adicionais"<br>  Volume in drive D is Data<br>  Volume Serial Number is 9CB2-EBBD<br>  Directory of D:\Program Files\PostgreSQL\tablespaces_adicionais<br> 22/01/2019  13:18              .<br> 22/01/2019  13:18              ..<br> 25/01/2019  18:58              always_tblspc<br> 25/01/2019  18:58              sisma_tblspc </pre>



<p>Interessante também, e relevante para um processo de upgrade, é ver o conteúdo destas pastas:</p>



<pre class="wp-block-preformatted">dir "D:\Program Files\PostgreSQL\tablespaces_adicionais\sisma_tblspc"<br>  Volume in drive D is Data<br>  Volume Serial Number is 9CB2-EBBD<br>  Directory of D:\Program Files\PostgreSQL\tablespaces_adicionais\sisma_tblspc<br> 25/01/2019  18:58              .<br> 25/01/2019  18:58              ..<br> 24/01/2019  18:59              PG_9.3_201306121 </pre>



<p>Ou seja, o postgresql cria uma sub-pasta marcando a versão do postgres que coloca aqui os dados. Num upgrade serão criadas aqui sub-pastas correspondentes à nova versão.</p>



<p>E isso fica para um próximo post&#8230; Até breve.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.viasig.com/2019/02/postgresql-mover-tablespaces/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PostgreSQL &#8211; autovacuum found orphan temp table</title>
		<link>https://blog.viasig.com/2019/01/postgresql-autovacuum-found-orphan-temp-table/</link>
					<comments>https://blog.viasig.com/2019/01/postgresql-autovacuum-found-orphan-temp-table/#respond</comments>
		
		<dc:creator><![CDATA[duarte]]></dc:creator>
		<pubDate>Thu, 24 Jan 2019 18:23:33 +0000</pubDate>
				<category><![CDATA[Avançado]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<guid isPermaLink="false">http://192.168.1.84:8000/?p=1023</guid>

					<description><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 2</span> <span class="rt-label rt-postfix">min</span></span>Quando o postgresql termina abruptamente de forma anormal, geralmente recupera sem problemas. Mas recentemente sucedeu-me que no log apareciam milhares de mensagens deste tipo: 2019-01-24 13:31:39 GMT LOG: autovacuum: found orphan temp table "pg_temp_56"."sde_logfile_data" in database "postgis" Aparentemente estas mensagens são escritas pelo menos todos os segundos, o que degrada o desempenho e aumenta o &#8230; <a href="https://blog.viasig.com/2019/01/postgresql-autovacuum-found-orphan-temp-table/" class="more-link">Continuar a ler<span class="screen-reader-text">PostgreSQL &#8211; autovacuum found orphan temp table</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 2</span> <span class="rt-label rt-postfix">min</span></span>
<p>Quando o postgresql termina abruptamente de forma anormal, geralmente recupera sem problemas.<br> Mas recentemente sucedeu-me que no log apareciam milhares de mensagens deste tipo:</p>



<pre class="wp-block-preformatted">2019-01-24 13:31:39 GMT LOG:  autovacuum: found orphan temp table "pg_temp_56"."sde_logfile_data" in database "postgis"</pre>



<p>Aparentemente estas mensagens são escritas pelo menos todos os segundos, o que degrada o desempenho e aumenta o tamanho dos logs.</p>



<p>Para resolver, basta apagar os schemas <del>tablespaces</del> problemáticos:<br></p>



<pre class="wp-block-preformatted">DROP SCHEMA pg_temp_56;</pre>



<p>Estes schemas <del>tablespaces </del>&#8220;especiais&#8221; podem ser listados assim:<br></p>



<pre class="wp-block-preformatted">select relname,nspname from pg_class join pg_namespace on (relnamespace=<br> pg_namespace.oid) where pg_is_other_temp_schema(relnamespace);</pre>



<p>E confirmando com as mensagens de log, podemos apagar apenas aqueles de que o autovacuum se queixa.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1024" height="563" src="https://blog.viasig.com/wp-content/uploads/2019/01/pglog_orphantemptable-1024x563.jpg" alt="" class="wp-image-1024" srcset="https://blog.viasig.com/wp-content/uploads/2019/01/pglog_orphantemptable-1024x563.jpg 1024w, https://blog.viasig.com/wp-content/uploads/2019/01/pglog_orphantemptable-300x165.jpg 300w, https://blog.viasig.com/wp-content/uploads/2019/01/pglog_orphantemptable-768x422.jpg 768w, https://blog.viasig.com/wp-content/uploads/2019/01/pglog_orphantemptable.jpg 1208w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Ao procurar na web, esta queixa não é muito frequente, mas acontece [1]. E nas listas de mail do postgresql [2], vemos até um debate acesso entre os programadores do postgres sobre se continuam a debitar este n.º exagerado de mensagens ou se devem limitar ou eliminar mesmo as mensagens. A opção actual é jogar pelo seguro &#8211; manter, para que os responsáveis pela base de dados notem que algo se passa e se preocupem o suficiente para corrigir a situação.</p>



<p>Comigo funcionou…</p>



<h4 class="wp-block-heading">Evitar conexões&#8230;</h4>



<p>É conveniente apagar estes schemas <del>tablespaces </del>tendo a certeza de que não há conexões à bd&#8230; Para isso, basta editar o ficheiro pg_hba.conf de forma a permitir apenas conexões do localhost. </p>



<p>Devemos comentar as linhas que dão acesso à bd de outros endereços, e deixar ou incluir apenas as linhas que dão acesso ao localhost. Um exemplo seria:</p>



<pre class="wp-block-preformatted">#IPv4 local connections:<br>host    all             all             127.0.0.1/32            md5<br>#IPv6 local connections:<br>host    all             all             ::1/128                 md5<br>#INTRANET - comentado temporariamente<br>#host     all     all     192.168.0.0/16  md5<br>#host     all     all     10.10.0.0/16  md5 </pre>



<p>Reiniciamos o serviço do postgresql o que provocará o fecho de todas as conexões, e o assumir da nova configuração, impedindo conexões indesejadas. No meu caso, antes disto, parei o servidor web e o servidor de mapas. Só para ser simpático e não deixar aplicações em estados de erro&#8230;</p>



<p>Depois de apagar os schemas <del>tablespaces</del>, devemos reiniciar o serviço postgresql, e verificar se no log aparecem mais avisos deste tipo, porque o autovacuum é também iniciado. Se sim, apagamos os schemas <del>tablespaces </del>em erro.</p>



<p>Quando tudo estiver ok, revertemos o pg_hba.conf para permitir novamente conexões, e reiniciamos o serviço postgresql. Testamos uma aplicação qualquer para vermos se tudo está bem. Vamos para casa ter com a família&#8230;</p>



<table class="wp-block-table"><tbody><tr><td>[1] &#8211; <a href="https://www.postgresql.org/message-id/flat/51C9975D.1040508%40uib.cat">https://www.postgresql.org/message-id/flat/51C9975D.1040508%40uib.cat</a> <br>[2] &#8211; <a href="https://www.postgresql.org/message-id/flat/48F4599D.7010601%40enterprisedb.com">https://www.postgresql.org/message-id/flat/48F4599D.7010601%40enterprisedb.com</a></td></tr></tbody></table>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.viasig.com/2019/01/postgresql-autovacuum-found-orphan-temp-table/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>LXD &#8211; upgrades sem riscos</title>
		<link>https://blog.viasig.com/2018/04/lxd-upgrades-sem-riscos/</link>
					<comments>https://blog.viasig.com/2018/04/lxd-upgrades-sem-riscos/#respond</comments>
		
		<dc:creator><![CDATA[duarte]]></dc:creator>
		<pubDate>Sat, 21 Apr 2018 16:53:47 +0000</pubDate>
				<category><![CDATA[Avançado]]></category>
		<category><![CDATA[Open Source]]></category>
		<guid isPermaLink="false">http://192.168.1.84:8000/?p=993</guid>

					<description><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 5</span> <span class="rt-label rt-postfix">min</span></span>Este artigo é o 2º da série sobre virtualização com LXD. O 1º artigo fez uma introdução rápida ao lxd. Já tenho todas as minhas aplicações web instaladas em containers LXD separados, numa vps de 3gb ram e 4 vcores, baseada em kvm. Comprei na última black friday e custa-me 5€/mês. Quem estiver à procura &#8230; <a href="https://blog.viasig.com/2018/04/lxd-upgrades-sem-riscos/" class="more-link">Continuar a ler<span class="screen-reader-text">LXD &#8211; upgrades sem riscos</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p><span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 5</span> <span class="rt-label rt-postfix">min</span></span>Este artigo é o 2º da série sobre virtualização com LXD. O 1º artigo fez uma <a href="https://blog.viasig.com/2018/01/lxd-o-virtualizador-ubuntu/">introdução rápida ao lxd</a>.</p>
<p>Já tenho todas as minhas aplicações web instaladas em containers LXD separados, numa vps de 3gb ram e 4 vcores, baseada em kvm. Comprei na última black friday e custa-me 5€/mês. Quem estiver à procura de vps baratas recomendo verem aqui: <a href="https://lowendbox.com/" target="_blank" rel="noopener noreferrer">https://lowendbox.com/</a>.</p>
<p>Nesta altura, tenho 3 máquinas:</p>
<pre style="font-size: 90%;">~$ lxc list
+------------+---------+----------------------+------+------------+-----------+
|    NAME    |  STATE  |         IPV4         | IPV6 |    TYPE    | SNAPSHOTS |
+------------+---------+----------------------+------+------------+-----------+
| dncplex    | RUNNING | 10.166.62.195 (eth0) |      | PERSISTENT | 0         |
+------------+---------+----------------------+------+------------+-----------+
| planetasig | RUNNING | 10.166.62.245 (eth0) |      | PERSISTENT | 0         |
+------------+---------+----------------------+------+------------+-----------+
| viasigwp   | RUNNING | 10.166.62.152 (eth0) |      | PERSISTENT | 0         |
+------------+---------+----------------------+------+------------+-----------+</pre>
<p>A máquina &#8220;dncplex&#8221; é o meu servidor de música, com plex server e o fantástico <a href="https://www.mymediaalexa.com/" target="_blank" rel="noopener noreferrer">MyMedia for Alexa</a>! que permite aceder à minha biblioteca de música no meu Echo!</p>
<p>A &#8220;planetasig&#8221; é obviamente o <a href="http://planetasig.viasig.com/" target="_blank" rel="noopener noreferrer">PlanetaSIG</a>, e a &#8220;viasigwp&#8221; é este mesmo blog.</p>
<p>Como tive sempre receio de upgrades de versões major no wordpress fui adiando o upgrade da v3 para a v4. E esta já vai na v4.9.5. Está mesmo na altura de fazer o upgrade à prova de falha.</p>
<p>Uma vez que uso o lxd, o plano é copiar o container para um novo, e fazer aí o upgrade. Se correr bem, paro o container antigo v3, e fico com o novo já com o wordpress v4. Se correr mal, apago e recomeço, ou desisto e fico na mesma&#8230; risco 0&#8230;<span id="more-993"></span></p>
<h5>Clonar o container original</h5>
<p>Para copiar ou clonar um container lxd é muito simples &#8211; basta usar o comando <em>copy</em>:</p>
<pre style="font-size: 90%;">$ lxc copy viasigwp viasigwp4

$ lxc list
 +------------+---------+----------------------+------+------------+-----------+
 | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
 +------------+---------+----------------------+------+------------+-----------+
 | dncplex | RUNNING | 10.166.62.195 (eth0) | | PERSISTENT | 0 |
 +------------+---------+----------------------+------+------------+-----------+
 | planetasig | RUNNING | 10.166.62.245 (eth0) | | PERSISTENT | 0 |
 +------------+---------+----------------------+------+------------+-----------+
 | viasigwp | RUNNING | 10.166.62.152 (eth0) | | PERSISTENT | 0 |
 +------------+---------+----------------------+------+------------+-----------+
 | viasigwp4 | STOPPED | | | PERSISTENT | 0 |
 +------------+---------+----------------------+------+------------+-----------+</pre>
<p>Ok, o nosso novo container está parado. Temos de o iniciar&#8230;</p>
<pre style="font-size: 90%;">$ lxc start viasigwp4
$ lxc list
 +------------+---------+----------------------+------+------------+-----------+
 | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
 +------------+---------+----------------------+------+------------+-----------+
 | dncplex | RUNNING | 10.166.62.195 (eth0) | | PERSISTENT | 0 |
 +------------+---------+----------------------+------+------------+-----------+
 | planetasig | RUNNING | 10.166.62.245 (eth0) | | PERSISTENT | 0 |
 +------------+---------+----------------------+------+------------+-----------+
 | viasigwp | RUNNING | 10.166.62.152 (eth0) | | PERSISTENT | 0 |
 +------------+---------+----------------------+------+------------+-----------+
 | viasigwp4 | RUNNING | | | PERSISTENT | 0 |
 +------------+---------+----------------------+------+------------+-----------+</pre>
<p>O IP ainda não está atribuído pelo dhcp do lxd, mas é só esperar um pouco e será atribuído um novo IP. (acabou por ser atribuído o ip 10.166.62.181)</p>
<p>Vamos parar o container original para evitar confusões e termos a certeza que vamos realmente usar o novo. O comando para parar containers lxd é <em>stop</em> obviamente:</p>
<pre>$ lxc stop viasigwp</pre>
<h5>Configurar o tráfego no HAProxy</h5>
<p>Eu ainda farei um artigo sobre a configuração do tráfego entre a internet e os containers lxd. Por agora, vou apenas rapidamente mostrar a alteração do ip ligado ao domínio do blog.viasig.com. Ou seja, o tráfego que chega à vps usando o nome blog.viasig.com era dirigido para o container original &#8220;viasigwp&#8221; com ip 10.166.62.245.</p>
<p>Agora, temos um novo container, onde faremos o upgrade, que tem um novo ip 10.166.62.181. É para este novo ip que o HAProxy deve enviar o tráfego do endereço blog.viasig.</p>
<p>Mostro abaixo a parte da configuração do HAProxy relevante para o blog a negrito e laranja (apenas no final da secção abaixo):</p>
<pre>$ sudo nano /etc/haproxy/haproxy.cfg

frontend public
 # Listen on port 80
 bind *:80

 mode http

#redirecionamentos de dominios http para https,
#antes de definirmos os servidores http para os dominios http
#1-blog.viasig.com
redirect scheme https code 301 if !{ ssl_fc } { hdr(host) -i blog.viasig.com }

#como uso https no blog, este é o frontend que redireciona o seu trafego
frontend public_https
 bind *:443
 mode tcp
 option tcplog
 tcp-request inspect-delay 5s
 tcp-request content accept if { req_ssl_hello_type 1 }
 default_backend bk_ssl_default

backend bk_ssl_default
 mode tcp
 option tcplog
 acl blogviasig_https req_ssl_sni -i blog.viasig.com

 use-server server1 if blogviasig_https

 <span style="color: #ff6600;">option ssl-hello-chk
 <strong>#o blog v3 é desativado</strong>
<strong> #server server1 10.166.62.152:443 check</strong>
<strong> #e o novo v4 é ativado</strong>
<strong> server server1 10.166.62.181:443 check</strong></span></pre>
<p>Testamos a configuração só para ter a certeza que está correcta, e carregamos a nova config:</p>
<pre>$ <span style="color: #ff6600;"><strong>sudo haproxy -c -V -f /etc/haproxy/haproxy.cfg</strong></span>
 Configuration file is valid
 $ <span style="color: #ff6600;"><strong>sudo systemctl reload haproxy</strong></span>
 $ <span style="color: #ff6600;"><strong>systemctl status haproxy</strong></span>
 ● haproxy.service - HAProxy Load Balancer
 Loaded: loaded (/lib/systemd/system/haproxy.service; enabled; vendor preset:
 Active: active (running) (Result: exit-code) since Tue 2018-12-04 19:16:08 WE
 Docs: man:haproxy(1)
 file:/usr/share/doc/haproxy/configuration.txt.gz
 Process: 31800 ExecReload=/bin/kill -USR2 $MAINPID (code=exited, status=0/SUCC
 Process: 31797 ExecReload=/usr/sbin/haproxy -c -f ${CONFIG} (code=exited, stat
 Process: 995 ExecStartPre=/usr/sbin/haproxy -f ${CONFIG} -c -q (code=exited, s
 Main PID: 1019 (haproxy-systemd)
 Tasks: 3
 Memory: 5.2M
 CPU: 23min 7.777s
 CGroup: /system.slice/haproxy.service
 ├─ 1019 /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg
 ├─31808 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy
 └─31809 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy</pre>
<h5>Upgrade do wordpress</h5>
<p>Podemos usar o browser para abrir o endereço blog.viasig.com e fazer o upgrade. É só clicar no botão de upgrade e rapidamente temos o ecrã de sucesso:</p>
<p><figure id="attachment_995" aria-describedby="caption-attachment-995" style="width: 445px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="wp-image-995 size-full" src="https://blog.viasig.com/wp-content/uploads/2018/04/Pasted-into-LXD-upgrade-de-wordpress-sem-riscos.png" alt="" width="445" height="596" srcset="https://blog.viasig.com/wp-content/uploads/2018/04/Pasted-into-LXD-upgrade-de-wordpress-sem-riscos.png 445w, https://blog.viasig.com/wp-content/uploads/2018/04/Pasted-into-LXD-upgrade-de-wordpress-sem-riscos-224x300.png 224w" sizes="auto, (max-width: 445px) 100vw, 445px" /><figcaption id="caption-attachment-995" class="wp-caption-text">Novo wp sem riscos&#8230;</figcaption></figure></p>
<h5>Arrumação final</h5>
<p>Tudo correu bem. Podemos ver a lista dos containers como ficou:</p>
<pre style="font-size: 90%;">$ lxc list
 +------------+---------+----------------------+------+------------+-----------+
 | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
 +------------+---------+----------------------+------+------------+-----------+
 | dncplex | RUNNING | 10.166.62.195 (eth0) | | PERSISTENT | 0 |
 +------------+---------+----------------------+------+------------+-----------+
 | planetasig | RUNNING | 10.166.62.245 (eth0) | | PERSISTENT | 0 |
 +------------+---------+----------------------+------+------------+-----------+
 | viasigwp | STOPPED | | | PERSISTENT | 0 |
 +------------+---------+----------------------+------+------------+-----------+
 | viasigwp4 | RUNNING | 10.166.62.181 (eth0) | | PERSISTENT | 0 |
 +------------+---------+----------------------+------+------------+-----------+</pre>
<p>Podemos apagar o container  viasigwp quando tivermos a certeza que já não precisamos delete, com o comando <em>lxc delete viasigwp</em>.</p>
<p>Por agora está parado&#8230; apenas a ocupar 1,4GB de disco:</p>
<pre>$ sudo du -sh /var/lib/lxd/containers/viasigwp
1.4G /var/lib/lxd/containers/viasigwp</pre>
<p>Já agora, podemos ver a memória usada pelo wp4:</p>
<pre>$ <span style="color: #ff6600;"><strong>lxc info viasigwp4</strong></span>
Name: viasigwp4
Remote: unix://
Architecture: x86_64
Created: 2018/04/13 21:43 UTC
Status: Running
Type: persistent
Profiles: default
Pid: 30377
Ips:
 eth0: inet 10.166.62.181 vethFNKBJU
 eth0: inet6 fe80::216:3eff:fef9:2084 vethFNKBJU
 lo: inet 127.0.0.1
 lo: inet6 ::1
Resources:
 Processes: 69
 Memory usage:
 Memory (current): <strong>576.75MB</strong>
 Memory (peak): <strong>719.80MB</strong>
 Network usage:
 eth0:
 Bytes received: 303.39MB
 Bytes sent: 601.68MB
 Packets received: 2521373
 Packets sent: 1531654
 lo:
 Bytes received: 0B
 Bytes sent: 0B
 Packets received: 0
 Packets sent: 0</pre>
<p>Podemos ver que depois de 1 semana, o wp 4 usou um máximo de 719MB de memória. Podemos limitar a memória máxima disponível a um container lxd, bem como limitar o uso de processador, espaço em disco e a velocidade de acesso ou IOps,  e da mesma forma para a placa de rede. Tudo  sobre o controle de recursos no lxd pode ser visto aqui com detalhe: <a href="https://stgraber.org/2016/03/26/lxd-2-0-resource-control-412/" target="_blank" rel="noopener noreferrer">https://stgraber.org/2016/03/26/lxd-2-0-resource-control-412/</a>.</p>
<p>No meu caso, limitei a memória máxima do container do plex server a apenas 512MB. Isto porque o plex tem a mania de usar toda a memória que encontra!! O comando que usei foi:</p>
<pre>lxc config set dncplex limits.memory 512MB</pre>
<p>Podemos ver as configurações com o comando inverso de <em>config show</em>:</p>
<pre>$ <span style="color: #ff6600;"><strong>lxc config show dncplex</strong></span>
architecture: x86_64
config:
 <strong>limits.memory: 512MB</strong>
 volatile.base_image: e1e62217dabb1acff585f13472af44b2720839546d1c3fb60d6187afa91fc995
 volatile.eth0.hwaddr: 00:16:3e:dd:e6:40
 volatile.idmap.base: "0"
 volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":100000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":100000,"Nsid":0,"Maprange":65536}]'
 volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":100000,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":100000,"Nsid":0,"Maprange":65536}]'
 volatile.last_state.power: RUNNING
devices:
 root:
 path: /
 type: disk
ephemeral: false
profiles:
- default
stateful: false
description: ""</pre>
<p>Assim, a memória fica controlada.</p>
<p>E é tudo&#8230; se tudo correr bem o próximo artigo será sobre HAProxy&#8230;</p>
<p>Saudações virtuais!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.viasig.com/2018/04/lxd-upgrades-sem-riscos/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>LXD o virtualizador ubuntu</title>
		<link>https://blog.viasig.com/2018/01/lxd-o-virtualizador-ubuntu/</link>
					<comments>https://blog.viasig.com/2018/01/lxd-o-virtualizador-ubuntu/#comments</comments>
		
		<dc:creator><![CDATA[duarte]]></dc:creator>
		<pubDate>Thu, 18 Jan 2018 22:54:07 +0000</pubDate>
				<category><![CDATA[Avançado]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[lxd]]></category>
		<category><![CDATA[virtualização]]></category>
		<guid isPermaLink="false">http://192.168.1.84:8000/?p=945</guid>

					<description><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 8</span> <span class="rt-label rt-postfix">min</span></span>Este post é sobre o LXD, uma forma de criar &#8220;máquinas virtuais&#8221; que residem em directorias na nossa máquina, sem mais intermediários (hypervisors). Para quem usa docker podem ver mais info sobre o projecto e como se comparam os 2: https://www.ubuntu.com/containers/lxd. Fica já a nota que o docker e o lxd são concorrentes, mas talvez &#8230; <a href="https://blog.viasig.com/2018/01/lxd-o-virtualizador-ubuntu/" class="more-link">Continuar a ler<span class="screen-reader-text">LXD o virtualizador ubuntu</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p><span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 8</span> <span class="rt-label rt-postfix">min</span></span>Este post é sobre o LXD, uma forma de criar &#8220;máquinas virtuais&#8221; que residem em directorias na nossa máquina, sem mais intermediários (hypervisors). Para quem usa docker podem ver mais info sobre o projecto e como se comparam os 2: <a href="https://www.ubuntu.com/containers/lxd" target="_blank" rel="noopener noreferrer">https://www.ubuntu.com/containers/lxd</a>.</p>
<p>Fica já a nota que o docker e o lxd são concorrentes, mas talvez sejam mais complementares. O docker isola componentes, o lxd isola sistemas operativos. Terão por isso vantagens e desvantagens muitas vezes simétricas. E ambos são similares na tecnologia de base que usam (lxc e <a href="https://en.wikipedia.org/wiki/Chroot" target="_blank" rel="noopener noreferrer">chroot</a> + <a href="https://en.wikipedia.org/wiki/Cgroups" target="_blank" rel="noopener noreferrer">cgroups</a>). Basicamente, usam capacidades do kernel linux para isolar componentes (é por isso que só podemos &#8220;virtualizar&#8221; componentes linux e não windows ou mac). Na verdade, e para ser tecnicamente menos incorrecto, não se criam máquinas virtuais, mas sim <em>containers</em>. Mas para simplicidade, no resto do texto quando falo de containers ou VM&#8217;s é tudo o mesmo&#8230; containers.</p>
<p>Aquilo que me entusiasma no LXD é a simplicidade de uso, com muito poucos  comandos, e a facilidade de gerir sistemas que integram vários componentes, como geralmente acontece numa plataforma SIG (qgis, postgresql, geoserver, etc.). Como o LXD virtualiza um SO inteiro, é natural e fácil usá-lo para conter sistemas aplicacionais inteiros.</p>
<p>As máquinas LXD podem ser criadas em directorias no nosso servidor Ubuntu, e podem conter diversos sistemas operativos. E é muito fácil clonar, fazer snapshots, parar e iniciar estes contentores de SO. Já cópias de segurança obrigam a alguma ginástica, mas estão a trabalhar num método simplificado.</p>
<p>Também é fácil limitar os recursos usados por cada VM, quer na memória máxima, quer no processador (cores, % de tempo, etc.), e vários outros recursos. Podem ver info completa aqui: <a href="https://stgraber.org/2016/03/26/lxd-2-0-resource-control-412/" target="_blank" rel="noopener noreferrer">https://stgraber.org/2016/03/26/lxd-2-0-resource-control-412/</a>.</p>
<p>A existência do LXD vem baixar a complexidade da virtualização baseada em containers, deixando de usar hypervisors como o KVM, OpenVZ, VMWare, VirtualBox, e HyperV.</p>
<p>Podemos instalar o Ubuntu directamente na máquina física, e criar VM&#8217;s usando comandos LXD. Os seus defensores indicam ganhos de desempenho, ou mais correctamente menos perda de desempenho, e por isso potencial maior densidade de VM&#8217;s. Não posso confirmar nem desmentir porque não testei nada disto. Mas parece-me algo lógico.</p>
<p>Só mais um detalhe &#8211; o LXD suporta nested virtualization, ou seja, dentro de uma VM Ubuntu podemos usá-lo para criar VM&#8217;s, que estão dentro da nossa VM inicial&#8230; confuso? Cuidado, que o OpenVZ não suporta lxd&#8230; portanto ao comprarem uma VPS assegurem-se que é baseada em KVM.</p>
<p></p>
<p><iframe loading="lazy" title="Numen-Light 01 / www.numen.eu / www.numen-light.eu" width="604" height="453" src="https://www.youtube.com/embed/2T5OVm119VM?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></p>
<p>Nested Virtualization&#8230; whaaat?<span id="more-945"></span></p>
<h4>Instalar o LXD</h4>
<p>Instalar o LXD é muito simples &#8211; já vem incluído no Ubuntu.</p>
<p>É preciso no entanto iniciá-lo uma primeira vez e definir a sua configuração, que principalmente define o tipo <em>storage</em> usado pelas máquinas a criar (baseadas em directorias ou pools zfs), e a configuração da rede que dirá se as VM&#8217;s são acessíveis do exterior, e se poderão comunicar entre si.</p>
<p>O tutorial que usei como base foi este da Digital Ocean: <a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-and-use-lxd-on-ubuntu-16-04" target="_blank" rel="noopener noreferrer">https://www.digitalocean.com/community/tutorials/how-to-set-up-and-use-lxd-on-ubuntu-16-04</a>.</p>
<p>A diferença é que escolhi usar directorias para mais simplicidade, em vez de ZFS. Embora ZFS seja a opção recomendada pela Canonical, fabricante do Ubuntu, envolve uma complexidade que seria contraproducente para mim &#8211; o objectivo é ter simplicidade máxima e o menor número de pontos de falha. Mais info aqui: <a href="https://insights.ubuntu.com/2016/02/16/zfs-is-the-fs-for-containers-in-ubuntu-16-04/" target="_blank" rel="noopener noreferrer">https://insights.ubuntu.com/2016/02/16/zfs-is-the-fs-for-containers-in-ubuntu-16-04/</a>.</p>
<p>Então, a sessão de configuração do lxd foi assim (o meu user é dncpax e as respostas estão a negrito):</p>
<pre>$ sudo usermod --append --groups lxd dncpax
$ sudo lxd init
Do you want to configure a new storage pool (yes/no) [default=yes]? <strong>y</strong>
Name of the storage backend to use (dir or zfs) [default=dir]: <strong>dir</strong>
Would you like LXD to be available over the network (yes/no) [default=no]? <strong>no</strong>
Do you want to configure the LXD bridge (yes/no) [default=yes]? <strong>yes</strong>
</pre>
<p>Como se vê escolhi sempre os defaults.</p>
<p>Neste ponto, o lxd lança um wizard de configuração da rede em modo texto (podemos usar num terminal). Se respondermos sempre com defaults, vamos ter no final uma rede interna gerida pelo LXD, do tipo 10.0.0.X.</p>
<p>Desta forma, as VM&#8217;s poderão contactar a máquina &#8220;mãe&#8221; e outras VM&#8217;s, e também a Internet. Mas não receberão tráfego exterior, ou seja, ninguém conseguirá aceder às nossas VM&#8217;s.</p>
<p>(Para permitir o acesso do &#8220;exterior&#8221; às nossas VM&#8217;s LXD vamos ter de usar algum tipo de router/firewall (IPTables) ou reverse proxy (NGinx ou HAProxy). Eu escolhi usar o HAProxy, que veremos noutro artigo.)</p>
<p>Durante o wizard, vai ser configurada uma rede IPv4, e opcionalmente uma rede IPv6. Eu usei sempre os defaults, mas não configurei a rede IPv6:</p>
<p><figure id="attachment_955" aria-describedby="caption-attachment-955" style="width: 570px" class="wp-caption aligncenter"><a href="https://blog.viasig.com/wp-content/uploads/2018/01/lxd_net_wiz_ipv6.png"><img loading="lazy" decoding="async" class="size-full wp-image-955" src="https://blog.viasig.com/wp-content/uploads/2018/01/lxd_net_wiz_ipv6.png" alt="wizard do lxd para configurar a rede" width="570" height="168" srcset="https://blog.viasig.com/wp-content/uploads/2018/01/lxd_net_wiz_ipv6.png 570w, https://blog.viasig.com/wp-content/uploads/2018/01/lxd_net_wiz_ipv6-300x88.png 300w" sizes="auto, (max-width: 570px) 100vw, 570px" /></a><figcaption id="caption-attachment-955" class="wp-caption-text">wizard do lxd para configurar a rede IPv6</figcaption></figure></p>
<p>A minha rede foi configurada como 10.70.99.X, e assim todas as VM&#8217;s terão um IP deste tipo.</p>
<h4>Utilizar LXD</h4>
<p>A partir daqui temos os comandos do lxd ao dispor. Parte são baseados em lxc e outros em lxd. (lxc é o componente de base do lxd.)</p>
<p>Por exemplo, ver as VM&#8217;s criadas (não há ainda) &#8211; lxc list:</p>
<pre>$ lxc list
+------+--------+------+------+------+-----------+
| NOME | ESTADO | IPV4 | IPV6 | TIPO | SNAPSHOTS |
+------+--------+------+------+------+-----------</pre>
<p>Nota: se tiverem um erro de permissão negada, é porque o vosso novo grupo lxd não está ainda &#8220;activo&#8221;. Podem fechar a sessão e abrir uma nova com o mesmo login e continuar o trabalho, ou executarem &#8220;newgrp lxd&#8221;.</p>
<p>Ver a configuração do lxd &#8211; lxc info:</p>
<pre>$ lxc info
config: {}
api_extensions:
- id_map
- id_map_base
- resource_limits
api_status: stable
api_version: "1.0"
auth: trusted
auth_methods: []
public: false
environment:
  addresses: []
  architectures:
  - x86_64
  - i686
  certificate: |
    -----BEGIN CERTIFICATE-----
    MIIFWzCCA0OgAwIVK3ESSSDQAIgte5p8cNcFQHJo0byAjiQD2YkT/sXr+3mf5U
    bla bla bla bla
    hTuelEv1+SWzBsN2nDbF7ZUDhw4cioBS59fkWidNrg==
    -----END CERTIFICATE-----
  certificate_fingerprint: 85ab3c61 bla 6d2bae
  driver: lxc
  driver_version: 2.0.8
  kernel: Linux
  kernel_architecture: x86_64
  kernel_version: 4.4.0-109-generic
  server: lxd
  server_pid: 3276
  server_version: 2.0.11
  storage: dir
  storage_version: ""</pre>
<p>Então o que temos por agora? Um deamon lxd que coordenará a existência e o isolamento das VM&#8217;s a criar. Podemos ver o seu estado actual com systemctl (notem a memória ocupada):</p>
<pre>systemctl status lxd
● lxd.service - LXD - main daemon
   Loaded: loaded (/lib/systemd/system/lxd.service; indirect; vendor preset: ena
   Active: active (running) since Qui 2018-01-18 21:35:36 WET; 14min ago
     Docs: man:lxd(1)
  Process: 3315 ExecStartPost=/usr/bin/lxd waitready --timeout=600 (code=exited,
  Process: 3277 ExecStartPost=/usr/lib/lxd/profile-config (code=exited, status=0
  Process: 3265 ExecStartPre=/usr/lib/x86_64-linux-gnu/lxc/lxc-apparmor-load (co
 Main PID: 3276 (lxd)
    Tasks: 9
   Memory: 7.5M
      CPU: 438ms
   CGroup: /system.slice/lxd.service
           └─3276 /usr/bin/lxd --group lxd --logfile=/var/log/lxd/lxd.log

Jan 18 21:35:35 ubuntumin systemd[1]: Starting LXD - main daemon...
Jan 18 21:35:36 ubuntumin lxd[3276]: lvl=warn msg="CGroup memory swap accounting
Jan 18 21:35:36 ubuntumin systemd[1]: Started LXD - main daemon.</pre>
<h4>Criar e gerir VM&#8217;s</h4>
<p>Trabalhar com VM&#8217;s ou containers LXD é muito fácil, e basicamente limita-se a estes passos:</p>
<ol>
<li>Criar o container com o OS escolhido</li>
<li>Aceder ao container na nossa shell ou por ssh</li>
<li>Configurar alguns limites se quisermos (de memória p.e.)</li>
<li>Parar ou reiniciar um container</li>
<li>Ver os detalhes de um container, incluindo memória ocupada</li>
</ol>
<p>A melhor página que conheço sobre gestão de containers LXD é esta: <a href="https://insights.ubuntu.com/2016/03/22/lxd-2-0-your-first-lxd-container/" target="_blank" rel="noopener noreferrer">https://insights.ubuntu.com/2016/03/22/lxd-2-0-your-first-lxd-container/</a></p>
<p>Então para criar uma VM de Ubuntu dentro do nosso Ubuntu <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> usamos o comando lxc launch. O sistema operativo que queremos usar pode ser escolhido de uma lista já extensa que pode ser consultada aqui: <a href="https://us.images.linuxcontainers.org/" target="_blank" rel="noopener noreferrer">https://us.images.linuxcontainers.org/</a>.</p>
<p>Antes de instalar uma máquina novinha vamos antes ver como temos a memória:</p>
<pre><span class="inner-pre" style="font-size: 80%;">$ free -m
              total        used        free      shared  buff/cache   available
Mem:           2000          47        1501           3         451        1795</span></pre>
<p>Como se vê, estamos só com 47MB usados e 451MB em cache.</p>
<p>Para instalar a nova vm chamada &#8220;wordpress1&#8221; (como é a 1ª vez, a imagem é descarregada do repositório online):</p>
<pre>$ lxc launch ubuntu:16.04 wordpress1
A criar wordpress1
A iniciar wordpress1</pre>
<p>E pronto. Temos um novo ubuntu fresquinho. Podemos ver na lista de containers com lxc list:</p>
<pre><span class="inner-pre" style="font-size: 80%;">$ lxc list
+------------+---------+---------------------+------+-------------+-----------+
|    NOME    | ESTADO  |        IPV4         | IPV6 |    TIPO     | SNAPSHOTS |
+------------+---------+---------------------+------+-------------+-----------+
| wordpress1 | RUNNING | 10.70.99.165 (eth0) |      | PERSISTENTE | 0         |
+------------+---------+---------------------+------+-------------+-----------+
</span></pre>
<p>Podemos ver a lista dos containers, se estão iniciados, e os endereços IP internos.</p>
<p>Para vermos a configuração de um container, incluíndo a memória usada:</p>
<pre>$ lxc info wordpress1
Nome: wordpress1
Remote: unix://
Arquitetura: x86_64
Criado: 2018/01/18 22:20 UTC
Estado: Running
Tipo: persistente
Perfis: default
Pid: 4426
Ips:
  eth0: inet    10.70.99.165    vethWJS19I
  eth0: inet6   fe80::216:3eff:fef3:793c        vethWJS19I
  lo:   inet    127.0.0.1
  lo:   inet6   ::1
Recursos:
  Processos: 27
  Memory usage:
    Memória (atual): 31.77MB
    Memória (máxima): 152.54MB
  Network usage:
    lo:
      Bytes recebidos: 0B
      Bytes enviados: 0B
      Pacotes recebidos: 0
      Pacotes enviados: 0
    eth0:
      Bytes recebidos: 195.18kB
      Bytes enviados: 7.45kB
      Pacotes recebidos: 138
      Pacotes enviados: 90</pre>
<p>Até agora a memória ocupada variou entre 31 e 157 MB&#8230;</p>
<p>Para aceder podemos usar ssh ou um comando do lxc (exec):</p>
<pre>$ lxc exec wordpress1 -- sudo --login --user ubuntu
To run a command as administrator (user "root"), use "sudo &lt;command&gt;".
See "man sudo_root" for details.

ubuntu@wordpress1:~</pre>
<p>Estamos agora &#8220;dentro&#8221; da nova máquina wordpress1, com o login ubuntu&#8230; podemos ver os seus processos de forma isolada, sem acesso à máquina mãe:</p>
<pre><span class="inner-pre" style="font-size: 80%;">$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.2  37596  5616 ?        Ss   22:20   0:00 /sbin/init
root        55  0.0  0.1  41724  3284 ?        Ss   22:20   0:00 /lib/systemd/sy
root        57  0.0  0.1  35280  3228 ?        Ss   22:20   0:00 /lib/systemd/sy
root       232  0.0  0.0  16000   856 ?        Ss   22:20   0:00 /sbin/dhclient
daemon     318  0.0  0.1  26048  2164 ?        Ss   22:20   0:00 /usr/sbin/atd -
syslog     324  0.0  0.1 186904  3288 ?        Ssl  22:20   0:00 /usr/sbin/rsysl
root       326  0.0  0.0  20104  1208 ?        Ss   22:20   0:00 /lib/systemd/sy
root       327  0.0  0.2 272872  5960 ?        Ssl  22:20   0:00 /usr/lib/accoun
root       328  0.0  0.2  65524  5476 ?        Ss   22:20   0:00 /usr/sbin/sshd
message+   329  0.0  0.1  42896  3828 ?        Ss   22:20   0:00 /usr/bin/dbus-d
root       341  0.0  0.1  26072  2528 ?        Ss   22:20   0:00 /usr/sbin/cron
root       342  0.0  1.2 158844 26576 ?        Ssl  22:20   0:00 /usr/lib/snapd/
root       350  0.0  0.4 277184  8260 ?        Ssl  22:20   0:00 /usr/lib/policy
root       378  0.0  0.0  12848  1784 ?        Ss+  22:20   0:00 /sbin/agetty --
root       441  0.0  0.1  59508  4032 ?        Ss   22:25   0:00 sudo --login --
ubuntu     442  0.0  0.2  23012  5064 ?        S    22:25   0:00 -bash
ubuntu     459  0.0  0.1  37764  3276 ?        R+   22:26   0:00 ps aux</span></pre>
<p>A partir daqui podemos instalar o que quisermos da forma habitual. Podemos aceder ao exterior, mas não o inverso &#8211; do exterior aceder ao nosso container. E isso será para resolver noutro post.</p>
<p>Por agora, deixem-me terminar com um pequeno teste de desempenho. Uso sempre o 7zip para testes rápidos de cpu. Portanto vamos instalar o 7zip no container testar o cpu com só 1 thread, e depois fazer o mesmo na máquina mãe, para vermos neste caso a quebra de rendimento.</p>
<pre>$ sudo apt-get update
Hit:1 http://archive.ubuntu.com/ubuntu xenial InRelease
bla bla
Fetched 24.6 MB in 10s (2276 kB/s)
Reading package lists... Done
$ sudo apt-get install 7zip-full
bla bla
Setting up p7zip-full (9.20.1~dfsg.1-4.2) ...
$ 7z b -mmt1

7-Zip [64] 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18
p7zip Version 9.20 (locale=C.UTF-8,Utf16=on,HugeFiles=on,2 CPUs)

RAM size:    2000 MB,  # CPU hardware threads:   2
RAM usage:    419 MB,  # Benchmark threads:      1

Dict        Compressing          |        Decompressing
      Speed Usage    R/U Rating  |    Speed Usage    R/U Rating
       KB/s     %   MIPS   MIPS  |     KB/s     %   MIPS   MIPS

22:    3917   100   3811   3810  |    41983   100   3791   3790
23:    3735   100   3806   3806  |    39076   100   3578   3577
24:    3337   100   3589   3588  |    39359   100   3652   3652
25:    3339   100   3812   3812  |    39856   100   3748   3748
----------------------------------------------------------------
Avr:          100   3755   3754               100   3692   3692
Tot:          100   3723   3723</pre>
<p>Portanto, dentro do container temos um total de 3723 MIPS de compressão. Vamos sair do container e fazer o mesmo exercício:</p>
<pre>ubuntu@wordpress1:~$ exit
logout
dncpax@ubuntumin:~$
dncpax@ubuntumin:~$ 7z b -mmt1

7-Zip [64] 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18
p7zip Version 9.20 (locale=pt_PT.UTF-8,Utf16=on,HugeFiles=on,2 CPUs)

RAM size:    2000 MB,  # CPU hardware threads:   2
RAM usage:    419 MB,  # Benchmark threads:      1

Dict        Compressing          |        Decompressing
      Speed Usage    R/U Rating  |    Speed Usage    R/U Rating
       KB/s     %   MIPS   MIPS  |     KB/s     %   MIPS   MIPS

22:    3815   100   3712   3711  |    41670   100   3762   3762
23:    3696   100   3767   3766  |    41115   100   3765   3764
24:    3557   100   3825   3825  |    40444   100   3753   3753
25:    3408   100   3891   3891  |    40016   100   3764   3763
----------------------------------------------------------------
Avr:          100   3799   3798               100   3761   3761
Tot:          100   3780   3779</pre>
<p>Temos então na máquina LXD 3780 MIPS de compressão.</p>
<p>Ou seja, 3723/3780 = 98% de desempenho no container! Sim, é um teste simplista, e não representa uma avaliação real, mas é óptimo indicador.</p>
<p>E pronto, acabo por aqui. O próximo post da série será dedicado a coisas mais sérias, como ter várias máquinas LXD a comunicar com o exterior, e ver como limitar os recursos usados por uma delas. Até breve.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.viasig.com/2018/01/lxd-o-virtualizador-ubuntu/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Medir o desempenho do PostGIS</title>
		<link>https://blog.viasig.com/2015/03/medir-o-desempenho-do-postgis/</link>
					<comments>https://blog.viasig.com/2015/03/medir-o-desempenho-do-postgis/#respond</comments>
		
		<dc:creator><![CDATA[duarte]]></dc:creator>
		<pubDate>Fri, 27 Mar 2015 18:14:37 +0000</pubDate>
				<category><![CDATA[Intermédio]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[postgis]]></category>
		<category><![CDATA[QGIS]]></category>
		<guid isPermaLink="false">http://blogteste.viasig.com/?p=893</guid>

					<description><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 6</span> <span class="rt-label rt-postfix">min</span></span>Uma das formas de medir o desempenho do PostgreSQL no nosso servidor, é usar o pgbench, a ferramenta padrão incluída com a instalação do pgsql. Há tempos fiz uns testes de comparação de 2 servidores que publiquei aqui: https://blog.viasig.com/2014/08/medir-o-desempenho-do-postgresql/. Ora, esses testes usam dados alfanuméricos e queries “normais”, de escrita e leitura, usando tabelas relacionadas. &#8230; <a href="https://blog.viasig.com/2015/03/medir-o-desempenho-do-postgis/" class="more-link">Continuar a ler<span class="screen-reader-text">Medir o desempenho do PostGIS</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p><span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 6</span> <span class="rt-label rt-postfix">min</span></span>Uma das formas de medir o desempenho do PostgreSQL no nosso servidor, é usar o <a title="pgbench: documentação" href="http://www.postgresql.org/docs/devel/static/pgbench.html" target="_blank" rel="noopener noreferrer">pgbench</a>, a ferramenta padrão incluída com a instalação do pgsql. Há tempos fiz uns testes de comparação de 2 servidores que publiquei aqui: https://blog.viasig.com/2014/08/medir-o-desempenho-do-postgresql/.</p>
<p>Ora, esses testes usam dados alfanuméricos e queries “normais”, de escrita e leitura, usando tabelas relacionadas. Ou seja, o pgbench tenta simular uma utilização usual do pgsql.</p>
<p>No nosso caso, SIGianos, a utilização usual não tem nada a haver – usamos dados espaciais e queries muito próprias. Este artigo mostra uma forma de medirmos o desempenho do PostGIS, usando também a ferramenta pgbench.</p>
<h4>Uso “normal” de SIG</h4>
<p>Quando um programa “normal”, não geográfico, consulta uma base de dados, em geral, obtém alguns registos, e pode até cruzá-los, para dar um resultado final. Provavelmente, apresenta uma tabela de resultados, paginados, com algumas colunas (menos de 10?). Um bom exemplo, é um programa de facturação ou de gestão de stocks. É este tipo de programas que o pgbench tenta simular.</p>
<p>Há uma enorme diferença para o uso que um programa de SIG faz de uma base de dados. O uso normal SIG é visualizar um mapa. E isso faz toda a diferença.</p>
<p><a href="/wp-content/uploads/2015/03/image.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="/wp-content/uploads/2015/03/image_thumb.png" alt="image" width="571" height="369" border="0" /></a></p>
<p>Este simples mapa de enquadramento usa 7 tabelas. A área visível usa um total de 618 registos (1+261+177+1+3+29+146). Se visualizarmos o país inteiro, a conta passa para 5841 registos. É muita informação para uma das operações mais básicas – pan e zoom.</p>
<p>Do ponto de vista da base de dados, o uso SIG é diferente:</p>
<ul>
<li>Um mapa é, tipicamente, composto por diversos temas (facilmente mais de 10);</li>
<li>Cada tema é uma tabela espacial diferente na base de dados, logo em cada visualização vamos ler uma série de tabelas;</li>
<li>Cada tema/tabela pode ser lido na totalidade (não paginado) se visualizarmos toda a área do tema;</li>
<li>Cada tema/tabela pode ter aplicada uma selecção (filtro) logo de início com base nos atributos (e.g. para vermos apenas uma categoria de rios ou estradas);</li>
<li>Cada tema/tabela pode ainda ter aplicado um filtro espacial se estivermos a visualizar apenas uma área específica (ou seja, são apenas pedidos os dados relativos ao rectângulo visível no mapa);</li>
<li>Mas, principalmente, os dados geográficos são muitos mais “pesados” ou “gordos”: têm uma coluna que contém todos os vértices da geometria! (Cada vértice tem 2 números do tipo <a title="double - documentação" href="http://www.postgresql.org/docs/devel/static/datatype-numeric.html" target="_blank" rel="noopener noreferrer">double</a>, o que equivale a 2 colunas em dados alfanuméricos.)</li>
<li>Para agravar a coisa, os utilizadores nunca escolhem os campos que precisam para trabalhar, e assim quando abrem a tabela de atributos todos os campos são lidos.</li>
</ul>
<h4>Usar o pgbench para simular utilizadores SIG</h4>
<p>Uma das capacidades do pgbench é que permite testar queries à base de dados feitas por nós, em vez de usar as pré-definidas. Basta criar um ficheiro sql que contém as nossas queries e passá-lo ao pgbench com o parâmetro –f.<span id="more-893"></span></p>
<p>É esta capacidade que usamos para simular queries espaciais e medir o desempenho em Transações por Minuto (TPS), tal com se faz para uma base de dados não espacial.</p>
<p>Assim, configuramos o PostgreSQL para que guarde no log todas as queries que recebe. Depois usamos o QGIS com um mapa típico que utilizamos frequentemente, e fazemos zoom a diversos locais e com diferentes escalas. A partir dos logs do PostgreSQL obtemos as queries SQL de cada zoom, e criamos um ficheiro .sql para cada zoom.</p>
<p>Em resumo, no nosso exemplo, obtivemos 10 ficheiros zoomN.sql que correspondem a 10 visualizações no QGIS do mesmo mapa, a escalas diferentes: zoom1.sql, zoom2.sql, … até zoom10.sql. Ou seja, um ficheiro .sql equivale a 1 mapa:</p>
<p>zoom1 – 1:1M                                                        zoom2 – 1:288.000</p>
<p><a href="/wp-content/uploads/2015/03/image1.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="/wp-content/uploads/2015/03/image_thumb1.png" alt="image" width="244" height="190" border="0" /></a><a href="/wp-content/uploads/2015/03/image2.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="/wp-content/uploads/2015/03/image_thumb2.png" alt="image" width="244" height="190" border="0" /></a></p>
<p>zoom3 – 1:72.000                                                        zoom4 – 1:18.000</p>
<p><a href="/wp-content/uploads/2015/03/image3.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="/wp-content/uploads/2015/03/image_thumb3.png" alt="image" width="244" height="190" border="0" /></a><a href="/wp-content/uploads/2015/03/image4.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="/wp-content/uploads/2015/03/image_thumb4.png" alt="image" width="244" height="189" border="0" /></a></p>
<p>Cada visualização criou um ficheiro .sql que podemos usar no pgbench, e simular vários utilizadores simultâneos de QGIS. Aqui,há uma simplificação: cada zoom é feito instantaneamente a seguir ao outro. Ou seja, vamos simular super-utilizadores! <img decoding="async" class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/wp-content/uploads/2015/03/wlEmoticon-winkingsmile.png" alt="Piscar de olho" /> que não fazem pausas entre zooms e pans.</p>
<p>O comando para simular 12 super-utilizadores que fazem 10 zooms/pans é o seguinte:</p>
<p>pgbench -f zoom1.sql -f zoom2.sql -f zoom3.sql -f zoom4.sql -f zoom5.sql -f zoom6.sql -f zoom7.sql -f zoom8.sql zoom9.sql zoom10.sql  -h &lt;servidor&gt; –U &lt;user&gt; -n -l -c 12 -j 2 -T 180 postgis</p>
<p><a href="/wp-content/uploads/2015/03/image5.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="/wp-content/uploads/2015/03/image_thumb5.png" alt="image" width="644" height="227" border="0" /></a></p>
<p>Tal como no <a title="Medir desempenho do PostgreSQL" href="/2014/08/medir-o-desempenho-do-postgresql/" target="_blank" rel="noopener noreferrer">artigo anterior</a> sobre pgbench, o significado dos parâmetros é:</p>
<ul>
<li>-n = não fazer vacuum aos dados, porque estamos a usar a bd de produção;</li>
<li>-l = log de tempos para um ficheiro;</li>
<li>-c 12 = simular 12 conexões simultâneas, ou seja, 12 utilizadores de SIG;</li>
<li>-j 2 = simular 2 threads por conexão (pouco impacto tem);</li>
<li>-T 180 = simular durante 180 segundos (3min);</li>
</ul>
<p>Os resultados são:<br />
<code><br />
transaction type: Custom query<br />
scaling factor: 1<br />
query mode: simple<br />
number of clients: 12<br />
number of threads: 2<br />
duration: 180 s<br />
number of transactions actually processed: 4004<br />
tps = 22.148347 (including connections establishing)<br />
tps = 22.188888 (excluding connections establishing)<br />
</code></p>
<p>O que quer isto dizer?</p>
<p>O que interessa é o valor final de 22.18 tps. Isto significa que o nosso PostGIS consegue responder a um ritmo de 22,18 mapas por segundo, em média. Ou seja, deviamos dizer 22,18 MPS (maps per second) <img decoding="async" class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/wp-content/uploads/2015/03/wlEmoticon-winkingsmile.png" alt="Piscar de olho" /></p>
<p>Este valor é a média para todas as escalas que utilizámos no teste. Podemos testar cada escala em separado, e obter desempenhos por escala. Num outro teste usando dados do OpenStreetMap, fizemos este gráfico:</p>
<p><a href="/wp-content/uploads/2015/03/image6.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="/wp-content/uploads/2015/03/image_thumb6.png" alt="image" width="644" height="431" border="0" /></a></p>
<p>Obviamente, quanto maior a escala, maior o detalhe, e, geralmente, menos dados. Logo, à escala 1:1M temos um poder de processamento de 1,51 MPS, e à escala :1:5600 temos 112,92 MPS.</p>
<p>O que interessa nisto tudo é que podemos comparar agora entre servidores diferentes de PostGIS, e entre configurações diferentes num servidor, para determinarmos a melhor configuração.</p>
<p>Notem que este teste elimina o factor QGIS, ou seja, não se considera o desempenho do QGIS a desenhar o mapa. Uma vez que convertemos cada vizualização num ficheiro .sql, ao executar o teste só usamos o ficheiro .sql. Assim, o desempenho do QGIS não entra na equação, o que é necessário se queremos medir o desempenho do servidor PostGIS.</p>
<h4>Outras questões de desempenho</h4>
<p>Ao testar o desempenho do PostGIS, acabamos por nos apercebermos de alguns factores que influenciam e muito os resultados e o desempenho observado de um servidor PostGIS.</p>
<p>Por exemplo, se durante o teste verificarmos o que se passa no servidor, podemos ter algumas surpresas:</p>
<p><a href="/wp-content/uploads/2015/03/beja084_2.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="beja084_2" src="/wp-content/uploads/2015/03/beja084_2_thumb.png" alt="beja084_2" width="531" height="484" border="0" /></a></p>
<p>(Sim, eu sei… é windows…)</p>
<p>O CPU esteve a 91%, para conseguir responder aos nossos 12 QGIS simulados. É perigoso andar tão perto dos 100%, porque o desempenho começa a diminuir. Aqui temos de jogar com o n.º de conexões. Neste caso, baixar de 12 para 10 conexões simultâneas até poderia dar resultados melhores. Cada servidor terá o seu n.º de conexões para o qual se obtém o máximo de tps. Temos de experimentar vários valores e ver o melhor.</p>
<p>Os valores de memória apresentados no Task Manager são inúteis, porque a memória ocupada está sempre perto dos 100%. Teríamos de fazer outro tipo de análise.</p>
<p>Já a ocupação de rede é interessante: é enorme! 769 Mbps! É muito fácil limitar o desempenho do PostGIS por causa de uma má ligação de rede entre o PostGIS e os utilizadores. Se compararmos com o teste de queries “normais” não espaciais, vemos que a ocupação de rede é apenas de 22 Mbps (para o total das 12 conexões simultâneas).</p>
<p><a href="/wp-content/uploads/2015/03/image7.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="image" src="/wp-content/uploads/2015/03/image_thumb7.png" alt="image" width="535" height="484" border="0" /></a></p>
<p>Outra questão importante para os resultados dos testes é observar o estado do PC onde corremos o pgbench, principalmente quanto à ocupação do CPU: como o pgbench corre num só processo ocupa só 1 core, e podemos facilmente limitar os resultados porque o nosso CPU não consegue responder. Temos de verificar durante os testes se o processo <em>pgbench.exe</em> ocupa MENOS que 1 core. No meu caso, usei um i5, que tem 4 cores. Logo, o pgbench tinha de ocupar menos de 25% de cpu para que os resultados fossem bem medidos.</p>
<h4>Conclusão</h4>
<p>Usar o pgbench com dados espaciais dá-nos uma excelente forma de testar o desempenho do PostGIS. Podemos perceber qual o melhor servidor, se físico, se virtual, para o nosso caso particular. Podemos ainda testar configurações alternativas do PostgreSQL e identificar aquela que dá melhores resultados.</p>
<p>Melhor ainda, será criar um pacote de dados OSM e os scripts .sql correspondentes, e usá-los para termos um teste padrão de PostGIS. Se todos usarmos estes dados vamos conseguir partilhar resultados entre toda a comunidade. Hmmm, temos de pensar nisto…</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.viasig.com/2015/03/medir-o-desempenho-do-postgis/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>MapServer em Windows e IIS</title>
		<link>https://blog.viasig.com/2015/02/mapserver-em-windows-e-iis/</link>
					<comments>https://blog.viasig.com/2015/02/mapserver-em-windows-e-iis/#respond</comments>
		
		<dc:creator><![CDATA[duarte]]></dc:creator>
		<pubDate>Mon, 23 Feb 2015 12:08:39 +0000</pubDate>
				<category><![CDATA[Intermédio]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[WebGIS]]></category>
		<category><![CDATA[MapServer]]></category>
		<guid isPermaLink="false">http://blogteste.viasig.com/?p=870</guid>

					<description><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 4</span> <span class="rt-label rt-postfix">min</span></span>O MapServer é geralmente instalado com Apache, mesmo em Windows. Para este caso, basta um dos vários instaladores existentes, por exemplo, o OSGeo4W. Mas, no meu caso e imagino muitos outros, como uso mais servidores Windows, precisei de instalar o MapServer de forma a que funcione com IIS. Para além disto, preciso também que o &#8230; <a href="https://blog.viasig.com/2015/02/mapserver-em-windows-e-iis/" class="more-link">Continuar a ler<span class="screen-reader-text">MapServer em Windows e IIS</span> <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[<p><span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Tempo de leitura: </span> <span class="rt-time"> 4</span> <span class="rt-label rt-postfix">min</span></span>O MapServer é geralmente instalado com Apache, mesmo em Windows. Para este caso, basta um dos vários instaladores existentes, por exemplo, o OSGeo4W.</p>
<p>Mas, no meu caso e imagino muitos outros, como uso mais servidores Windows, precisei de instalar o MapServer de forma a que funcione com IIS. Para além disto, preciso também que o endereço web dos meus mapas não mostre sempre o ficheiro de configuração usado. É feio, e é um risco de segurança. Ninguém devia saber a estrutura das directorias no disco rígido do servidor.</p>
<h4>MapServer como aplicação FastCGI &#8211; As melhores instruções</h4>
<p>A parte inicial de configurar o IIS de forma a executar o MapServer é mais ou menos fácil de encontrar na net. Esta parte consiste em configurar o IIS de forma a considerar o executável mapserv.exe como sendo uma aplicação FastCGI. Isto é mais ou menos padrão nos IIS &gt;7.0 (win7/win8/win2008/win2012). Este link explica bem como fazer isto, usando os ficheiros do MS4W:</p>
<p><a title="https://github.com/mapserver/mapserver/wiki/Installing-Mapserver-under-IIS-7.n-with-FastCGI" href="https://github.com/mapserver/mapserver/wiki/Installing-Mapserver-under-IIS-7.n-with-FastCGI">https://github.com/mapserver/mapserver/wiki/Installing-Mapserver-under-IIS-7.n-with-FastCGI</a></p>
<p>Mas melhor ainda é uma instalação automática – sim existe! Preparada pelo nosso grande Tamas Szekeres:</p>
<p><a title="http://www.gisinternals.com/query.html?content=filelist&amp;file=release-1600-gdal-1-11-1-mapserver-6-4-1.zip" href="http://www.gisinternals.com/query.html?content=filelist&amp;file=release-1600-gdal-1-11-1-mapserver-6-4-1.zip">http://www.gisinternals.com/query.html?content=filelist&amp;file=release-1600-gdal-1-11-1-mapserver-6-4-1.zip</a></p>
<p>Nesta página escolham o ficheiro <a href="http://download.gisinternals.com/sdk/downloads/release-1600-gdal-1-11-1-mapserver-6-4-1/mapserver-6.4.1-1600-core.msi">mapserver-6.4.1-1600-core.msi</a>.</p>
<h4>A minha instalação</h4>
<p>Eu preferi fazer uma instalação manual, usando ficheiro zip do Tamas Szekeres contendo todo o software, em vez do .msi. Isto dá-me mais flexibilidade para encontrar a configuração que mais se ajusta às minhas necessidades.</p>
<p><span id="more-870"></span></p>
<p>Criei uma directoria wwwroot\MapServer, e descomprimi aqui o ficheiro zip. Este ficheiro contém apenas 2 directorias: bin e doc.</p>
<p>E, para facilitar a organização dos ficheiros map e daquilo que serão os serviços web, acrescentei mais 3 directorias: mapfiles, servicos, e tmp.</p>
<p>O aspecto final é este:</p>
<p><a href="/wp-content/uploads/2015/02/image.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="/wp-content/uploads/2015/02/image_thumb.png" alt="image" width="644" height="352" border="0" /></a></p>
<p>Ou seja, tudo o que pertence ao MapServer propriamente dito fica dentro da pasta &#8220;binarios&#8221;. Agora falta configurar o IIS para executar o mapserv.exe como aplicação FastCGI. A receita é curta e é feita na consola de gestão do IIS&#8230;</p>
<h6>1) Dar permissões de escrita à pasta tmp.</h6>
<p>Este passo é apenas necessário para permitir que o MapServer consiga criar ficheiros, o que apenas sucede em alguns cenários. Em princípio, se servirmos apenas WMS, WFS, não será necessário. Mas pelo sim, pelo não, mais vale configurar…</p>
<h6>2) Permitir a execução de scripts na pasta MapServer.</h6>
<p>Na pasta MapServer, abrir a funcionalidade “Handler Mappings” :</p>
<p><a href="/wp-content/uploads/2015/02/image1.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="/wp-content/uploads/2015/02/image_thumb1.png" alt="image" width="531" height="376" border="0" /></a></p>
<p>e abrir a acção “Edit Feature Permissions”. Nesta janela dar permissões de “Read”, “Script”:</p>
<p><a href="/wp-content/uploads/2015/02/image2.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="/wp-content/uploads/2015/02/image_thumb2.png" alt="image" width="753" height="414" border="0" /></a></p>
<h6>3) Definir um documento <em>default</em> a apontar para o executável.</h6>
<p>Mais tarde pode ser removido, mas para testar é muito útil. Nas definições básicas da pasta MapServer, escolher a funcionalidade “Default Document”, e escrever o caminho para o executável mapserv.exe (cuidado com as barras /):</p>
<p><a href="/wp-content/uploads/2015/02/image3.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="/wp-content/uploads/2015/02/image_thumb3.png" alt="image" width="702" height="370" border="0" /></a></p>
<h6>4) Criar a aplicação FastCGIS para o MapServer.</h6>
<p>Esta configuração é feita no nó principal do nosso site. Por isso, selecionamos o nó “Default web site” ou o nome que demos ao nosso site, a abrimos a funcionalidade &#8220;Handler Mappings&#8221;:</p>
<p><a href="/wp-content/uploads/2015/02/image4.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="/wp-content/uploads/2015/02/image_thumb4.png" alt="image" width="806" height="433" border="0" /></a></p>
<p>Aqui, clicamos na acção “Add Module Mapping” e definimos estas propriedades:</p>
<p><a href="/wp-content/uploads/2015/02/image5.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="/wp-content/uploads/2015/02/image_thumb5.png" alt="image" width="764" height="445" border="0" /></a></p>
<p>Ou seja, definimos que o executável mapserv.exe deve ser executado como uma aplicação FastCGI. Temos ainda de clicar no botão “Request Restrictions” e definir os “verbos” permitidos e o acesso necessário à aplicação:</p>
<p><a href="/wp-content/uploads/2015/02/image6.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="/wp-content/uploads/2015/02/image_thumb6.png" alt="image" width="269" height="228" border="0" /></a><a href="/wp-content/uploads/2015/02/image7.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="/wp-content/uploads/2015/02/image_thumb7.png" alt="image" width="269" height="229" border="0" /></a></p>
<h6>5) Último passo! Temos de definir as variáveis de ambiente que o MapServer necessita.</h6>
<p>Estas variáveis estão todas escritas no ficheiro SDKShell.bat que está na pasta do MapServer. Estas variáveis têm de ser definidas ao nível da aplicação FastCGI, e o único sítio onde se pode fazer é ao nível do servidor IIS e não ao nível do site. Por isso, é preciso selecionar o nó raíz do IIS, e selecionar a opção “FastCGI Settings”:</p>
<p><a href="/wp-content/uploads/2015/02/image8.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="/wp-content/uploads/2015/02/image_thumb8.png" alt="image" width="663" height="446" border="0" /></a></p>
<p>Nesta janela, vemos a nossa aplicação FastCGI já criada. Podemos editar a nossa aplicação, e na janela de configuração clicamos na opção “Environment Variables”. Aqui temos de criar 4 variáveis:</p>
<p><a href="/wp-content/uploads/2015/02/image9.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="/wp-content/uploads/2015/02/image_thumb9.png" alt="image" width="904" height="590" border="0" /></a></p>
<p>As 4 variáveis de ambiente são:</p>
<ul>
<li>PATH = C:\Inetpub\wwwroot\MapServer\binarios;C:\Inetpub\wwwroot\MapServer\binarios\gdal\python\osgeo;C:\Inetpub\wwwroot\MapServer\binarios\proj\apps;C:\Inetpub\wwwroot\MapServer\binarios\gdal\apps;C:\Inetpub\wwwroot\MapServer\binarios\ms\apps;C:\Inetpub\wwwroot\MapServer\binarios\gdal\csharp;C:\Inetpub\wwwroot\MapServer\binarios\ms\csharp;C:\Inetpub\wwwroot\MapServer\binarios\curl;%PATH%</li>
<li>GDAL_DATA = C:\Inetpub\wwwroot\MapServer\binarios\gdal-data</li>
<li>GDAL_DRIVER_PATH = C:\Inetpub\wwwroot\MapServer\binarios\gdal\plugins</li>
<li>PROJ_LIB = C:/Inetpub/wwwroot/MapServer/binarios/proj/share</li>
</ul>
<p>E é tudo.</p>
<p>Depois desta configuração, os pedidos ao MapServer já devem funcionar:</p>
<p><a href="http://localhost/MapServer">http://localhost/MapServer</a></p>
<p><a href="/wp-content/uploads/2015/02/image10.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="/wp-content/uploads/2015/02/image_thumb10.png" alt="image" width="634" height="421" border="0" /></a></p>
<p>Parabéns – o MapServer está a funcionar. A partir daqui o uso é o normal. Podemos indicar o mapa que queremos usando o parâmetro mode=map&amp;map=ficheiro. Por exemplo:</p>
<p><a href="/wp-content/uploads/2015/02/image11.png"><img loading="lazy" decoding="async" style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;" title="image" src="/wp-content/uploads/2015/02/image_thumb11.png" alt="image" width="635" height="425" border="0" /></a></p>
<p>Agora, a questão é conseguir ter endereços simpáticos, que não mostrem o nome e caminho do ficheiro de configuração… o que queremos são endereços do tipo:</p>
<ul>
<li><a href="http://localhost/MapServer/servicos/PDM">http://localhost/MapServer/servicos/PDM</a></li>
<li><a href="http://localhost/MapServer/servicos/PlantasLocalizacao">http://localhost/MapServer/servicos/PlantasLocalizacao</a></li>
</ul>
<p>Mas é opcional… já podemos publicar todos os ficheiros map que quisermos. Fica a promessa de outro artigo com esta configuração para breve.</p>
<p>Ah, e já agora – este processo pode-se usar para instalar o QGIS Server. É exactamente a mesma coisa.</p>
<p>Bons web services!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.viasig.com/2015/02/mapserver-em-windows-e-iis/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
