I sistemi UNIX® utilizzano i descrittori di files per leggere e scrivere su disco i files ed i socket di rete, un file descriptor identifica quindi un file o un socket che viene aperto da una connessione di rete o da un processo locale. Ogni volta che un processo di sistema apre un file o un socket viene allocato un descrittore di file, quando questo viene chiuso il relativo file descriptor verrà liberato. Per gestire l'accesso ai file e ai socket, Squid utilizza una tabella di processo che contiene l'elenco di tutti i file descriptor aperti. La dimensione di questa tabella é statica e viene impostata al momento dell'esecuzione del comando ./configure. I diversi Sistemi Operativi oggi sul mercato utilizzano uno schema proprietario nella gestione dei processi e può accadere che il valore dei file descriptor predefinito nel Kernel del Sistema sia troppo piccolo per garantire il funzionamento di alcuni apparati di webcache la cui peculiarietà è quella di gestire dei carichi di traffico molto elevati. Può quindi rendersi necessario aumentare il valore dei file descriptor prima di eseguire il comando ./configure. Per determinare un valore adeguato si deve tenere conto dei seguenti fattori
la singola richiesta HTTP utilizza contemporaneamente sino a 3 file descriptor
connessione HTTP lato client, connessione HTTP lato server e la scrittura o la lettura della cache su disco (scrivere nella cache un MISS o leggere nella cache un HIT)
la scrittura delle informazioni nei file di log utilizza contemporaneamente sino a 4 file descriptor
Squid utilizza solitamente quattro file di log principali (access.log, cache.log, store.log e swap.state) e nel momento in cui accede a detti file apre un file descriptor
le comunicazioni tra Squid ed i processi esterni utilizzano mediamente sino a 20 file descriptors
gli autenticatori, i redirectors e le porte in ascolto, mantengono sempre un certo numero di file descriptors attivi, il valore medio dipende molto dal numero degli helpers utilizzati e dal numero dei socket che vengono aperti da Squid (porte HTTP, ICP, SNMP ed altro).
un browser web esegue mediamente 2 o 3 richieste HTTP persistenti (idle time)
ciò significa che per ogni browser web, volendo fare un dimensionamento pessimistico, si deve prevedere un utilizzo di circa 8 file descriptor.
Quando Squid è fermo in attesa di richieste utilizza in media 24 descrittori di files (file di log e comunicazioni tra processi), ogni singola richiesta HTTP determina l'apertura di una media di 8 file descriptor (singola richiesta e connessioni persistenti).
|
file descriptor medi |
utenti concorrenti |
connessioni persistenti |
totale file descriptor |
|
24 |
20 |
20*8 |
160+24=184 |
|
24 |
50 |
50*8 |
400+24=424 |
|
24 |
100 |
100*8 |
800+24=824 |
|
24 |
200 |
200*8 |
1600+24=1624 |
|
24 |
400 |
400*8 |
3200+24=2324 |
|
24 |
500 |
500*8 |
4000+24=4024 |
Nell'ipotesi più pessimistica con la quale si prevede l'apertura di 10 o più file descriptors per connessione persistente, con 400 client concorrenti saranno necessari almeno 4096 file descriptor. Una buona configurazione può prevedere 1024 file descriptor, tale impostazione può andare bene se si prevede un traffico medio. La tabella riportata in calce può essere utilizzata per dimensionare al meglio il nostro sistema di webcache, se desideriamo verificare il numero di file descriptor configurati per una versione pacchettizzata e preinstallata di Squid, possiamo determinare questo valore ricavandolo dal file cache.log
2004/04/03 13:08:29| With 1024 file descriptors available |
Squid può presentare dei problemi con i file descriptor nel momento in cui viene eseguito, anche in questo caso l'avviso potrà essere rilevato dal file cache.log
2004/04/12 21:33:22| WARNING! Your cache is running out of file descriptors |
nel caso si dovesse presentare questo avviso di warning è necessario accrescere il limite dei file descriptor, la modalità con cui è possibile variare il numero di file descriptor, come abbiamo visto precedentemente, é specifica per ogni Sistema Operativo.
Il Cache Manager è un ottimo strumento per verificare l'allocazione dei processi attivi per file descriptor
Active file descriptors: File Type Tout Nread * Nwrite * Remote Address Description ---- ------ ---- -------- -------- --------------- ------------------------------ 3 Log 0 0 0 /usr/local/squid/var/logs/cache.log 4 Socket 0 0 0 .0 DNS Socket 5 File 0 0 1177 /usr/local/squid/var/logs/access.log 6 Pipe 0 0 0 unlinkd -> squid 7 File 0 0 1609 /usr/local/squid/var/logs/store.log 8 File 0 0 0 /home/var/spool/squid/swap.state 9 Pipe 0 0 0 squid -> unlinkd 10 Socket 1440 70* 0 127.0.0.1.51740 cache_object://127.0.0.1/filedescriptors 11 Socket 0 0* 0 .0 HTTP Socket 12 Socket 0 0* 0 .0 ICP Socket 13 Socket 0 0* 0 .0 HTCP Socket 14 Socket 0 0* 0 .0 SNMP Port |
Il valore dei files descriptors impostato come default per ogni distribuzione Linux è generalmente pari a 1024, gestire questo tipo di impostazione non è affatto semplice. Infatti prima di configurare Squid è necessario verificare il numero di file descriptors attualmente configurati utilizzando il comando ulimit(8), si tratta di un comando che fa parte della shell. Il primo passo da compiere è quello di verificare il numero di file descriptor disponibili sulla nostra piattaforma
% ulimit -n 1024 |
a questo punto dovremmo editare uno dei file di system include del kernel, in particolare si tratta del file /usr/include/bits/tipes.h oppure del file /usr/include/bits/typesizes.h modificando il valore __FD_SETSIZE
% vi /usr/include/bits/typesizes.h #define __FD_SETSIZE 4096 |
il valore __FD_SETSIZE viene controllato durante l'esecuzione dello script di ./configure. Squid è particolarmente vorace di file descriptors che sono una risorsa finita ma regolabile del sistema operativo, oltre che molto preziosa, visto che sono i canali di comunicazione che vengono utilizzati dai vari processi per parlare con il mondo esterno e fra di loro. Per verificare quanti file descriptors il sistema metta a disposizione con la configurazione standard si può digitare il seguente comando
% cat /proc/sys/fs/file-max 104857 |
è opportuno che questo numero sia piuttosto alto, in linea di massima può andare bene se maggiore di 65000. Qualora il numero dovesse essere più basso, si consiglia di editare (come root) il file /etc/sysctl.conf aggiungendo la riga
fs.file-max = 102400 |
e poi lanciare (sempre come root) il comando
% sysctl -p |
che legge le impostazioni dal file /etc/sysctl.conf (viene di norma eseguito automaticamente al reboot, quindi le impostazioni non andranno perse). Se per caso la nostra distribuzione linux non utilizzasse il sistema sysctl, si può in alternativa aggiungere la riga
echo 102400 > /proc/sys/fs/file-max |
al file rc.local, e lanciarla anche dalla riga di comando (come root) per attivarla anche immediatamente. queste impostazioni vanno aggiunte su tutti i sistemi su cui Squid verrà installato, non solo su quelli dove viene compilato. A questo punto incrementiamo il limite massimo dei processi di file descriptors. Dovremmo utilizzare la stessa shell (bash, sh, tsh...) con la quale successivamente configureremo e compileremo Squid
% ulimit -Hn 4096 % ulimit -n 4096 |
dove 4096 è il valore di file descriptors che si intendono utilizzare con Squid, eseguiamo un make clean prima di avviare lo script ./config.status che ci consentirà di configurare nuovamente l'ambiente tenendo conto delle nuove impostazioni del kernel
% make clean % ./config.status --recheck ... checking Default FD_SETSIZE value... 4096 checking Maximum number of filedescriptors we can open... 4096 checking Default UDP send buffer size... 65535 checking Default UDP receive buffer size... 65535 checking Default TCP send buffer size... 16384 checking Default TCP receive buffer size... 87380 Limiting receive buffer size to 64K checking if sys_errlist is already defined... (cached) no checking for libresolv _dns_ttl_ hack... no checking if inet_ntoa() actually works... yes checking for working statvfs() interface... yes checking for _res.nsaddr_list... (cached) yes creating ./config.status ... |
ora compiliamo ed installiamo nuovamente Squid
% make % make install |
non abbiamo ancora finito, impostare il valore corretto di file descriptors con linux non riguarda solo la compilazione e l'installazione di Squid ma anche il suo avviamento
ulimit -HSn 4096 |
possiamo inserire questo ultimo comando nello script di avviamento di Squid, in qualsiasi distribuzione Red Hat o Fedora core il file da modificare è /etc/rc.d/init.d/squid
Il valore di default è 1024, per impostare il numero di File Descriptor dovremo editare il file /etc/system
set rlim_fd_max = 4096 |
L'approccio al problema dei file descriptors nei sistemi BSD è totalmente diverso e naturalmente più funzionale se paragonato con i sistemi linux, la voce di configurazione che nel kernel controlla questa impostazione prende il nome di MAXFILES.
Ultimamente questo tipo di approccio è stato leggermente modificato, infatti i nuovi kernel dei sistemi FreeBSD controllano dinamicamente il numero delle tabelle interne che vengono utilizzate dal sistema operativo, tale impostazione viene determinata prendendo come riferimento la quantità di memoria che è stata fisicamente installata sul server di produzione. Il file di configurazione del Kernel di FreeBSD (e di molti alti sistemi BSD) si trova in /usr/src/sys/i386/conf/GENERIC, l'impostazione che determina questa modalità di funzionamento è
maxusers 0 |
se vogliamo impostare manualmente il valore dei descrittori di files dovremmo editare il file di configurazione del kernel, questa modifica vale anche per i sistemi NetBSD ed OpenBSD
options MAXFILES=8192
|
possiamo verificare il valore dei file descriptors attivi in un dato momento utilizzando il comando sysctl(8), le variabili del kernel di un sistema FreeBSD possono essere visualizzate ed eventualmente modificate utilizzando il comando sysctl
% sysctl -a | grep kern.maxfiles
kern.maxfiles: 4040
kern.maxfilesperproc: 3636
|
come per i sistemi linux per visualizzare il numero di files descriptors attivi possiamo anche utilizzare l'opzione di shell ulimit
% ulimit -n
4040
|
non è dunque necessario ricompilare il kernel per impostare il valore corretto dei file descriptors, sarà sufficente editare il file /etc/sysctl.conf
kern.maxfiles=4040
kern.maxfilesperproc=3636
|
per concludere possiamo dire che modificare manualmente il numero di file descriptors in un sistema BSD ha senso solo se si vuole ottimizzare le prestazioni di un server di rete ad alto traffico.
Un'altro collo di bottiglia per il kernel di un sistema FreeBSD è rappresentato dalla corretta impostazione del valore di MBUF. MBUF sono dei pezzi di memoria che vengono utilizzati dal kernel per consentire tutte le connessioni di rete. Il numero di MBUF scala in relazione alla impostazione dell'opzione MAXUSERS all'interno del file di configurazione del kernel, anche in questo caso con i nuovi kernel di FreeBSD, questo valore viene impostato in maniera automatica così come avviene per i descrittori di files, anche in questo caso potrebbe rendersi necessario aumentare il valore degli MBUF. L'opzione NMBCLUSTERS controlla il numero di MBUFS creati dal kernel di sistema
% netstat -m
129/320/65536 mbufs in use (current/peak/max):
129 mbufs allocated to data
128/260/16384 mbuf clusters in use (current/peak/max)
600 Kbytes allocated to network (1% of mb_map in use)
0 requests for memory denied
0 requests for memory delayed
0 calls to protocol drain routines
|
questo sistema FreeBSD dispone di 16384 MBUF, se volessimo aumentare questo valore dovremmo modificare il file di configurazione del Kernel così come segue
options NMBCLUSTERS=32768
|
questa impostazione vale anche per NetBSD e OpenBSD
il numero massimo di file descriptor è 2048, questo valore é preimpostato nella libreria dinamica MSVCRT.DLL e non può essere modificato se non ricompilando la DLL stessa.
Se si utilizza il runtime EMX (The UN*X to OS/2-EMX Porting) è possibile definire il numero massimo di file handles modificando il file config.sys
SET EMXOPT=-h# |
questa impostazione fissa il limite massimo di file handles a #, il valore di # deve essere un numero compreso tra 10 e 65536, l'ultima versione disponibile compilata con il runtime EMX supporta solo 256 file handles.