go version)?go1.11.1
Yes
go env)?The error too many open files is being thrown by submitting 20 requests per second in the code below.
The limit of open files on my system is 256 ( ulimit -n ).
Using lsof -p
If the OS open files limit is incremented the problem just is postponed. And I think that increment is not the solution.
package main
import (
"log"
"net/http"
"golang.org/x/crypto/bcrypt"
)
func main() {
srv := &http.Server{
Addr: ":9000",
}
http.HandleFunc("/auth", func(w http.ResponseWriter, r *http.Request) {
log.Printf("/auth")
if err := bcrypt.CompareHashAndPassword([]byte("$2y$10$MWTmFsLIM3jHVNiDDZH/U.qkpebJ/z02phdclx9rEcz5B7/cbujcy"), []byte("test")); err != nil {
log.Printf("Error on check key and secret. (%v)", err.Error())
w.WriteHeader(http.StatusUnauthorized)
return
}
w.WriteHeader(http.StatusOK)
})
log.Printf("Listening on port 9000")
log.Fatal(srv.ListenAndServe())
}
The FD be released and not throw too many open files error.
http: Accept error: accept tcp [::]:9000: accept: too many open files.
If your server can't do 20 qps because its CPU is busy with, say, bcrypt but your load testing tool (which? you don't say.) keeps generating new connections, I would expect it to fail like this.
I'm not sure there's anything to do here.
I am using the artillery to run the tests:
artillery quick -d 60 -r 20 http://localhost:9000/auth
Well, the load testing tool has taught you something: you now know what your server can't do. Binary search on the -r value a bit and find the server's limit.
What do you want me to do with this bug?
caddy suggests to up the ulimit on fd's for production use. It seems to me like an OS config issue and not a bug in Go or it's std lib
Hi @ecavalcanti .
You should:
cat /proc/sys/fs/file-max.net/http server.The solution should look like this:
package main
import (
"log"
"net/http"
"time"
"golang.org/x/crypto/bcrypt"
)
func main() {
srv := &http.Server{
Addr: ":9000",
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
srv.SetKeepAlivesEnabled(false)
http.HandleFunc("/auth", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Connection", "close")
defer r.Body.Close()
log.Printf("/auth")
if err := bcrypt.CompareHashAndPassword([]byte("$2y$10$MWTmFsLIM3jHVNiDDZH/U.qkpebJ/z02phdclx9rEcz5B7/cbujcy"), []byte("test")); err != nil {
log.Printf("Error on check key and secret. (%v)", err.Error())
w.WriteHeader(http.StatusUnauthorized)
return
}
w.WriteHeader(http.StatusOK)
})
log.Printf("Listening on port 9000")
log.Fatal(srv.ListenAndServe())
}
Most helpful comment
Hi @ecavalcanti .
You should:
cat /proc/sys/fs/file-max.net/httpserver.The solution should look like this: