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)
    ...
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥30 关于用python写支付宝扫码付异步通知收不到的问题
  • ¥50 vue组件中无法正确接收并处理axios请求
  • ¥15 隐藏系统界面pdf的打印、下载按钮
  • ¥15 MATLAB联合adams仿真卡死如何解决(代码模型无问题)
  • ¥15 基于pso参数优化的LightGBM分类模型
  • ¥15 安装Paddleocr时报错无法解决
  • ¥15 python中transformers可以正常下载,但是没有办法使用pipeline
  • ¥50 分布式追踪trace异常问题
  • ¥15 人在外地出差,速帮一点点
  • ¥15 如何使用canvas在图片上进行如下的标注,以下代码不起作用,如何修改