MongoDB replicaset test drive

Segnalo un’interessante iniziativa realizzata dal team di MongoDB con il supporto di amazon:

Accedendo a  test drive è possibile accedere ad un’istallazione di test di mongodb su cui provare il sistema di replica e testarne l’ottimizzazione.

squid come reverse proxy

Squid è un prodotto eccellente per fare da web cache; sia che si voglia alleggerire il carico sulla connessione, sia che si voglia fare del filtraggio a livello applicativo sia che si abbia la necessità di fare del monitoraggio molto dettagliato dell’uso del web su di una rete, la flessibilità di questo applicativo permette di intervenire praticamente su ogni aspetto del protocollo http e non solo.

Segnalo fin da subito che squid, come tutti i prodotti di web cache, richiede un’ attenzione particolare alla configurazione, in particolare per l’aspetto dei permessi; si corre il rischio, infatti, di mettere su internet un server proxy che può essere usato da terzi per mascherare le proprie attività.

Oggi voglio mostrare come configurare squid per usarlo come reverse-proxy. Si parla di proxy quando la cache viene messa davanti ai client e risolve al posto di questi le chiamate su internet. Si parla di reverse-proxy quando il server viene posto davanti ai web server e raccoglie al posto dei server web le chiamate dei client.

La ragione base per cui si fa questo è migliorare le prestazioni incidendo il meno possibile sui costi. I server cache infatti mantengono in memoria e/o su disco le risposte alle richieste più frequenti dei client e rispondono direttamente senza convolgere i server web; infatti  sono in genere in grado si rispondere ad un numero di richieste molto più alto di un server web che sempre più spesso deve essere configurato per gestire elaborazioni pesanti.

Squid è un prodotto molto consolidato ed è presente oramai sui tutte le distribuzioni linux. Per istallarlo quindi in genere la cosa più semplice è ricorrere ai tool della propria distribuzione. Su Debian/Ubuntu:

sudo aptitude update
sudo aptitude search squid
sudo aptitude install squid

La configurazione di default di squid è molto ben fatta e contiene così tanti commenti da essere quasi completamente autoesplicativa; merita un’esame se si vuole utilizzare questo prodotto. Nel nostro caso però la costruiremo da zero. Come risulta dalla documentazione ufficiale ci sono più possibilità per la configurazione in modalità Reverse Proxy; ne analizzeremo una di uso ragionevolmente generale.

http_port 80 accel defaultsite=[server name] vhost

cache_peer [IP sorgente 1] parent 80 0 no-query originserver name=RevPro1
acl web1 dstdomain [accelerated domains list 1]

cache_peer [IP sorgente 2] parent 80 0 no-query originserver name=RevPro2
acl web2 dstdomain [accelerated domains list 2]

http_access allow web1
http_access allow web2
cache_peer_access RevPro1 allow web1
cache_peer_access RevPro2 allow web2

cache_dir diskd /var/cache/squid3 1000 32 32 Q1=64 Q2=72
cache_mem 1024 MB

cache_replacement_policy heap LFUDA
memory_replacement_policy heap GDSF
cache_swap_low  90
cache_swap_high 95

Vediamo ora questa configurazione in maggiore dettaglio:

http_port 80 accel defaultsite=[server name] vhost

In questo modo si dice a squid che lavorerà in modalità reverse-proxy e con che tipo di configurazione. Defaultsite conviene valorizarlo con il nome del server web, quali sono i siti di cui si fa reverse proxy viene specificato più avanti. Vhost specifica che la discriminante per la scelta del server di origine sarà il dominio.

cache_peer [IP sorgente 1] parent 80 0 no-query originserver name=RevPro1

Definiamo qui un server web di cui fare reverse proxy e assegniamo un nome a questa definizione (RevPro1).

acl web1 dstdomain [accelerated domains list 1]

Definiamo una lista di siti web (separati da spazi) di cui si vuole fare reverse proxy e le assegnamo un nome (web1).

cache_peer [IP sorgente 2] parent 80 0 no-query originserver name=RevPro2
acl web2 dstdomain [accelerated domains list 2]

Ripeto per un secondo server origin e una seconda lista di siti.

http_access allow web1
http_access allow web2

dico a squid che deve rispondere alle richieste (dei client) relative alle due liste di siti web1 e web2.

cache_peer_access RevPro1 allow web1
cache_peer_access RevPro2 allow web2

