我的任务是创建一个反向代理应用程序,它从请求/响应主体中提取一些特定信息并将其发送到logstash。所以我决定先做一些负载测试。我编写了非常简单的后端Web服务器和基本代理。
后端服务器代码:
package main
import "net/http"
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":3001", nil)
}
func handler(w http.ResponseWriter, r *http.Request) {
r.Body.Close()
w.Write([]byte("test"))
}
反向代理服务器代码:
package main
import (
"net/http"
"net/http/httputil"
"net/url"
)
var (
proxy *httputil.ReverseProxy
)
func init() {
url, _ := url.Parse("http://localhost:3001")
proxy = httputil.NewSingleHostReverseProxy(url)
proxy.Transport = &mimTransport{}
}
func main() {
http.ListenAndServe(":3000", proxy)
}
func handler(w http.ResponseWriter, r *http.Request) {
r.Host = "localhost:3001"
proxy.ServeHTTP(w, r)
}
type mimTransport struct {
}
func (t *mimTransport) RoundTrip(request *http.Request) (*http.Response, error) {
response, err := http.DefaultTransport.RoundTrip(request)
if response != nil {
defer request.Body.Close()
}
// info extraction will be here
return response, err
}
正如您可以看到后端服务器正在监听localhost:3001
和代理监听localhost:3000
我正在使用apache基准进行负载测试。
当我在12k-14k左右运行$ ab -c 20 -n 20000 -s 10 http://127.0.0.1:3000/
时,请求代理开始写错误,如:
2016/12/23 13:02:50 http: proxy error: read tcp [::1]:58330->[::1]:3001: read: connection reset by peer
2016/12/23 13:02:50 http: proxy error: read tcp [::1]:58461->[::1]:3001: read: connection reset by peer
2016/12/23 13:02:50 http: proxy error: read tcp [::1]:58977->[::1]:3001: read: connection reset by peer
2016/12/23 13:02:50 http: proxy error: read tcp [::1]:59459->[::1]:3001: read: connection reset by peer
...
不久之后,apache替补席因超时而死。一些替补结果:
Benchmarking 127.0.0.1 (be patient)
Completed 2000 requests
Completed 4000 requests
Completed 6000 requests
Completed 8000 requests
Completed 10000 requests
^C
Server Software:
Server Hostname: 127.0.0.1
Server Port: 3000
Document Path: /
Document Length: 4 bytes
Concurrency Level: 20
Time taken for tests: 4.868 seconds
Complete requests: 11514
Failed requests: 22
(Connect: 0, Receive: 0, Length: 22, Exceptions: 0)
Non-2xx responses: 22
Total transferred: 1381790 bytes
HTML transferred: 45968 bytes
Requests per second: 2365.28 [#/sec] (mean)
Time per request: 8.456 [ms] (mean)
Time per request: 0.423 [ms] (mean, across all concurrent requests)
Transfer rate: 277.20 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 4.2 1 111
Processing: 0 3 4.8 3 113
Waiting: 0 3 4.7 3 113
Total: 0 4 6.4 4 116
Percentage of the requests served within a certain time (ms)
50% 4
66% 4
75% 5
80% 5
90% 5
95% 6
98% 6
99% 7
100% 116 (longest request)
还有更多,如果我在第一次测试结束后再次启动ab
,我会收到类似的内容:
Benchmarking 127.0.0.1 (be patient)
apr_pollset_poll: The timeout specified has expired (70007)
Total of 52 requests completed
(也许以前测试中的一些连接还活着)
互联网上说Go中有一些DoS保护机制,显然它是重置连接的原因。 所以我的问题是:感谢。