2016-11-28 2 views
0

Я фактически использую пакет gorilla для размещения моего сервера веб-сервера в golang. Если я оставлю свой сервер, у меня есть эта ошибка каждые 10 дней или около того.слишком много ошибок открытых файлов с сервером websocket в golang

2016/11/28 19:22:49 http: Accept error: accept tcp [::]:9001: accept4: too many open files; retrying in 1s 
2016/11/28 19:22:50 http: Accept error: accept tcp [::]:9001: accept4: too many open files; retrying in 1s 
2016/11/28 19:22:51 http: Accept error: accept tcp [::]:9001: accept4: too many open files; retrying in 1s 
2016/11/28 19:22:52 http: Accept error: accept tcp [::]:9001: accept4: too many open files; retrying in 1s 
2016/11/28 19:22:53 http: Accept error: accept tcp [::]:9001: accept4: too many open files; retrying in 1s 
2016/11/28 19:22:54 http: Accept error: accept tcp [::]:9001: accept4: too many open files; retrying in 1s 

это мой код:

func websocketHandler(writer http.ResponseWriter, request *http.Request){ 
    var socket *websocket.Conn 
    user := new(user.User) 
    user.Token = getParamURI(request.URL.RequestURI(), "token") 

    if user.GetUserByToken() == false { 

     errors := api.Error{} 
     socket.Close() 
     errors.ListErrors = append(errors.ListErrors, "Session doesn't exist") 
     writer.Header().Set("Content-Type", "application/json") 
     writer.WriteHeader(http.StatusNotAcceptable) 
     json.NewEncoder(writer).Encode(errors) 
     return 

    } 

    socket, _ = upgrader.Upgrade(writer, request, nil) 

    err := make(chan string) 

    go pingSocket(socket, err) 
    go handleChangeNotification(socket, user.Id, err) 
    go handleChangeMessage(socket, user.Id, err) 
    for { 
     tmp := <- err 
     if len(tmp) > 0 { 
      break 
     } 
    } 
    socket.Close() 
} 

моя конфигурация ULIMIT:

core file size   (blocks, -c) 0 
data seg size   (kbytes, -d) unlimited 
scheduling priority    (-e) 0 
file size    (blocks, -f) unlimited 
pending signals     (-i) 7902 
max locked memory  (kbytes, -l) 64 
max memory size   (kbytes, -m) unlimited 
open files      (-n) 1024 
pipe size   (512 bytes, -p) 8 
POSIX message queues  (bytes, -q) 819200 
real-time priority    (-r) 0 
stack size    (kbytes, -s) 8192 
cpu time    (seconds, -t) unlimited 
max user processes    (-u) 7902 
virtual memory   (kbytes, -v) unlimited 
file locks      (-x) unlimited 

ошибка довольно непонятное, я не понимаю, потому что я хорошо закрыть сокет в случае разрыва или ошибки, а сервер находится в производстве, но в бета-тесте с 4-5 пользователями, поэтому это не о лимите.

Может ли кто-нибудь сказать мне, откуда исходит ошибка?

+0

Вы уверены, что 'websocketHandler' возвращается во всех случаях? Каковы дескрипторы файлов, открытые вашей программой? Что показывает трассировка стека, которую программа выполняет с файловыми дескрипторами? – JimB

+0

Показать код, который считывается из сокета и код, отправляемый каналу err. –

+1

Запустите 'netstat', чтобы просмотреть открытые сетевые подключения, если проблема в другом месте (например, открытие и закрытие соединений с базой данных). –

ответ

1

Если вы закрыли все считыватели и рассмотрели все другие возможные причины, это может быть проблема ulimit, если у вас есть движение по высоте. Но обычно вы можете увеличить это, даже если вы не являетесь пользователем root, поскольку существуют два типа ограничений, т. Е. Ограничение. максимальный и мягкий предел. Вы можете проверить их обоих в Linux с помощью:

# ulimit -Sn

# ulimit -Hn

Если мягкий предел (Sn) ниже, чем жесткий предел (Hn) (по умолчанию или установить администратором), вы можете сделать это выше до жесткого предела. На всех моих установках CentOS, поскольку я могу видеть, что по умолчанию 1024 для Sn и 4096 для Hn, так что вы можете легко максимизировать Sn до 4096, ни один пользователь root.

Эта функция позволит максимально увеличить количество открытых файлов, если это возможно. Скопируйте/вставьте и вызовите maxOpenFile() в начале основной функции и посмотрите, помогает ли она.

import "syscall" 

func maxOpenFiles() { 
    var rLimit syscall.Rlimit 

    err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit) 
    if err != nil { 
     log.Println("Error Getting Rlimit ", err) 
    } 

    if rLimit.Cur < rLimit.Max { 
     rLimit.Cur = rLimit.Max 
     err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit) 
     if err != nil { 
      log.Println("Error Setting Rlimit ", err) 
     } 
    } 
} 

Код прост, сначала мы считываем текущие настройки для количества файлов, а если Cur меньше Max, мы его максимально. Этот func устанавливает ограничения на файлы только для текущего процесса app/linux.

Смежные вопросы