dongyan5141 2018-05-17 15:47
浏览 51

Golang和Apache AB

I have a system with HTTP POST requests and it runs with Spring 5 (standalone tomcat). In short it looks like this:

client (Apache AB) ----> micro service (java or golang) --> RabbitMQ --> Core(spring + tomcat).

The thing is, when I use my Java (Spring) service, it is ok. AB shows this output:

ab -n 1000 -k -s 2 -c 10 -s 60 -p test2.sh -A 113:113 -T 'application/json' https://127.0.0.1:8449/SecureChat/chat/v1/rest-message/send 
This is ApacheBench, Version 2.3 <$Revision: 1807734 $> 
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient)
Completed 100 requests
...
Completed 1000 requests
Finished 1000 requests


Server Software:        
Server Hostname:        127.0.0.1
Server Port:            8449
SSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256

Document Path:          /rest-message/send
Document Length:        39 bytes

Concurrency Level:      10
Time taken for tests:   434.853 seconds
Complete requests:      1000
Failed requests:        0
Keep-Alive requests:    0
Total transferred:      498000 bytes
Total body sent:        393000
HTML transferred:       39000 bytes
Requests per second:    2.30 [#/sec] (mean)
Time per request:       4348.528 [ms] (mean)
Time per request:       434.853 [ms] (mean, across all concurrent 
requests)
Transfer rate:          1.12 [Kbytes/sec] received
                    0.88 kb/s sent
                    2.00 kb/s total

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        4   14   7.6     17      53
Processing:  1110 4317 437.2   4285    8383
Waiting:     1107 4314 437.2   4282    8377
Total:       1126 4332 436.8   4300    8403

That is through TLS.

But when I try to use my Golang service I get timeout:

Benchmarking 127.0.0.1 (be patient)...apr_pollset_poll: The timeout specified has expired (70007)
Total of 92 requests completed

And this output:

ab -n 100 -k -s 2 -c 10 -s 60 -p test2.sh -T 'application/json' http://127.0.0.1:8089/
This is ApacheBench, Version 2.3 <$Revision: 1807734 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient)...^C

Server Software:        
Server Hostname:        127.0.0.1
Server Port:            8089

Document Path:          /
Document Length:        39 bytes

Concurrency Level:      10
Time taken for tests:   145.734 seconds
Complete requests:      92
Failed requests:        1
   (Connect: 0, Receive: 0, Length: 1, Exceptions: 0)
Keep-Alive requests:    91
Total transferred:      16380 bytes
Total body sent:        32200
HTML transferred:       3549 bytes
Requests per second:    0.63 [#/sec] (mean)
Time per request:       15840.663 [ms] (mean)
Time per request:       1584.066 [ms] (mean, across all concurrent requests)
Transfer rate:          0.11 [Kbytes/sec] received
                        0.22 kb/s sent
                        0.33 kb/s total

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:  1229 1494 1955.9   1262   20000
Waiting:     1229 1291 143.8   1262    2212
Total:       1229 1494 1955.9   1262   20000

That is through plane tcp.

I guess I have some mistakes in my code. I made it in one file

func initAmqp(rabbitUrl string) {
    var err error
    conn, err = amqp.Dial(rabbitUrl)
    failOnError(err, "Failed to connect to RabbitMQ")
}

func main() {
    err := gcfg.ReadFileInto(&cfg, "config.gcfg")
    if err != nil {
        log.Fatal(err);
    }

    PrintConfig(cfg)

    if cfg.Section_rabbit.RabbitUrl != "" {
        initAmqp(cfg.Section_rabbit.RabbitUrl);
    }

    mux := http.NewServeMux();
    mux.Handle("/", NewLimitHandler(1000, newTestHandler()))
    server := http.Server {
        Addr:   cfg.Section_basic.Port,
        Handler:    mux,
        ReadTimeout: 20 * time.Second,
        WriteTimeout: 20 * time.Second,
    }

    defer conn.Close();
    log.Println(server.ListenAndServe());
}

func NewLimitHandler(maxConns int, handler http.Handler) http.Handler {
    h := &limitHandler{
        connc:   make(chan struct{}, maxConns),
        handler: handler,
    }
    for i := 0; i < maxConns; i++ {
        h.connc <- struct{}{}
    }
    return h
}

func newTestHandler() http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        handler(w, r);
    })
}

func handler(w http.ResponseWriter, r *http.Request) {
    if b, err := ioutil.ReadAll(r.Body); err == nil {

        fmt.Println("message is ", string(b));
        res := publishMessages(string(b))

        w.Write([]byte(res))
        w.WriteHeader(http.StatusOK)
        counter ++;
    }else {
        w.WriteHeader(http.StatusInternalServerError)
        w.Write([]byte("500 - Something bad happened!"))
    }
}

func publishMessages(payload string) string {
    ch, err := conn.Channel()
    failOnError(err, "Failed to open a channel")

    q, err = ch.QueueDeclare(
        "",    // name
        false, // durable
        false, // delete when unused
        true,  // exclusive
        false, // noWait
        nil,   // arguments
    )

    failOnError(err, "Failed to declare a queue")

    msgs, err := ch.Consume(
        q.Name, // queue
        "",     // consumer
        true,   // auto-ack
        false,  // exclusive
        false,  // no-local
        false,  // no-wait
        nil,    // args
    )
    failOnError(err, "Failed to register a consumer")

    corrId := randomString(32)

    log.Println("corrId ", corrId)

    err = ch.Publish(
        "",                 // exchange
        cfg.Section_rabbit.RabbitQeue,      // routing key
        false,              // mandatory
        false,              // immediate
        amqp.Publishing{
            DeliveryMode: amqp.Transient,
            ContentType:  "application/json",
            CorrelationId: corrId,
            Body:         []byte(payload),
            Timestamp:    time.Now(),
            ReplyTo:       q.Name,
        })

    failOnError(err, "Failed to Publish on RabbitMQ")

    defer ch.Close();

    result :=  "";
    for d := range msgs {
        if corrId == d.CorrelationId {
            failOnError(err, "Failed to convert body to integer")

            log.Println("result = ", string(d.Body))

            return string(d.Body);

         }else {
            log.Println("waiting for result = ")
        }
    }

    return result;
}

Can someone help?

EDIT here are my variables

type limitHandler struct {
    connc   chan struct{}
    handler http.Handler
}

var conn *amqp.Connection
var q amqp.Queue

EDIT 2

func (h *limitHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    select {
    case <-h.connc:


        fmt.Println("ServeHTTP");


        h.handler.ServeHTTP(w, req)

        h.connc <- struct{}{}
    default:
        http.Error(w, "503 too busy", http.StatusServiceUnavailable)
    }
}

EDIT 3

func failOnError(err error, msg string) {
    if err != nil {
        log.Fatalf("%s: %s", msg, err)
        panic(fmt.Sprintf("%s: %s", msg, err))
    }
}
  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 用stata实现聚类的代码
    • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
    • ¥170 如图所示配置eNSP
    • ¥20 docker里部署springboot项目,访问不到扬声器
    • ¥15 netty整合springboot之后自动重连失效
    • ¥15 悬赏!微信开发者工具报错,求帮改
    • ¥20 wireshark抓不到vlan
    • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
    • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
    • ¥15 stata安慰剂检验作图但是真实值不出现在图上