Associo le origin alle liste dei siti supponendo che un dato server web di origine serve alcuni dei siti mentre l’altro serve gli altri.

cache_dir diskd /var/cache/squid3 1000 32 32 Q1=64 Q2=72
cache_mem 1024 MB

cache_replacement_policy heap LFUDA
memory_replacement_policy heap GDSF
cache_swap_low  90
cache_swap_high 95

Infine queste righe configurano la cache.

Come quasi sempre su squid si definiscono degli oggetti per definire attività da permettere o vietare; si definiscono delle acl per definire il “chi” ed infine si associano questi due tipi di informazione in righe dove si definisce chi può fare cosa.

Come sempre prima di mettere in produzione un server con squid è bene leggerne la documentazione ufficiale.

gmail – cambiare il sender

La posta di gmail offre uno strumento poco noto ma molto utile. E’ possibile inviare posta con un sender differente dall’account con cui si è fatto login.

Questa feature di gmail può tornare utile in almeno due casi:

  1. se si hanno diverse caselle di posta sfruttando il cambio di sender e la possibilià di scaricare posta da altre caselle, per concentrare la gestione della propria posta in un unico punto.
  2. se si gestisce un dominio con centinaia di caselle su cui con ogni probabilità verranno richieste caselle non personali di cui è fin troppo facile perdere traccia, da la possibilità di limitare gli utenti alle caselle personali e usare i gruppi per tutte le caselle funzionali come le varie webmaster, postmaster etc.. Il vantaggio è doppio: igruppi non si pagano e  l’amministratore può ricostruire facilmente da chi vengono letti.

Per sfruttare questa feature bisogna:

  1. Fare login sulla webmail
  2. entrare nei settings del proprio account
  3. Selezionare il tab Accounts
  4. selezionare “Add another address you own”
  5. Sulla finestra di pop-up inserire il nome che si vuole mostrare accanto all’indirizzo nell’header From:”
  6. Sulla finestra di pop-up inserire l’email che si vuole nel campo From
  7. Sulla finestra di pop-up togliere il check “Treat as an alias box”
  8. Selezionare Next Step
  9. Si riceverà sull’altro account (o gruppo) un’email con un link di autorizzazione
  10. Confermare selezionando il link nell’email
  11. Tornare alla finestra di pop-up e concludere la procedura.

Da questo momento è possibile mandare la posta con unb altro Sender.

Howto – ambiente di test – mysql – replica master-master

Vediamo ora come implementare una replica master-master per MySQL.

Per prima cosa bisogna scaricare  il database MySQL. Per questo ambiente di test scarichiamo il pacchetto binario dal sito MySQL,

Ad esempio su di una distribuzione debian-like procederemo come al solito con

aptitude search mysql 
aptitude install mysql-server

Andiamo ora a creare due istanze del db.

Creiamo come root le datadir

mkdir /var/lib/mysql-mm-1
mkdir /var/lib/mysql-mm-2

Sempre come root prepariamo le configurazioni

cp -rp /etc/mysql/my.cnf /etc/mysql-mm-1/my.cnf
cp -rp /etc/mysql/my.cnf /etc/mysql-mm-2/my.cnf

Editiamo ora il file my.cnf fino ad ottenere per il nodo 1 qualche cosa come

[client]
port            = 3307
socket          = /var/run/mysqld/mysqld-mm-1.sock

[mysqld_safe]
socket          = /var/run/mysqld/mysqld-mm-1.sock
nice            = 0

[mysqld]
user            = mysql
pid-file        = /var/run/mysqld/mysqld-mm-1.pid
socket          = /var/run/mysqld/mysqld-mm-1.sock
port            = 3307
basedir         = /usr
datadir         = /var/lib/mysql-mm-1
tmpdir          = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
key_buffer              = 16M
max_allowed_packet      = 16M
thread_stack            = 192K
thread_cache_size       = 8
myisam-recover         = BACKUP
query_cache_limit       = 1M
query_cache_size        = 16M
log_error = /var/log/mysql/error-mm-1.log
server-id               = 11
log_bin                 = /var/log/mysql/mm-1-bin.log
expire_logs_days        = 10
max_binlog_size         = 100M

[mysqldump]
quick
quote-names
max_allowed_packet      = 16M

[mysql]

[isamchk]
key_buffer              = 16M

e per il nodo 2 qualche cosa come

