En attendant le portage entièrement en go de bases de données fichier populaires telles que berkeley db ou SQLite, il faut se contenter de système de stockage clé/valeur comme leveldb ou diskv que je vous présenterai dans cet article.
On pourrait qualifier Diskv de base de données nosql basée sur un système clé/valeur.
Le principe de diskv est d'utiliser le système de fichier comme espace de stockage avec les principes suivants :
On comprend donc une première limite : les clés ne peuvent avoir pour valeur que ce qui est autorisé par le système d'exploitation comme étant un nom de fichier.
Note : Le code d'exemple commenté dans cet article ne nécessite pas de logiciel tiers. On peut en utiliser toutes les fonctionnalités sans les logiciels HP cités ci-après. La citation de ces logiciels permet d'illustrer le propos.
Il m'arrive de faire des tests de performance avec le logiciel HP Preformance Center (logiciel de la société HP qui se base sur la technologie LoadRunner). Une des fonctionnalités de l'outil est l'IP Spoofing. C'est une technique avec laquelle on fait croire à un système sous test que plusieurs machines différentes se connectent, alors qu'il n'y a parfois qu'un seul injecteur impliqué dans le test de charge. Ce qui est utile pour tester l'efficacité de certains systèmes à répartition de charge.
Ce subterfuge est possible en utilisant plusieurs adresses IP avec une configuration matérielle (plusieurs cartes Ethernet connectées au réseau) ou logicielle (faire croire au réseau que l'injecteur est un routeur donnant accès à un sous-réseau) ou un mix des deux.
Principe de fonctionnement de l'IP Spoofing
J'ai récemment reçu deux serveurs dans le parc que j'administre et je voulais vérifier ma configuration (c.-à-d. savoir si ma configuration était capable de faire un tir avec de l'IP spoofing). Une des nombreuses solutions est de tester un site web et de regarder dans les fichiers de log si l'adresse IP d'origine est variée (les adresses IP doivent correspondre à ce que l'on a configuré côté Performance Center et/ou avec l'équipe réseau de l'entreprise). Seulement, il n'y aurait pas eu matière à rédiger cet article :).
Ma webapp de test a deux points d'accès :
Key : 11.204.220.91 ==> Nov 22, 2013 at 5:02pm (PM) Key : 11.204.220.92 ==> Nov 22, 2013 at 5:02pm (PM) Key : 11.204.220.93 ==> Nov 22, 2013 at 5:02pm (PM) Key : 11.204.220.94 ==> Nov 22, 2013 at 5:02pm (PM) Key : 11.204.220.95 ==> Nov 22, 2013 at 5:02pm (PM) Key : 11.189.18.206 ==> Nov 22, 2013 at 4:55pm (PM) Key : 11.160.164.219 ==> Nov 22, 2013 at 5:02pm (PM) Key : 11.160.164.220 ==> Nov 22, 2013 at 5:02pm (PM) Key : 11.160.164.221 ==> Nov 22, 2013 at 5:02pm (PM) Key : 11.160.164.222 ==> Nov 22, 2013 at 5:02pm (PM) Key : 11.160.164.223 ==> Nov 22, 2013 at 5:02pm (PM) Key : 127.0.0.1 ==> Nov 22, 2013 at 4:42pm (PM)
Récupérer et installer le paquet golang de diskv à l'aide des commandes suivantes :
go get github.com/peterbourgon/diskv go install github.com/peterbourgon/diskv
Note: Le paquet contient une dépendance à github.com/petar/GoLLRB, un package d'arbre de recherche binaire que nous utiliserons dans le but de classer les résultats de notre requête à la base.
import ( "github.com/peterbourgon/diskv" )
On commence par écrire la fonction qui décrit la manière dont les clés seront stockées. Ici, on indique de stocker tous les fichiers (dont le contenu stockera nos valeurs) seront stockés dans le même répertoire (dans notre cas, le répertoire clients).
flatTransform := func(string) []string { return []string{} }
Puis on crée une fonction qui décrit la manière dont les informations seront triées (bien sûr, cette étape est optionnelle si vous ne souhaitez pas trier les informations ou déléguer le tri au client par exemple avec la bibliothèque Javascript DataTable) :
func strLess(a, b string) bool { return a < b }
On initialise ensuite le gestionnaire de la base de données qui la crée si elle n'existe pas (c.-à-d. la création du répertoire).
var db *diskv.Diskv db = diskv.New(diskv.Options{ BasePath: "clients", Transform: flatTransform, CacheSizeMax: 1024 * 1024, Index: &diskv.LLRBIndex{}, IndexLess: strLess, })
Le code de nos contrôleurs sera assez simple. Vous remarquerez une petite astuce. Si vous souhaitez passer un contenu HTML à une vue sans que le filtre de sécurité du paquet html/template ne le filtre en l'échappant, il faut utiliser un champ template.HTML au lieu d'un champ string.
type Page struct { Title string Content template.HTML }
Le contrôleur de la page d'accueil itère sur toutes les clés présentes dans la base de données (range db.Keys()) et pour chacune des clés trouvées, il lit la valeur associée (en l'occurrence le contenu du fichier qui a pour nom la clé) à l'aide de l'instruction db.Read(k). Enfin, on passe la liste des informations trouvées à la vue.
func handlerHome(w http.ResponseWriter, r *http.Request) { var content = `
` for k := range db.Keys() { v, err := db.Read(k) checkHttpError(err, w) content += `Key : ` + k + ` ==> ` + string(v) + `
` } var p = Page{Title: "Home", Content: template.HTML(content)} err := templates.ExecuteTemplate(w, "base.html", p) checkHttpError(err, w) }
Le contrôleur de la page cible vous permet de faire la connaissance de quelques fonctionnalités de la bibliothèque standard de golang :
func handlerTarget(w http.ResponseWriter, r *http.Request) { ip := strings.Split(r.RemoteAddr,":")[0] const layout = "Jan 2, 2006 at 3:04pm (MST)" t := time.Now() timeNow := t.Format(layout) err := db.Write(ip, []byte(timeNow)) checkHttpError(err, w) content := `` + ip + ` => ` + timeNow + `` p := Page{Title: "Home", Content: template.HTML(content)} err = templates.ExecuteTemplate(w, "base.html", p) checkHttpError(err, w) }
Le code du template de base est très simple :
<!DOCTYPE html> <html class="no-js" lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title></title> </head> <body> </body> </html>
err:=db.EraseAll()
Une traduction du blog officiel de golang expliquant le mécanisme de la réflexion en Go. Lire »
Traduction d'un article du blog officiel expliquant comment échanger des données entre deux programmes golang grâce à un format natif Lire »
Traduction d'une partie des spécifications officielles du langage Go, cet article explique comment développer en Go. Lire »
La bibliothèque standard de go ne gère pas les variables de session d'une application. Il existe une solution avec le toolkit Gorilla Lire »
Préconisations officielles pour la gestion des erreurs dans un programme golang. Cet article complète les explications sur panic, defer et recover Lire »
Soyez le premier à commenter cet article
Tous les commentaires sont soumis à modération. Les balises HTML sont pour la plupart autorisées. Les liens contextuels et intéressants sont en follow.