Nouveau : Datasets open source gratuits disponibles !Decouvrir →
🐹
Avance 30 min Go

Microservices avec Go

Pourquoi Microservices avec Go ?

Dans un monde où les applications grandissent rapidement et deviennent complexe, les microservices ont pris une place centrale. Un développeur peut avoir besoin de microservices pour plusieurs raisons, notamment pour la scalabilité, la maintenance et le développement en équipe. Par exemple, dans un système d'application e-commerce, chaque composant (catalogue, paiement, commande) peut être un microservice distinct, permettant une évolution indépendante et une meilleure isolation des erreurs.

Prerequis

  • Connaissance de base du langage Go
  • Familiarité avec les concepts de base de l'architecture en microservices
  • Un environnement de développement Go configuré (Go 1.16 ou plus tard recommandé)
  • Un IDE comme VSCode pour une meilleure productivité

Concepts fondamentaux

1. Architecture en Microservices

Un système d'architecture en microservices est composé de petits services indépendants qui communiquent via des API RESTful. Chaque service gère une fonctionnalité spécifique.

// Exemple d'un service simple en Go
package main

import (
    "fmt"
    "net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
}

func main() {
    http.HandleFunc("/hello", helloHandler)
    http.ListenAndServe(":8080", nil)
}

2. Communication entre Microservices

Les microservices communiquent généralement via des API RESTful ou gRPC pour une communication plus rapide et efficace.

// Exemple de client HTTP simple en Go
package main

import (
    "fmt"
    "net/http"
    "io/ioutil"
)

func main() {
    resp, err := http.Get("http://localhost:8080/hello")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Error reading response body:", err)
        return
    }

    fmt.Println(string(body))
}

3. Gestion des Erreurs et du Retour des erreurs

Chaque microservice doit être capable de retourner des erreurs claires et compréhensibles.

// Exemple de gestion d'erreurs en Go
package main

import (
    "fmt"
    "net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
    if err := someFunction(); err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        fmt.Fprintf(w, "Error: %s", err)
        return
    }
    fmt.Fprintf(w, "Hello, World!")
}

func someFunction() error {
    // Simulate an error
    return fmt.Errorf("some error occurred")
}

func main() {
    http.HandleFunc("/hello", helloHandler)
    http.ListenAndServe(":8080", nil)
}

Mise en pratique : projet fil rouge

1. Création du Projet

mkdir task-manager
cd task-manager
go mod init task-manager

2. Création des Fichiers et Packages

  • main.go pour la fonction principale
  • task.go pour les structurs de tâches et leurs méthodes
  • handler.go pour les gestionnaires d'API HTTP
touch main.go task.go handler.go

3. Code Source Complet

main.go

package main

import (
    "net/http"
    "task-manager/handler"
)

func main() {
    http.HandleFunc("/tasks", handler.TasksHandler)
    http.HandleFunc("/tasks/", handler.TaskDetailsHandler)

    fmt.Println("Starting server at port 8080")
    if err := http.ListenAndServe(":8080", nil); err != nil {
        panic(err)
    }
}

task.go

package task

type Task struct {
    ID        int    `json:"id"`
    Title     string `json:"title"`
    Completed bool   `json:"completed"`
}

var tasks = []Task{
    {ID: 1, Title: "Buy groceries", Completed: false},
    {ID: 2, Title: "Do laundry", Completed: true},
}

handler.go

package handler

import (
    "encoding/json"
    "net/http"
    "task-manager/task"
)

func TasksHandler(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case "GET":
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(task.Tasks)
    default:
        w.WriteHeader(http.StatusMethodNotAllowed)
        fmt.Fprintf(w, "Method %s not allowed", r.Method)
    }
}

func TaskDetailsHandler(w http.ResponseWriter, r *http.Request) {
    id := r.URL.Path[len("/tasks/"):]

    for _, task := range task.Tasks {
        if task.ID == id {
            w.Header().Set("Content-Type", "application/json")
            json.NewEncoder(w).Encode(task)
            return
        }
    }

    w.WriteHeader(http.StatusNotFound)
    fmt.Fprintf(w, "Task not found")
}

4. Exécution du Projet

go run main.go handler.go task.go

Erreurs frequentes et debugging

1. Erreur : listen: address already in use

Cause : L'adresse est déjà utilisée par un autre service. Correction : Changer le port d'écoute.

// Avant
http.ListenAndServe(":8080", nil)

// Après
http.ListenAndServe(":8081", nil)

2. Erreur : panic: runtime error: index out of range

Cause : Tentative de lire au-delà des limites d'un slice. Correction : Vérifier la longueur du slice avant l'accès.

// Avant
id := r.URL.Path[len("/tasks/"):]

for _, task := range task.Tasks {
    if task.ID == id {
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(task)
        return
    }
}

