doujiurong7210 2016-08-31 08:46
浏览 33
已采纳

Redigo:在Apache负载测试中出现错误

I am connecting my go program to redis using library redigo. When i run one request I get correct results. But on load testing, using apache benchmark tool, It works when:

ab -n 1000 -k -c 10 -p post.txt -T application/x-www-form-urlencoded http://localhost:8084/abcd

However when request is:

ab -n 1000 -k -c 15 -p post.txt -T application/x-www-form-urlencoded http://localhost:8084/abcd

I am getting error:

panic: dial tcp :6379: too many open files

This is my code:

func newPool() *redis.Pool {
    return &redis.Pool{
        MaxIdle: 80, // max number of connections
        Dial: func() (redis.Conn, error) {
            c, err := redis.Dial("tcp", ":6379")
            if err != nil {
                panic(err.Error())
            }
            return c, err
        },
        // If Wait is true and the pool is at the MaxActive limit, then Get() waits
        // for a connection to be returned to the pool before returning
        Wait: true,
    }
}

var pool = newPool()

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

func func1(pool *redis.Pool, id int) string {
    c := pool.Get()
    defer c.Close()
    m, err := redis.String(c.Do("HGET", "key", id))
    checkError(err)
    return m
}

func func2(pool *redis.Pool, string_ids []string) chan string {
    c := make(chan string)
    var ids []int
    var temp int
    for _, v := range string_ids {
        temp, _ = strconv.Atoi(v)
        ids = append(ids, temp)
    }
    go func() {
        var wg sync.WaitGroup
        wg.Add(len(ids))
        for _, v := range ids {
            go func(id int) {
                defer wg.Done()
                c <- func1(pool, id)
            }(v)
        }
        wg.Wait()
        close(c)
    }()
    return c
}
func getReq(w http.ResponseWriter, req *http.Request) {
    err := req.ParseForm()
    checkError(err)
    ids := req.Form["ids[]"]
    for v := range func2(pool, ids) {
        fmt.Println(v)
    }
}

func main() {
    http.HandleFunc("/abcd", getReq)

    log.Fatal(http.ListenAndServe(":8084", nil))
}

How to handle atleast 40 concurrent request using apache benchmark tool.

Note: I haven't changed anything in my redis conf file

I am getting following response when running apache benchmark tool. Only 15 request are completed.

$ ab -n 1000 -k -c 15 -p post.txt -T application/x-www-form-urlencoded http://localhost:8084/abcd
This is ApacheBench, Version 2.3 <$Revision: 1528965 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
apr_socket_recv: Connection refused (111)
Total of 15 requests completed
  • 写回答

1条回答 默认 最新

  • dongxin5429 2016-08-31 13:21
    关注

    To fix the issue immediately, set MaxActive on your redis.Pool, which you mention in the comments but don't set yourself.

    Fundamentally though, you should not be dispatching goroutines for every id lookup. Your maximum possible concurrency would then be (number of client connections) x (number of ids in the request), each of which can open a new redis connection. It would be far faster and more efficient to have a single redis connection read each of the ids serially. There's no need for any of the extra concurrency you have here, do it all serially from the handler, and don't convert the strings to ints when redis only operates on string keys to begin with.

    func getReq(w http.ResponseWriter, req *http.Request) {
        err := req.ParseForm()
        checkError(err)
    
        c := pool.Get()
        defer c.Close()
    
        for _, id := range req.Form["ids[]"] {
            m, err := redis.String(c.Do("HGET", "key", id))
            checkError(err)
            fmt.Println(id)
        }
    }
    

    If you want to optimize this further, you can use pipelines to reduce the round trips to the redis server.

    for _, id := range req.Form["ids[]"] {
        c.Send("HGET", "key", id))
    }
    c.Flush()
    values, err := redis.Strings(c.Receive())
    checkError(err)
    ...
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器