Cachear los Resultados de la Ejecución de Solicitudes

GolangGolangBeginner
Practicar Ahora

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En este proyecto, aprenderás a implementar una biblioteca de caché que admite un tiempo de expiración basado en el paquete singleflight de Go. Esta biblioteca de caché se puede utilizar en sistemas distribuidos para cachear los resultados de ejecución de solicitudes, mejorando el rendimiento de tu aplicación.

👀 Vista previa

$ /usr/local/go/bin/go test --race
PASS
ok      cacheflight     1.263s

🎯 Tareas

En este proyecto, aprenderás:

  • Cómo inicializar un módulo de Go e instalar los paquetes necesarios
  • Cómo implementar la biblioteca de caché utilizando el paquete singleflight
  • Cómo probar la biblioteca de caché para asegurarte de que funcione como se espera

🏆 Logros

Después de completar este proyecto, podrás:

  • Comprender los conceptos básicos de la caché y el paquete singleflight en Go
  • Implementar una biblioteca de caché que admita un tiempo de expiración
  • Integrar la biblioteca de caché en tu sistema distribuido para mejorar el rendimiento de tu aplicación

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("Golang")) -.-> go/ConcurrencyGroup(["Concurrency"]) go(("Golang")) -.-> go/AdvancedTopicsGroup(["Advanced Topics"]) go(("Golang")) -.-> go/TestingandProfilingGroup(["Testing and Profiling"]) go(("Golang")) -.-> go/CommandLineandEnvironmentGroup(["Command Line and Environment"]) go/ConcurrencyGroup -.-> go/goroutines("Goroutines") go/ConcurrencyGroup -.-> go/channels("Channels") go/ConcurrencyGroup -.-> go/mutexes("Mutexes") go/AdvancedTopicsGroup -.-> go/time("Time") go/TestingandProfilingGroup -.-> go/testing_and_benchmarking("Testing and Benchmarking") go/CommandLineandEnvironmentGroup -.-> go/command_line("Command Line") subgraph Lab Skills go/goroutines -.-> lab-301256{{"Cachear los Resultados de la Ejecución de Solicitudes"}} go/channels -.-> lab-301256{{"Cachear los Resultados de la Ejecución de Solicitudes"}} go/mutexes -.-> lab-301256{{"Cachear los Resultados de la Ejecución de Solicitudes"}} go/time -.-> lab-301256{{"Cachear los Resultados de la Ejecución de Solicitudes"}} go/testing_and_benchmarking -.-> lab-301256{{"Cachear los Resultados de la Ejecución de Solicitudes"}} go/command_line -.-> lab-301256{{"Cachear los Resultados de la Ejecución de Solicitudes"}} end

Inicializar el módulo e instalar los paquetes necesarios

En este paso, aprenderás a inicializar el módulo e instalar los paquetes necesarios para el proyecto.

  1. Abra la terminal en el directorio /home/labex/project.

  2. Inicialice el módulo utilizando el siguiente comando:

    $ /usr/local/go/bin/go mod init cacheflight
  3. Instale los paquetes necesarios utilizando los siguientes comandos:

    $ /usr/local/go/bin/go get github.com/golang/groupcache/singleflight
    $ /usr/local/go/bin/go get github.com/stretchr/testify/assert

Implementar la biblioteca de caché

En este paso, implementarás la biblioteca de caché basada en el paquete singleflight.

  1. Abra el archivo cacheflight.go en el directorio /home/labex/project.

  2. Agregue el contenido necesario a import.

    import (
        "sync"
        "time"
    
        "github.com/golang/groupcache/singleflight"
    )
  3. Agregue el contenido necesario a type Group y type cacheResult.

    // cacheResult es el resultado de la caché
    type cacheResult struct {
        data      interface{} // los datos de la caché
        ctime     time.Time   // tiempo de creación de la caché
        isRunning chan bool   // ¿está en ejecución la función?
    }
    
    // Group es la estructura principal
    type Group struct {
        cacheExpiration time.Duration          // tiempo de expiración de la caché
        sfg             *singleflight.Group    // grupo singleflight
        cache           map[string]cacheResult // resultado de la caché
        mu              sync.Mutex             // mutex
    }
  4. Implemente la función NewGroup para devolver un nuevo grupo de caché con el tiempo de expiración de la caché especificado.

    func NewGroup(cacheExpiration time.Duration) (group *Group) {
        group = &Group{
            sfg:             &singleflight.Group{},
            cache:           make(map[string]cacheResult),
            cacheExpiration: cacheExpiration,
        }
        return
    }
  5. Implemente la función do para manejar la lógica de caché.

    func (g *Group) do(key string, fn func() (interface{}, error)) (ret interface{}, err error) {
        return g.sfg.Do(key, func() (interface{}, error) {
            g.mu.Lock()
            result, ok := g.cache[key]
            if result.isRunning!= nil {
                g.mu.Unlock()
                // esperar a que fn termine
                <-result.isRunning
                return g.do(key, fn)
            } else if!ok || result.ctime.Add(g.cacheExpiration).Before(time.Now()) {
                // si la caché no existe o ha expirado
                var run = make(chan bool)
                result.isRunning = run
                g.cache[key] = result
                // cuando fn termine y cierre el canal run, permitir que otras gorutinas obtengan la caché
                defer close(run)
            } else {
                // si la caché existe y no ha expirado
                g.mu.Unlock()
                return result.data, nil
            }
    
            g.mu.Unlock()
    
            // diferentes claves pueden ejecutarse al mismo tiempo
            ret, err = fn()
            if err!= nil {
                return ret, nil
            }
    
            result = cacheResult{
                data:  ret,
                ctime: time.Now(),
            }
            g.mu.Lock()
            g.cache[key] = result
            g.mu.Unlock()
    
            return ret, nil
        })
    }
  6. Implemente la función Do para ser un envoltorio de la función do.

    func (g *Group) Do(key string, fn func() (interface{}, error)) (ret interface{}, err error) {
        return g.do(key, fn)
    }

Probar la biblioteca de caché

En este paso, probarás la biblioteca de caché para asegurarte de que funcione como se espera.

  1. Abra la terminal en el directorio /home/labex/project.

  2. Ejecute el siguiente comando para ejecutar las pruebas:

    $ cd /home/labex/project
    $ /usr/local/go/bin/go test --race
  3. Si la función de caché se ha implementado correctamente, verás la siguiente salida:

    PASS
    ok      cacheflight     1.263s
  4. Si se produce un error de tiempo de espera, ejecute los siguientes comandos en la terminal y luego haga clic en el botón de reinspección para aprobar la comprobación:

    $ cd /home/labex/project
    $ /usr/local/go/bin/go test --race

¡Felicitaciones! Has implementado con éxito la biblioteca de caché basada en el paquete singleflight. Ahora puedes utilizar esta biblioteca en tu sistema distribuido para cachear los resultados de ejecución de solicitudes y mejorar el rendimiento de tu aplicación.

✨ Revisar Solución y Practicar

Resumen

¡Felicitaciones! Has completado este proyecto. Puedes practicar más laboratorios en LabEx para mejorar tus habilidades.