Category Archives: Avançado

PostgreSQL – mover tablespaces

É 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…

Como funcionam os tablespaces no postgres?

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.).
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.

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

Localização em disco do tablespace pg_default

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 “lado”, por exemplo DATA\meu_tablespace.

pg_tblspc – não mexer, não imitar. A pasta DATA é off-limits!

Lição – a directoria DATA não é para o user mexer! É de sistema, é gerida pelo postgres, está off-limits!
Pois mas eu não sabia… e vai daí, criei uma série de tablespaces aqui mesmo:

CREATE TABLESPACE meu_tablspc LOCATION 'C:\Program Files\PostgreSQL\9.3\data\meusdadosgeo';

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.
Anos mais tarde, ao fazer upgrades com pg_upgrade comecei a ter os problemas respectivos…

Como funcionam os tablespaces e a directoria pg_tblspc?

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

dir "D:\Program Files\PostgreSQL\9.3\data\pg_tblspc"
Directory of D:\Program Files\PostgreSQL\9.3\data\pg_tblspc
22/01/2019 13:23 .
22/01/2019 13:23 ..
22/01/2019 13:23 12493007 [D:\Program Files\PostgreSQL\tables
paces_digc\sisma_tblspc]
22/01/2019 13:23 18357 [D:\Program Files\PostgreSQL\tablespac
es_digc\always_tblspc]

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

Ao criarmos os tablespaces dentro da pasta DATA estão a ver a confusão, 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… resultando em erro de upgrade.

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. (better paranoid than dead)

Como corrigir?

Os tablespaces, dizem os docs, devem ser criados numa pasta cujo dono é a conta do sistema operativo que controla o serviço do postgres. No meu caso é “Network Service”.
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:

C:\Program Files\PostgreSQL\9.3
C:\Program Files\PostgreSQL\9.5

Assim, a minha pasta será criada desta forma:
C:\Program Files\PostgreSQL\meus_tablespaces

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

C:\Program Files\PostgreSQL\9.3
C:\Program Files\PostgreSQL\9.5
C:\Program Files\PostgreSQL\tablespaces_adicionais

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

Receita

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…)

1) parar o serviço do postgres

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

 dir "D:\Program Files\PostgreSQL\9.3\data\pg_tblspc"
12493007 [D:\Program Files\PostgreSQL\9.3\data\sisma_tblspc]
18357 [D:\Program Files\PostgreSQL\9.3\data\always_tblspc]

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

move "D:\Program Files\PostgreSQL\9.3\data\sisma_tblspc"   "D:\Program Files\PostgreSQL\tablespaces_adicionais"
move "D:\Program Files\PostgreSQL\9.3\data\always_tblspc" "D:\Program Files\PostgreSQL\tablespaces_adicionais"

4) vamos apagar os junctions todos na pasta DATA\pg_tablspc

rd D:\Program Files\PostgreSQL\9.3\data\pg_tblspc\12493007
rd D:\Program Files\PostgreSQL\9.3\data\pg_tblspc\18357

5) vamos recriar os junctions apontando-os para as dir correctas

mklink /J "D:\Program Files\PostgreSQL\9.3\data\pg_tblspc\12493007" "D:\Program Files\PostgreSQL\tablespaces_adicionais\sisma_tblspc"
mklink /J "D:\Program Files\PostgreSQL\9.3\data\pg_tblspc\18357" "D:\Program Files\PostgreSQL\tablespaces_adicionaisc\always_tblspc"

6) iniciamos o serviço do postgres

E testamos, com diversas queries, e verificamos se no log surgem erros. Mas em principio se a bd iniciou não haverá problemas.
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.

A partir daqui, podemos ver que a estrutura dos tablespaces em disco ficou:

dir "D:\Program Files\PostgreSQL\tablespaces_adicionais"
Volume in drive D is Data
Volume Serial Number is 9CB2-EBBD
Directory of D:\Program Files\PostgreSQL\tablespaces_adicionais
22/01/2019 13:18 .
22/01/2019 13:18 ..
25/01/2019 18:58 always_tblspc
25/01/2019 18:58 sisma_tblspc

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