w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "Task not found")

// Après
id := r.URL.Path[len("/tasks/"):]

index, err := strconv.Atoi(id)
if err != nil || index < 0 || index >= len(task.Tasks) {
    w.WriteHeader(http.StatusNotFound)
    fmt.Fprintf(w, "Task not found")
    return
}

task := task.Tasks[index]
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(task)

3. Erreur : unrecognized selector sent to nil interface

Cause : Appel d'une méthode sur un objet nil. Correction : Vérifier que l'objet n'est pas nil avant l'appel de la méthode.

// Avant
task := task.Tasks[id]
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(task)

// Après
if id >= 0 && id < len(task.Tasks) {
    task := task.Tasks[id]
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(task)
} else {
    w.WriteHeader(http.StatusNotFound)
    fmt.Fprintf(w, "Task not found")
}

Pour aller plus loin

1. Utiliser Docker pour le déploiement

Docker permet de conteneuriser les applications et facilite leur déploiement sur n'importe quel environnement.

  • Créer un fichier Dockerfile :
## Utilise une image officielle Go
FROM golang:1.16

## Définit le répertoire de travail dans le conteneur
WORKDIR /app

## Copie les fichiers du projet vers le répertoire de travail
COPY . .

## Compile l'application
RUN go build -o main

## Exécute l'application
CMD ["./main"]
  • Construire et exécuter le conteneur :
docker build -t task-manager .
docker run -p 8080:8080 task-manager

2. Utiliser Kubernetes pour la gestion de l'échelle et de la disponibilité

Kubernetes est un orchestrateur de conteneurs qui gère le déploiement, la mise à échelle et la maintenance des applications en microservices.

  • Installer Kubernetes sur votre machine (minikube recommandé pour les tests locaux)
  • Créer un fichier deployment.yaml :
apiVersion: apps/v1
kind: Deployment
metadata:
  name: task-manager
spec:
  replicas: 3
  selector:
    matchLabels:
      app: task-manager
  template:
    metadata:
      labels:
        app: task-manager
    spec:
      containers:
      - name: task-manager
        image: task-manager:latest
        ports:
        - containerPort: 8080
  • Déployer l'application sur Kubernetes :
kubectl apply -f deployment.yaml

3. Utiliser gRPC pour une communication plus rapide et efficace

gRPC est un framework RPC (Remote Procedure Call) open-source qui permet de créer des services en microservices.

  • Créer un fichier task.proto :
syntax = "proto3";

package task;

service TaskService {
  rpc GetTasks (Empty) returns (TaskList);
  rpc GetTaskById (TaskId) returns (Task);
}

message Empty {}

message TaskId {
  int32 id = 1;
}

message Task {
  int32 id = 1;
  string title = 2;
  bool completed = 3;
}

message TaskList {
  repeated Task tasks = 1;
}
  • Générer le code en Go :
protoc --go_out=plugins=grpc:. task.proto

Défi pratique

Créer un microservice pour une API de blog. Le service doit être capable de créer, lire, mettre à jour et supprimer des articles.

  1. Créer les fichiers main.go, article.go et handler.go.
  2. Implémenter les fonctionnalités CRUD.
  3. Tester le service avec un client HTTP comme Postman.

Besoin d'aide sur Go ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Qu'est-ce que Microservices avec Go?
Microservices avec Go est un modèle d'architecture logicielle qui permet de développer des applications en divisant le code source en petits services indépendants, chacun exécuté dans son propre processus et communiquant entre eux via des API RESTful. Go, également connu sous le nom de Golang, est un langage de programmation conçu pour la simplicité, l'efficacité et la productivité, ce qui en fait idéal pour développer des microservices.
Comment démarrer un projet de Microservices avec Go?
Pour démarrer un projet de microservices avec Go, commencez par concevoir votre architecture. Définissez les services individuels qui seront nécessaires pour votre application et leurs points d'entrée API. Ensuite, créez chaque service en utilisant le langage Go en vous assurant que chacun est autonome et peut être déployé indépendamment. Utilisez des outils comme Docker pour containeriser vos services et Kubernetes pour orchestrer leur déploiement et la gestion de l'échelle.
Quelles sont les principales avantages d'utiliser Go pour les microservices?
Go offre plusieurs avantages pour le développement de microservices, notamment sa facilité d'utilisation qui permet une rapidité accrue dans le codage et la maintenance. Sa performance élevée est également un atout majeur pour les applications nécessitant des temps de réponse courts. De plus, Go supporte la concurrence native par le biais de goroutines et les channels, ce qui facilite la gestion de l'asynchronisme et l'écriture de code concurrentiel. Enfin, sa communauté active et son écosystème robustes offrent une multitude de bibliothèques et outils utiles pour le développement de microservices.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.