Golang에 Memcached 캐시 사용

과거에 나는 응용 프로그램의 데이터를 캐시하는 방법과 외부 자원(예를 들어)을 사용하여 캐시하는 방법을 가르쳐 왔다.
오늘 프로그램의 생각은 JSONPlaceholder API에 요청을 보내는 것입니다. 매개 변수에 제공된 id에 따라 사진 한 장을 얻을 것입니다.
Express를 사용한 적이 있다면, 제가 사용할 프레임워크는 Fiber입니다.과거 js나 비슷한 프레임워크에서 저희 Api를 만드는 것이 편할 것입니다.
본고에서 제가Memcached 클라이언트로 사용할 라이브러리는 gomemcache입니다. 왜냐하면 이 라이브러리의 설정과 사용은 매우 간단하기 때문입니다.

저희가 인코딩을 해볼게요.
먼저 다음 패키지를 설치합니다.
go get github.com/gofiber/fiber/v2
go get github.com/bradfitz/gomemcache/memcache
그런 다음 간단한 API를 만듭니다.
package main

import "github.com/gofiber/fiber/v2"

func main() {
    app := fiber.New()

    app.Get("/", func(c *fiber.Ctx) error {
        return c.SendString("I hope it runs 😅")
    })

    app.Listen(":3000")
}
API를 실행하려면 다음 명령을 사용합니다.
go run .
Api를 테스트하는 경우 응답 본문에서 I hope it runs 😅 메시지가 표시됩니다.
이제 사진 한 장을 얻으려면 응답하는 주체에 다음과 같은 json을 포함합니다.
{
  "albumId": 1,
  "id": 1,
  "title": "accusamus beatae ad facilis cum similique qui sunt",
  "url": "https://via.placeholder.com/600/92c952",
  "thumbnailUrl": "https://via.placeholder.com/150/92c952"
}
이제 Photo라는 구조를 만들어야 하지만 먼저 utils.go라는 파일을 만듭니다.구조에는 다음 필드가 포함됩니다.
// @utils.go

package main

type Photo struct {
    AlbumID      int    `json:"albumId"`
    ID           int    `json:"id"`
    Title        string `json:"title"`
    URL          string `json:"url"`
    ThumbnailURL string `json:"thumbnailUrl"`
}
이런 방식을 통해 우리는 단점에 대해 약간의 변경을 할 수 있다. 우선 우리는 id 파라미터를 추가할 것이다.그리고 우리는 c.Params() 함수를 사용하여 그 값을 얻을 것이다.
app.Get("/:id", func(c *fiber.Ctx) error {
    id := c.Params("id")
    // ...
})
현재, 우리는 매개 변수에서 전달된 id 에 따라 http 요청을 보내서 사진 한 장을 얻을 것입니다.우리는 그 사진을 너에게 돌려줄 것이다.
app.Get("/:id", func(c *fiber.Ctx) error {
    id := c.Params("id")
    res, err := http.Get("https://jsonplaceholder.typicode.com/photos/" + id)
    if err != nil {
        return err
    }

    defer res.Body.Close()
    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        return err
    }

    photo := Photo{}
    parseErr := json.Unmarshal(body, &photo)
    if parseErr != nil {
        return parseErr
    }

    return c.JSON(fiber.Map{"Data": photo})
})
현재 Api를 테스트할 때 id 파라미터를 지적하는 것을 잊지 마십시오. 저희는 해당하는 사진에서 데이터를 얻을 것입니다.그러나 JSONPlaceholder API에서 데이터를 직접 받는 경우가 많습니다.
우리가 원하는 것은 사진 데이터를 캐시에 일정 시간 보존하는 것이다. 이 기간 동안 우리가 받아야 할 데이터는 반드시 캐시에서 나와야 한다.
우선 utils.go 파일로 돌아가서 toJson()라는 함수를 만듭니다. 이 함수는 버퍼를 매개 변수로 하고 사진의 json을 되돌려줍니다.
// @utils.go

package main

import "encoding/json"

type Photo struct {
    AlbumID      int    `json:"albumId"`
    ID           int    `json:"id"`
    Title        string `json:"title"`
    URL          string `json:"url"`
    ThumbnailURL string `json:"thumbnailUrl"`
}

func toJson(val []byte) Photo {
    photo := Photo{}
    err := json.Unmarshal(val, &photo)
    if err != nil {
        panic(err)
    }
    return photo
}
이제 gomemcache 라이브러리를 가져와Memcached 클라이언트를 만들 수 있습니다.이 예에서 우리는 호스트와 포트만 지적할 수 있다.
package main

import (
    "encoding/json"
    "io/ioutil"
    "net/http"

    "github.com/bradfitz/gomemcache/memcache"
    "github.com/gofiber/fiber/v2"
)

var cache = memcache.New("localhost:11211")