dir "D:\Program Files\PostgreSQL\tablespaces_adicionais\sisma_tblspc"
Volume in drive D is Data
Volume Serial Number is 9CB2-EBBD
Directory of D:\Program Files\PostgreSQL\tablespaces_adicionais\sisma_tblspc
25/01/2019 18:58 .
25/01/2019 18:58 ..
24/01/2019 18:59 PG_9.3_201306121

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.

E isso fica para um próximo post… Até breve.

PostgreSQL – autovacuum found orphan temp table

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 tamanho dos logs.

Para resolver, basta apagar os schemas tablespaces problemáticos:

DROP SCHEMA pg_temp_56;

Estes schemas tablespaces “especiais” podem ser listados assim:

select relname,nspname from pg_class join pg_namespace on (relnamespace=
pg_namespace.oid) where pg_is_other_temp_schema(relnamespace);

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

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 – 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.

Comigo funcionou…

Evitar conexões…

É conveniente apagar estes schemas tablespaces tendo a certeza de que não há conexões à bd… Para isso, basta editar o ficheiro pg_hba.conf de forma a permitir apenas conexões do localhost.

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:

#IPv4 local connections:
host all all 127.0.0.1/32 md5
#IPv6 local connections:
host all all ::1/128 md5
#INTRANET - comentado temporariamente
#host all all 192.168.0.0/16 md5
#host all all 10.10.0.0/16 md5

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…

Depois de apagar os schemas tablespaces, 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 tablespaces em erro.

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…

[1] – https://www.postgresql.org/message-id/flat/51C9975D.1040508%40uib.cat
[2] – https://www.postgresql.org/message-id/flat/48F4599D.7010601%40enterprisedb.com

LXD o virtualizador ubuntu

Este post é sobre o LXD, uma forma de criar “máquinas virtuais” 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 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 chroot + cgroups). Basicamente, usam capacidades do kernel linux para isolar componentes (é por isso que só podemos “virtualizar” 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 containers. Mas para simplicidade, no resto do texto quando falo de containers ou VM’s é tudo o mesmo… containers.

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.

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.

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: https://stgraber.org/2016/03/26/lxd-2-0-resource-control-412/.

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.

Podemos instalar o Ubuntu directamente na máquina física, e criar VM’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’s. Não posso confirmar nem desmentir porque não testei nada disto. Mas parece-me algo lógico.

Só mais um detalhe – o LXD suporta nested virtualization, ou seja, dentro de uma VM Ubuntu podemos usá-lo para criar VM’s, que estão dentro da nossa VM inicial… confuso? Cuidado, que o OpenVZ não suporta lxd… portanto ao comprarem uma VPS assegurem-se que é baseada em KVM.

Nested Virtualization… whaaat?

Instalar o LXD

Instalar o LXD é muito simples – já vem incluído no Ubuntu.

É preciso no entanto iniciá-lo uma primeira vez e definir a sua configuração, que principalmente define o tipo storage usado pelas máquinas a criar (baseadas em directorias ou pools zfs), e a configuração da rede que dirá se as VM’s são acessíveis do exterior, e se poderão comunicar entre si.

O tutorial que usei como base foi este da Digital Ocean: https://www.digitalocean.com/community/tutorials/how-to-set-up-and-use-lxd-on-ubuntu-16-04.

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 – o objectivo é ter simplicidade máxima e o menor número de pontos de falha. Mais info aqui: https://insights.ubuntu.com/2016/02/16/zfs-is-the-fs-for-containers-in-ubuntu-16-04/.

Então, a sessão de configuração do lxd foi assim (o meu user é dncpax e as respostas estão a negrito):

$ sudo usermod --append --groups lxd dncpax
$ sudo lxd init
Do you want to configure a new storage pool (yes/no) [default=yes]? y
Name of the storage backend to use (dir or zfs) [default=dir]: dir
Would you like LXD to be available over the network (yes/no) [default=no]? no
Do you want to configure the LXD bridge (yes/no) [default=yes]? yes

Como se vê escolhi sempre os defaults.

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.

Desta forma, as VM’s poderão contactar a máquina “mãe” e outras VM’s, e também a Internet. Mas não receberão tráfego exterior, ou seja, ninguém conseguirá aceder às nossas VM’s.

(Para permitir o acesso do “exterior” às nossas VM’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.)

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:

wizard do lxd para configurar a rede
wizard do lxd para configurar a rede IPv6

A minha rede foi configurada como 10.70.99.X, e assim todas as VM’s terão um IP deste tipo.

Utilizar LXD

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.)

Por exemplo, ver as VM’s criadas (não há ainda) – lxc list:

$ lxc list
+------+--------+------+------+------+-----------+
| NOME | ESTADO | IPV4 | IPV6 | TIPO | SNAPSHOTS |
+------+--------+------+------+------+-----------

Nota: se tiverem um erro de permissão negada, é porque o vosso novo grupo lxd não está ainda “activo”. Podem fechar a sessão e abrir uma nova com o mesmo login e continuar o trabalho, ou executarem “newgrp lxd”.

Ver a configuração do lxd – lxc info:

$ 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: ""

Então o que temos por agora? Um deamon lxd que coordenará a existência e o isolamento das VM’s a criar. Podemos ver o seu estado actual com systemctl (notem a memória ocupada):

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.

Criar e gerir VM’s

Trabalhar com VM’s ou containers LXD é muito fácil, e basicamente limita-se a estes passos:

  1. Criar o container com o OS escolhido
  2. Aceder ao container na nossa shell ou por ssh
  3. Configurar alguns limites se quisermos (de memória p.e.)
  4. Parar ou reiniciar um container
  5. Ver os detalhes de um container, incluindo memória ocupada

A melhor página que conheço sobre gestão de containers LXD é esta: https://insights.ubuntu.com/2016/03/22/lxd-2-0-your-first-lxd-container/

Então para criar uma VM de Ubuntu dentro do nosso Ubuntu 😉 usamos o comando lxc launch. O sistema operativo que queremos usar pode ser escolhido de uma lista já extensa que pode ser consultada aqui: https://us.images.linuxcontainers.org/.

Antes de instalar uma máquina novinha vamos antes ver como temos a memória:

$ free -m
              total        used        free      shared  buff/cache   available
Mem:           2000          47        1501           3         451        1795

Como se vê, estamos só com 47MB usados e 451MB em cache.

Para instalar a nova vm chamada “wordpress1” (como é a 1ª vez, a imagem é descarregada do repositório online):

$ lxc launch ubuntu:16.04 wordpress1
A criar wordpress1
A iniciar wordpress1

E pronto. Temos um novo ubuntu fresquinho. Podemos ver na lista de containers com lxc list:

$ lxc list
+------------+---------+---------------------+------+-------------+-----------+
|    NOME    | ESTADO  |        IPV4         | IPV6 |    TIPO     | SNAPSHOTS |
+------------+---------+---------------------+------+-------------+-----------+
| wordpress1 | RUNNING | 10.70.99.165 (eth0) |      | PERSISTENTE | 0         |
+------------+---------+---------------------+------+-------------+-----------+

Podemos ver a lista dos containers, se estão iniciados, e os endereços IP internos.

Para vermos a configuração de um container, incluíndo a memória usada:

$ 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

Até agora a memória ocupada variou entre 31 e 157 MB…

Para aceder podemos usar ssh ou um comando do lxc (exec):

$ lxc exec wordpress1 -- sudo --login --user ubuntu
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

ubuntu@wordpress1:~

Estamos agora “dentro” da nova máquina wordpress1, com o login ubuntu… podemos ver os seus processos de forma isolada, sem acesso à máquina mãe:

$ 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

A partir daqui podemos instalar o que quisermos da forma habitual. Podemos aceder ao exterior, mas não o inverso – do exterior aceder ao nosso container. E isso será para resolver noutro post.

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.

$ 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

Portanto, dentro do container temos um total de 3723 MIPS de compressão. Vamos sair do container e fazer o mesmo exercício:

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

Temos então na máquina LXD 3780 MIPS de compressão.

Ou seja, 3723/3780 = 98% de desempenho no container! Sim, é um teste simplista, e não representa uma avaliação real, mas é óptimo indicador.

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.

Mosaicos com áreas transparentes

Neste artigo regresso a um assunto já familiar neste blog – criar mosaicos de ortofotomapas usando o GDAL – (sim eu sei, outra vez?) mas como tenho andado às voltas com as áreas sem informação, que surgem negras nos mosaicos pensei em postar o que acabei por fazer. A solução final é usar máscaras, e não bandas alfa como habitual. Vamos ver como e porquê… assume-se já alguma familiaridade com o GDAL, mas pode sempre saltar as partes teóricas aborrecidas e ver os comandos usados no final do artigo 😉 Ler artigo completo

PostgreSQL e ESRI – parte 4

O subtítulo deste artigo devia ser “O bom, o mau e o péssimo”…

Depois de ter respondido a um comentário que me perguntava sobre a nossa experiência em curso de migrar para PostgreSQL, pensei em melhorar a resposta e fazer um artigo – a maior parte da escrita já estava feita de qualquer forma 😉

Responder ao comentário levou-me a pensar mais um pouco sobre a questão… e uma parte que me parecia pouco clara é o porquê de fazermos a migração para PostgreSQL (pgsql prós amigos) e porquê insistir em usar geometrias PostGIS (geometrias pg)? Só para recordar: a ESRI permite 2 formatos de armazenamento das geometrias nas bases de dados que suporta – ou no formato ESRI (que chamou de ST_Geometry) ou no formato “nativo” da bd.
Ler artigo completo

Desenvolver aplicações SIG de forma Agile!

Estou a digerir tudo o que vi na formação de 3 dias sobre metodologias Agile e Scrum e este post servirá como bloco de notas.

Esta semana estive 3 dias em formação com o excelente formador Mitch Lacey. Este sr. tem já uma grande experiência em projectos de desenvolvimento de software, e ouvi-lo foi realmente uma experiência enriquecedora.

Não vou entrar em grandes detalhes teóricos sobre Agile/Scrum, porque não sou definitavemente a pessoa indicada para o fazer. Vou em vez disso enumerar os pontos que mais me impressionaram e que mais valor terão se os integrar na forma como a “minha” equipa funciona. Portanto, as afirmações seguintes devem ser encaradas como uma perspectiva muito pessoal…

Agile é um conjunto de práticas que visam desenvolver um projecto de forma iteractiva, com ciclos curtos entre versões intermédias antes de chegar à entrega final, com vista a reduzir os riscos associados a este tipo de projectos – sendo o maior entregar um produto que não se ajusta à visão do cliente!

Scrum é a metodologia Agile mais difundida, e obteve o seu nome do Rugby: scrum é a altura em que os jogadores se reunem para reiniciar o jogo, e ambas as equipas disputam a bola. Em Agile, Scrum é um método em que uma equipa de desenvolvimento se concentra ferozmente em terminar um conjunto de tarefas num prazo curto – tipicamente 14 ou 28 dias – e se compromete a no final do prazo produzir uma versão funcional do produto que está a desenvolver.

Qual é a grande diferença em relação ao processo tradicional (designado “Waterfall” ou “em Cascata“)? É que no processo Waterfall, os requisitos para a aplicação a desenvolver são definidos à partida, na fase de levantamento e definição dos mesmos. Em seguida, esta lista de especificações é trabalhada com o cliente final, e atinge-se um acordo, sendo fechada a lista de itens a implementar. E é aqui que este método tem a sua maior fraqueza: é pouco flexível, e não considera facilmente requisitos que se alteram com o tempo (alguém se identifica com esta experiência??). A analogia de construir uma casa é muito clarificadora: ao olhar para a planta da minha futura casa, posso ficar muito satisfeito com o que está planeado. Mas, mais tarde, ao andar pela estrutura já construída da casa, vou conseguir obter uma visão mais clara do que estava na planta, e consequentemente vou definir melhoramentos e até novas funções que quero ter na versão final da casa. Isto é um processo natural e não deve ser combatido. E é o que os métodos Agile nos oferecem: ao cliente final permite algum controlo durante a vida do projecto, e à equipa de desenvolvimento permite um grande poder de adaptação à mudança, permitindo concluir o projecto dentro do prazo e do orçamento, mesmo absorvendo alterações aos pressupostos iniciais. E para descansar os espíritos mais desconfiados, resta acrescentar que esta metodologia é reconhecida pelo PMI, e é usada pelas maiores empresas de software como Microsoft ou IBM.

