Golang:存储/缓存要在以下http请求中提供的值

时间:2013-08-28 12:28:32

标签: http caching go global-variables

我正在编写一些Go webservices(也使用http.ListenAndServe在Go中实现Web服务器)。 我有一个结构图,我想保留在内存中(大约数据大小为100Kb),供不同的http请求使用。

在Go中实现这一目标的最佳方法是什么? 根据您的经验,使用全局包变量或缓存系统(如memcache / groupcache)是否更好?

3 个答案:

答案 0 :(得分:12)

除了您已收到的答案之外,请考虑使用接收方式method valueshttp.HandlerFunc

如果您的数据是在流程开始之前加载的数据,您可以使用以下内容:

type Common struct {
    Data map[string]*Data
}

func NewCommon() (*Common, error) {
    // load data
    return c, err
}

func (c *Common) Root(w http.ResponseWriter, r *http.Request) {
    // handler
}

func (c *Common) Page(w http.ResponseWriter, r *http.Request) {
    // handler
}

func main() {
    common, err := NewCommon()
    if err != nil { ... }

    http.HandleFunc("/", common.Root)
    http.HandleFunc("/page", common.Page)

    http.ListenAndServe(...)
}

如果所有Common数据都是只读的,这很有效。如果{/ 1}}数据是可读/写的,那么您将需要更多类似的内容:

Common

其余部分基本相同,除了不通过接收者的字段直接访问数据,您可以通过getter和setter访问它们。在正在读取大部分数据的Web服务器中,您可能需要RWMutex,以便可以彼此同时执行读取。第二种方法的另一个优点是您已经封装了数据,因此如果您的应用程序需要增加,您可以在将来添加透明写入和/或读取内存缓存或组缓存或其他类似内容。< / p>

我真的喜欢将处理程序定义为对象上的方法,因为它可以更轻松地对它们进行单元测试:您可以轻松定义包含所需值的table driven test并输出您期待而不必捣乱全局变量。

答案 1 :(得分:3)

仍然可以解决问题的简单解决方案通常是正确的方法。在服务器本地缓存数据既简单又高效,即使使用更丰富的系统,也可以在许多情况下完成。

作为一个例子,上个月我实施了快速黑客攻击(http://ubuntu-edge.info)由于围绕众筹活动传播的新闻而受到一些负担,并且Go流程的负载非常低时间,在一台小型EC2机器上。数据很简单,只是缓存在内存中,每分钟从外部进程更新的数据库刷新一次。

我一般看看memcache(现在是groupcache),自己这样做会意味着复制更多的功能。例如,当要在内存中保留太多数据时,或丢失服务器可能会影响整个系统的性能,因为缓存的数据一下子全部消失,或者因为性能受到争用的影响。

作为旁注,groupcache实际上是一个库,因此您可以将其嵌入到服务器中,而不是作为一个实际的外部系统。

答案 2 :(得分:2)

不要沉迷于过早的优化。定义Go包API以封装数据,然后您可以随时更改实现。例如,只是涂鸦,

package data

type Key struct {
    // . . .
}

type Data struct {
    // . . .
}

var dataMap map[Key]Data

func init() {
    dataMap = make(map[Key]Data)
}

func GetData(key Key) (*Data, error) {
    data := dataMap[key]
    return &data, nil
}