// ...
현재, 우리의 단점에서, 우리는 응답에서 데이터를 보내기 전에 응용 프로그램의 데이터를 캐시해야 한다.이를 위해 우리는 cache.Set() 함수를 사용하여 세 가지 속성을 포함하는 매개 변수를 전달할 것이다.
첫 번째는 키이고 이 예에서는 id이며 두 번째는 값이다. 이 예에서는 주체(응답 주체 버퍼)이고 마지막은 초 단위의 만료 시간이다. 나는 값을 10으로 설정했다.
app.Get("/:id", func(c *fiber.Ctx) error {
    // ...

    cacheErr := cache.Set(&memcache.Item{Key: id, Value: body, Expiration: 10})
    if cacheErr != nil {
        panic(cacheErr)
    }

    return c.JSON(fiber.Map{"Data": photo})
})
단점에서, 우리는 여전히 json.Unmarshal() 의 논리를 삭제하고, 우리가 만든 toJson() 함수로 그것을 대체해야 한다.
이를 위해 답안의 주체를 함수의 유일한 매개 변수로 전달하고 Api의 답안에서 함수 데이터를 되돌려줍니다.
app.Get("/:id", func(c *fiber.Ctx) error {
    // ...

    cacheErr := cache.Set(&memcache.Item{Key: id, Value: body, Expiration: 10})
    if cacheErr != nil {
        panic(cacheErr)
    }

    data := toJson(body)
    return c.JSON(fiber.Map{"Data": data})
})
현재 우리는 데이터를 캐시할 것이지만, 우리는 아직 완성하지 못했다. 왜냐하면 우리는 중간부품을 만들어야 하기 때문이다.
이 중간부품은 캐시에 키가 존재하는지 확인하는 것입니다. 키가 존재하면 캐시에 저장된 데이터를 되돌려줍니다.
그러나 캐시에 키가 존재하지 않으면 루트의 다음 방법을 실행할 것입니다. 이 예에서 http 요청을 실행할 것입니다.
func verifyCache(c *fiber.Ctx) error {
    // ...
}
우선 우리는 id 매개 변수의 값을 얻어야 한다.그리고 우리는 cache.Get() 을 사용할 것입니다. 이것은 하나의 인자만 필요합니다. 이것은 키입니다. 우리는 id를 그에게 전달할 것입니다.
func verifyCache(c *fiber.Ctx) error {
    id := c.Params("id")
    val, err := cache.Get(id)
    // ...
}
키가 존재하지 않으면 c.Next() 함수를 사용하여 http 요청을 계속 수행할 것입니다.
func verifyCache(c *fiber.Ctx) error {
    id := c.Params("id")
    val, err := cache.Get(id)
    if err != nil {
        return c.Next()
    }

    // ...
}
그렇지 않으면, 우리는 다시 toJson() 함수를 사용하여 버퍼를 json으로 변환하고 그것을 되돌려줍니다.
func verifyCache(c *fiber.Ctx) error {
    id := c.Params("id")
    val, err := cache.Get(id)
    if err != nil {
        return c.Next()
    }

    data := toJson(val.Value)
    return c.JSON(fiber.Map{"Cached": data})
}
마지막으로 가장 중요하지 않은 것은 우리가 우리의 노선에 중간부품을 추가해야 한다는 것이다. 아래와 같다.
app.Get("/:id", verifyCache, func(c *fiber.Ctx) error {
    // ...
})
최종 코드는 다음과 같습니다.
package main

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

    "github.com/bradfitz/gomemcache/memcache"
    "github.com/gofiber/fiber/v2"
)

var cache = memcache.New("localhost:11211")

func verifyCache(c *fiber.Ctx) error {
    id := c.Params("id")
    val, err := cache.Get(id)
    if err != nil {
        return c.Next()
    }

    data := toJson(val.Value)
    return c.JSON(fiber.Map{"Cached": data})
}

func main() {
    app := fiber.New()

    app.Get("/:id", verifyCache, func(c *fiber.Ctx) error {
        id := c.Params("id")
        res, err := http.Get("https://jsonplaceholder.typicode.com/photos/" + id)
        if err != nil {
            panic(err)
        }

        defer res.Body.Close()
        body, err := ioutil.ReadAll(res.Body)
        if err != nil {
            panic(err)
        }

        cacheErr := cache.Set(&memcache.Item{Key: id, Value: body, Expiration: 10})
        if cacheErr != nil {
            panic(cacheErr)
        }

        data := toJson(body)
        return c.JSON(fiber.Map{"Data": data})
    })

    app.Listen(":3000")
}
현재, 만약 우리가 응용 프로그램의 성능을 테스트하려고 한다면, 우리는 그것의 성능이 매우 다르다는 것을 알아차릴 수 있을 것이다.캐시를 사용하지 않는 경우 요청마다 평균 시간327ms이 걸리고 캐시를 실현한 후 요청마다 평균 시간6ms이 걸린다.

결론
여느 때와 마찬가지로, 나는 네가 이것이 매우 재미있다고 느끼기를 바란다.만약 본문의 어떤 잘못도 주의한다면, 평론에서 언급하십시오.😁
위대한 하루 되세요!🤙

좋은 웹페이지 즐겨찾기