Porque é que estas técnicas me interessaram? Os pontos mais importantes:

  • A equipa de desenvolvimento com que trabalho é pequena – podemos contar com 2,5 técnicos (sim, temos realmente uma metade de técnico!), e somos facilmente dispersados por várias solicitações em simultâneo
  • O meio onde nos inserimos é muito dinâmico – as alterações aos requisitos são muito frequentes, e a sua definição inicial é muito difícil de obter e estabilizar
  • Trabalhamos para o “Cliente Interno”, onde as relações informais dominam, e os processos formais inerentes ao método Waterfall dificilmente são aplicados e respeitados

Da abordagem Scrum, estes são os pontos que mais me agradam e que vejo possibilidade de implementar rapidamente:

  1. Definir o “Product Backlog”, que mais não é que uma lista de funções a implementar numa aplicação, ordenada por prioridade
  2. Definir o “Sprint Backlog”, que é a lista prioritizada de funções que vamos implementar no próximo ciclo de 14 dias (o sprint)
  3. Reuniões relâmpago diárias, onde rapidamente (15 min.) cada um dos elementos da equipa percorre estes 3 pontos – o que concretizaste ontem, o que vais fazer hoje, e tens algum ponto crítico?
  4. Estar atento a solicitações de alterações ou novas funções, mas lutar por integrá-las no Product Backlog, que poderá ser re-prioritizado todas as semanas (mas as funções só podem entrar num sprint no seu início)
  5. Consciencializar todos os elementos da equipa de que todos são responsáveis pela equipa! Todos se devem preocupar com a saúde emocional da equipa e com a concretização dos compromissos assumidos com o exterior (notem aqui a grande diferença mental entre cumprir objectivos e cumprir compromissos)
  6. Obter uma versão funcional no final de cada Sprint! E demonstrá-la. Na teoria Scrum, a demo deve ser feita ao cliente. No meu caso, parece-me mais plausível realizar uma demo interna à equipa, para validar a direcção dada ao projecto, detectar incongruências, enfim, andar pela estrutura da casa e ver se é como imaginámos quando fizemos a planta…

É realmente uma forma de trabalhar muito aliciante, e que de alguma forma torna o desenvolvimento de projectos mais humano.

Algumas ferramentas consideradas essenciais a uma boa prática Agile já utilizamos na equipa:

  • Repositório de código e Controle de versões – usamos o SVN, e o AnkhSVN para integrar com o Visual Studio. Não há checkin de código que não compile. Este é um passo fundamental na organização da equipa!
  • Documentação – embora não tenhamos ainda a prática de documentação automática do código, embora já se tenha discutido o assunto várias vezes, usamos um Wiki para documentar quer a vertente técnica quer a vertente de utilização das aplicações

E das peças que nos faltam, o que podemos integrar no nosso caso particular?

  • Teste unitários – é algo que deveremos implementar, mas que está ainda algo longíquo de ser possível… é necessário primeiro re-organizar o código em componentes suficientemente pequenos, modulares, para possibilitar esta técnica. Mas os ganhos são óbvios – rapidez de efectuar testes e na detecção de bugs
  • Test Driven Development – ver ponto anterior, é algo desejável, mas cuja execução obriga a remodelar o repositório de código existente. Talvez a longo prazo seja possível…

Para mais informação recomendo vivamente a leitura deste artigo: “Agile Project Management for GIS“. Muitos mais podem ser encontrados “googlando” a Internet (como por exemplo este na revista PM Network, pp 42). E para aqueles que ficarem convencidos, fica a referência do curso – Fullsix.