为什么我的Hello World go服务器被ApacheBench粉碎? [英] Why is my Hello World go server getting crushed by ApacheBench?

查看:136
本文介绍了为什么我的Hello World go服务器被ApacheBench粉碎?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 主包

导入(
io
净/ http


func hello(w http.ResponseWriter,r * http.Request){
io.WriteString(w,Hello world!\\\

}

func main(){
http.HandleFunc(/,hello)
http.ListenAndServe(:8000,nil)
}

我有几个令人难以置信的基本HTTP服务器,并且他们都展示了这个问题。

  $ ab -c 1000 -n 10000 http://127.0.0.1:8000/ 
这是ApacheBench,版本2.3< $ Revision:1604373 $>
版权所有1996 Adam Twiss,Zeus Technology Ltd,http://www.zeustech.net/
授权给Apache软件基金会,http://www.apache.org/

基准127.0.0.1(耐心)
完成1000次请求
完成2000次请求
完成3000次请求
完成4000次请求
完成5000次请求
apr_socket_recv :连接被拒绝(61)
完成的5112个请求的总数

事情仍然没落。对我来说,这个问题似乎通常显示在5k-6k左右的标记:

  $ ab -c 10 -n 10000 http ://127.0.0.1:8000 / 
这是ApacheBench,版本2.3< $ Revision:1604373 $>
版权所有1996 Adam Twiss,Zeus Technology Ltd,http://www.zeustech.net/
授权给Apache软件基金会,http://www.apache.org/

基准127.0.0.1(耐心等待)
已完成1000次请求
已完成2000次请求
已完成3000次请求
已完成4000次请求
已完成5000次请求
已完成6000请求
apr_socket_recv:操作超时(60)
完成的6277个请求的总数



<事实上,你可以完全放弃并发,问题仍然存在(有时):

  $ ab -c 1  - n 10000 http://127.0.0.1:8000/ 
这是ApacheBench,版本2.3< $ Revision:1604373 $>
版权所有1996 Adam Twiss,Zeus Technology Ltd,http://www.zeustech.net/
授权给Apache软件基金会,http://www.apache.org/

基准127.0.0.1(耐心等待)
已完成1000次请求
已完成2000次请求
已完成3000次请求
已完成4000次请求
已完成5000次请求
已完成6000请求
apr_socket_recv:操作超时(60)
完成的6278个请求的总数



<我不禁想知道我是否在某种地方遇到某种操作系统限制?我会怎么说?我将如何缓解?

解决方案

总之,您的端口用完了。



osx上的默认临时端口范围为49152-65535,仅为16,383个端口。由于每个 ab 请求都是 http / 1.0 (在您的第一个示例中不存在keepalive),所以每个新请求都需要另一个端口。

使用每个端口时,它将被放入一个等待tcpMaximum Segment Lifetime的队列中,该值在osx上配置为15秒。因此,如果您在15秒内使用16,383个以上的端口,那么在进一步连接时,您将会受到操作系统的限制。根据首先从哪个进程耗尽端口,您将从服务器获取连接错误,或从 ab



<通过使用 http / 1.1 能力负载生成器(如 wrk ),或者使用keepalive( ab ,所以连接可以根据工具的并发设置重新使用。

$ b -k
$ b

现在,基准测试的服务器代码很少,因此负载生成器的收税量与服务器本身相同,本地操作系统和网络堆栈可能会做出很好的贡献。如果您想对一个http服务器进行基准测试,最好从多台不在同一台机器上运行的客户端做一些有意义的工作。


package main

import (
    "io"
    "net/http"
)

func hello(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "Hello world!\n")
}

func main() {
    http.HandleFunc("/", hello)
    http.ListenAndServe(":8000", nil)
}

I've got a couple of incredibly basic HTTP servers, and all of them are exhibiting this problem.

$ ab -c 1000 -n 10000 http://127.0.0.1:8000/
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
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 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
apr_socket_recv: Connection refused (61)
Total of 5112 requests completed

With a smaller concurrency value, things still fall over. For me, the issue seems to show up around the 5k-6k mark usually:

$ ab -c 10 -n 10000 http://127.0.0.1:8000/
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
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 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
apr_socket_recv: Operation timed out (60)
Total of 6277 requests completed

And in fact, you can drop concurrency entirely and the problem still (sometimes) happens:

$ ab -c 1 -n 10000 http://127.0.0.1:8000/
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
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 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
apr_socket_recv: Operation timed out (60)
Total of 6278 requests completed

I can't help but wonder if I'm hitting some kind of operating system limit somewhere? How would I tell? And how would I mitigate?

解决方案

In short, you're running out of ports.

The default ephemeral port range on osx is 49152-65535, which is only 16,383 ports. Since each ab request is http/1.0 (without keepalive in your first examples), each new request takes another port.

As each port is used, it get's put into a queue where it waits for the tcp "Maximum Segment Lifetime", which is configured to be 15 seconds on osx. So if you use more than 16,383 ports in 15 seconds, you're effectively going to get throttled by the OS on further connections. Depending on which process runs out of ports first, you will get connection errors from the server, or hangs from ab.

You can mitigate this by using an http/1.1 capable load generator like wrk, or using the keepalive (-k) option for ab, so that connections are reused based on the tool's concurrency settings.

Now, the server code you're benchmarking does so little, that the load generator is being taxed just as much as the sever itself, with the local os and network stack likely making a good contribution. If you want to benchmark an http server, it's better to do some meaningful work from multiple clients not running on the same machine.

这篇关于为什么我的Hello World go服务器被ApacheBench粉碎?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