[client]
port		= 3308
socket		= /var/run/mysqld/mysqld-mm-2.sock

[mysqld_safe]
socket		= /var/run/mysqld/mysqldi-mm-2.sock
nice		= 0

[mysqld]
user		= mysql
pid-file	= /var/run/mysqld/mysqld-mm-2.pid
socket		= /var/run/mysqld/mysqld-mm-2.sock
port		= 3308
basedir		= /usr
datadir		= /var/lib/mysql-mm-2
tmpdir		= /tmp
lc-messages-dir	= /usr/share/mysql
skip-external-locking
bind-address		= 127.0.0.1
key_buffer		= 16M
max_allowed_packet	= 16M
thread_stack		= 192K
thread_cache_size       = 8
myisam-recover         = BACKUP
query_cache_limit	= 1M
query_cache_size        = 16M
log_error = /var/log/mysql/error-mm-2.log
server-id		= 12
log_bin			= /var/log/mysql/mm-2-bin.log
expire_logs_days	= 10
max_binlog_size         = 100M

[mysqldump]
quick
quote-names
max_allowed_packet	= 16M

[mysql]
[isamchk]
key_buffer		= 16M

da notare in questi file:

  • port: ho usato porte non standard e diverse per i due nodi
  • server-id: ho dato due valori diversi ai due nodi
  • log-bin: ho abilitato i binary log
  • datadir: specifica per ogni nodo.

Devo ora popolare le directory dei dati:

mysql_install_db --user=mysql  --defaults-file=/etc/mysql-mm-1/my.cnf
mysql_install_db --user=mysql  --defaults-file=/etc/mysql-mm-2/my.cnf

Posso ora avviare i due database

mysqld_safe --defaults-file=/etc/mysql-mm-1/my.cnf &
mysqld_safe --defaults-file=/etc/mysql-mm-2/my.cnf &

Al primo avvio dovranno essere generati tutta una serie di file ma dopo un po’ i due database dovrebbero essere accessibili:

mysql --port 3307 --host 127.0.0.1 --user=root
mysql --port 3308 --host 127.0.0.1 --user=root

NB: su Ubuntu apparmor impedisce di eseguire questa procedura. Per escluderlo

aa-complain /usr/sbin/mysqld

Trattandosi di due istanze appena create non ci dobbiamo preoccupare allineare la situazione iniziale dei due nodi mysql imprtando dei backup.

Procediamo quindi a configurare il nodo mysql due come replica del nodo mysql uno.

Per prima cosa dobbiamo vedere lo stato come master del nodo uno:

mysql --port 3307 --host 127.0.0.1 --user=root
show master status\G

otterremo qualche cosa come

*************************** 1. row ***************************
            File: mm-1-bin.000005
        Position: 107
    Binlog_Do_DB: 
Binlog_Ignore_DB: 
1 row in set (0.00 sec)

Nel caso avessimo ripristinato da un backup avremmo dovuto far riferimento a informazioni analoghe ma prese al momento del backup.
Abilitiamo ora la prima replica

mysql --port 3307 --host 127.0.0.1 --user=root
change master to MASTER_HOST='127.0.0.1', MASTER_PORT=3307 , MASTER_USER='root' , MASTER_LOG_FILE = 'mm-1-bin.000005', MASTER_LOG_POS =107;
show slave status\G

Ho qui utilizzato l’utente root. In condizioni non di test bisognerebbe utilizzare un utente con gli appositi permessi (REPLICATION_CLIENT, REPLICATION_SLAVE).
Lo stesso per l’altro nodo

mysql --port 3308 --host 127.0.0.1 --user=root
change master to MASTER_HOST='127.0.0.1', MASTER_PORT=3308 , MASTER_USER='root' , MASTER_LOG_FILE = 'mm-2-bin.000005', MASTER_LOG_POS =107;
show slave status\G

mysql e binlog

Una delle caratteristiche più interessanti di MySQL è il suo sistema di replica. Questo lo rende possibili molte configurazioni che rendon il prodotto estremamente flessibile.

Si può abilitare MySQL per replicare tutte le query che comportano delle modifiche alla base dati su degli appositi file di log detti binlog. Questo, con le nuove versioni di MySQL può avvenire in due modi: riportando le query o riportando le modifiche ai file. Non approfondiremo oltre, in questo post, le differenze tra queste due modalità e faremo riferimento al caso in cui vengano riportate le query. Gran parte delle considerazioni rimangono valide in entrambi i casi.

