Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task - create a version of the cache shared between servers and based on redis #78

Closed
17 tasks
Tracked by #11
benoitdm-oslandia opened this issue Oct 21, 2022 · 8 comments
Closed
17 tasks
Tracked by #11

Comments

@benoitdm-oslandia
Copy link
Owner

Créer un cache exploitant redis

Dans le cas d'un déploiement avec une scalabilité horizontale, le cache sera différent d'une instance à l'autre. Pour palier à ce problème, on peut utiliser une instance Redis qui fera le stockage du cache !

Liens utiles (lecture)

Étapes

  1. Installer au préalable un serveur Redis

    Mise en place externe au projet

  2. Ajouter une option du processus ou une variable d'env pour activer l'utilisation du cache Redis

  3. Ajouter la configuration Redis (toml)

  4. Initialiser la connexion Redis

  5. Mettre en place une logique d’implémentation

    [GET] :
    si la donnée n'est pas disponible dans le cache Redis,

    • on va la chercher en base
    • on l'enregistre dans le cache Redis

    1_tAvBvnbFK_MkEfHj_ViQMQ

    [GET] :
    si la donnée n'est pas disponible ni dans le cache Redis, ni en base,
    on enregistre l'information de non-existence dans le cache Redis

    1_5ZAZg47q-V2aEbHnt_UByw

    [POST] :
    on enregistre toujours les nouvelles données dans le cache Redis

    [PATCH | PUT] :
    on enregistre la modification de données dans le cache Redis,
    en écrasant l'ancien cache

    :eye_in_speech_bubble: Redis stocke des clefs/valeurs

    • Ex. etag: {...} // réponse json d'une collection

    :eye_in_speech_bubble: où ajouter les instructions redis ?

    on va utiliser la notion de middleware !

  6. Implémenter le middleware

    • vérifier : verifyRedis()
    • enregistrer : setRedis()
    • récupérer : getRedis()
    • nettoyer : clearRedis()

    cf. commentaire : exemples d'implémentation

  7. Ajouter un test d'utilisation du cache Redis

  8. Mettre en place un benchmark avec / sans cache Redis

  9. Test de charge

    Mise en place interne au projet

@benoitdm-oslandia
Copy link
Owner Author

In GitLab by @lowzonenose on Nov 1, 2022, 10:10

changed time estimate to 120h

@benoitdm-oslandia
Copy link
Owner Author

In GitLab by @lowzonenose on Nov 1, 2022, 20:50

Exemple d'implémentation du cache Redis en middleware

  • Ex. Conf
// exposer plusieurs variables d'env pour configurer le service : **PGFS_REDIS**
// et
// mettre en place la config toml
  • Ex. Service / Data Redis
type CacheRedis struct {...}
func redisConnect() CacheRedis {} 
func redisConfig() {}
func (c *CacheRedis) set () {}
func (c *CacheRedis) get () {}
func (c *CacheRedis) active () {}
(...)
  • Ex. Request GET :

ajout du middleware Redis

// middleware sur toutes les routes en GET
func addRoute(router *mux.Router, path string, handler func(http.ResponseWriter, *http.Request) *appError) {
  addRouteWithMethod(router, path, MiddlewareRedis(handler), "GET")
}

func addRouteWithMethod(router *mux.Router, path string, handler func(http.ResponseWriter, *http.Request) *appError, method string) {
  router.Handle(path, appHandler(handler)).Methods(method)
}

type appHandler func(http.ResponseWriter, *http.Request) *appError

// middleware
func MiddlewareRedis(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // logique du cache redis : 
        // > Redis Actif ?
        // > renvoie un cache (GetRedis(something)) ou redirige vers le handler (next)
        next.ServeHTTP(w, r)
    })
}

// handler
func handler(w http.ResponseWriter, r *http.Request) *appError {
  // logique de la reponse : 
  // > renvoie une reponse de la bdd
  // > Redis Actif ?
  // >   creer une entrée dans le cache -> setRedis(something)
}
  • Ex. Request POST :
  • aucune modifiation des signatures
  • chaque handler possède le code Redis -> SetRedis(something)
func addRouteWithMethod(router *mux.Router, path string, handler func(http.ResponseWriter, *http.Request) *appError, method string) {
	router.Handle(path, appHandler(handler)).Methods(method)
}

// handler
func handler(w http.ResponseWriter, r *http.Request) *appError {
  // logique de la reponse : 
  // > renvoie une reponse de la bdd
  // > Redis Actif ?
  // >   creer une entrée dans le cache -> SetRedis(something)
}
  • Ex. Context :

passage d'informations du middleware vers le handler dans le contexte de la requête

// middleware
func MiddlewareRedis(next http.Handler) http.Handler {
 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  ctx := r.Context()
  ctx = context.WithValue(ctx, "data", something)
  r = r.WithContext(ctx)
  next.ServeHTTP(w, r)
 })
}

// handler
func handler(w http.ResponseWriter, r *http.Request) *appError {
  if data := r.Context().Value("data"); data != nil {
    // some stuff...
  }
}

@benoitdm-oslandia
Copy link
Owner Author

In GitLab by @lowzonenose on Nov 1, 2022, 20:52

added 8h of time spent

@benoitdm-oslandia
Copy link
Owner Author

In GitLab by @lowzonenose on Nov 2, 2022, 24:33

Autre exemple d'implémentation du cache Redis en middleware

// middleware sur toutes les routes
func addRouteWithMethod(router *mux.Router, path string, handler func(http.ResponseWriter, *http.Request) *appError, method string) {
  router.Handle(path, appHandler(handler)).Methods(method)
  router.Use(redis.Middleware)
}

// middleware
func (c *CacheRedis) Middleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // logique du cache redis : 
        // > Redis Actif ?
        // > renvoie un cache (getRedis(something)) ou redirige vers le handler (next)
        next.ServeHTTP(w, r)
    })
}
type CacheRedis struct {...}
func redisConnect() CacheRedis {} 
func redisConfig() {}
func (c *CacheRedis) Set () {}
func (c *CacheRedis) Get () {}
func (c *CacheRedis) Active () {}
func (c *CacheRedis) Middleware () {}
(...)

@benoitdm-oslandia
Copy link
Owner Author

hum ... il faut qu'on parle @lowzonenose 😄

@benoitdm-oslandia
Copy link
Owner Author

marked this issue as related to #11

@benoitdm-oslandia
Copy link
Owner Author

cloned to #89

@benoitdm-oslandia
Copy link
Owner Author

marked this issue as related to #89

This was referenced Nov 10, 2022
@nrevelant nrevelant changed the title Task - créer un cache exploitant redis Task - create a version of the cache shared between servers and based on redis Dec 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

No branches or pull requests

2 participants