I binlog servono almeno in 3 situazioni molto critiche:

  • assieme ai backup per la Point in Time Recovery: se al momento del backup si sono salvati valori riportati da “show master status\G”, è possibile riapplicare tutte le modifiche effettuate al database e riporatte sui binary log fino ad un preciso istante. Idealmente ricosytruendo lo sato del database subito prima del problema.
  • sistemi in replica: i binlog solo lo strumento attraverso il quale i vari nodi in replica si comunicano le rispettive modifiche alla base dati.
  • analisi a posteriori di bug o attacchi

Si noti, avendone la possibilità, è opprtuno valutare se farli scrivere su dischi e attraverso un controller diverso da quelli utilizzati per i file di dati, trattandosi di una scrittura potenzialmente pesante.

La generazione dei bynary log su MySQL non è abilitata di default ma bisogna aggiungere un gruppo di statement di configurazione come il seguente prima delle configurazione dei vari Engine :

server-id = 1
log_bin = /data/log/mysql-bin.log
expire_logs_days = 10
max_binlog_size = 500M
log_slave_updates = 1
#binlog_do_db = include_database_name
#binlog_ignore_db = include_database_name

la lista dei parametri sopra non è esaustiva.

  • server-id: questo valore è fondamentale nei sistemi in replica in quanto permette al server di capire quale nodo ha ricevuto la query per primo. Bisogna quindi assegnare un numero univoco per ogni server coinvolto
  • log_bin: è il template del nome del file che viene generato. Questa linea abilita anche i binlog.
  • expire_log_days: definisce per quanti giorni i binlog vengono mantenuti da MySQL sul disco
  • max_binlog_size: definisce le dimensioni massime del file. Al raggiungimento di questo limite il file viene chiuso e ne viene aperto un’altro. Nello scegliere le dimensioni di questi file bisogna fare un compromesso tra le loro dimensioni e il loro numero per trovare la situazione più facilmente gestibile.
  • log_slave_updates: nei sistemi in replica permette di specificare se il nodo deve salvare sul binlog anche le query che ha ricevuto dal proprio master o solo eventuali query ricevute direttamente
  • binlog_do_db: se presente specifica la lista dei database le cui modifiche devono essere riportate sui binary log
  • binlog_ignore_db: se presente specifica la lista dei database le cui modifiche non devono essere riportate sui binary log

Attenzione a statement come gli ultimi due:

  • hanno comportamenti differenti nel caso si abbiano nei binary log le query o le modifiche
  • il db a cui si riferische è quello della connessione che non è necessariamente quello della query (es. select * from agenda.telefono)

E’ assolutamente opportuno un approfondimento sui manuali ufficiale prima di procedere con sistemi di produzione.

Come si può dedurre dal nome indipendentemente dal formato scelto i binlog sono file binary non facilmente gestibili con gli strumenti standard di UNIX. Viene in aiuto un tool specifico mysqlbinlog. Questo comando applicato ad una serie di file manda in standard output i comandi sql nella giusta sequenza temporale. Ha molte opzioni e, ovviamente, bisogna far riferimento al suo manuale prima di usarlo su sistemi di produzione.

The Capitalist Game

In The Capitalist game si è alla guida di una società che dovrà produrre e vendere beni in un mercato simulato.

Il gioco è basato su turni di un’ora  che corrispondono ad un mese all’interno del gioco. Ogni società ha 40 anni (di gioco) per svilupparsi prima di venir cancellata. Lo stesso giocatore potrà poi dare vita ad altre società.

Si hanno a disposizione tre tipi di infrastrutture: fabbriche, magazzini e negozi per produrre beni, immagazzinarli e venderli. Non tutti i prodotti sono vendibili direttamente nei negozi essendoci numerosi semilavorati che servono come step intermedi per la produzione di altri beni.

Un sistema di licenze permette di sbloccare, con il crescere della società, sempre nuovi prodotti.

Parallelamente è presente una “borsa azioni” in cui il giocatore può comprare e vendere quote delle società in gioco.

E’ presente infine un mercato da cui è sempre possibile acquistare e vendere beni.

Le varie società attive non sono realmente in concorrenza e l’interazione si riduce quasi solo al confronto sulle classifiche.

Il gioco è comunque piacevole ed equilibrato.