Nginx (как прокси-сервер revser) не уведомляет gin-goni c (как веб-сервер), когда клиент отменяет соединение - PullRequest
7 голосов
/ 05 февраля 2020

На веб-сайте, который использует gin-gonic в качестве веб-сервера и nginx в качестве прокси-сервера, клиенты отправляют свои данные на сервер через открытые API-интерфейсы gin-conic, и для отправки серверных команд клиентам каждый (т. Е. Клиент) имеет подключение к веб-серверу, на котором он хранится в течение длительного времени (т.е. он не истекает в течение нескольких часов) и заполнить тело ответа желаемой командой (для двунаправленного подключения мы можем использовать ws вместо этого).

Проблема в том, что нам нужно понять, сбросил ли клиент / отменил соединение с сервером. Чтобы понять, что у нас есть эта строка case <-c.Request.Context().Done(): в следующем коде.

func MakeConnection(c *gin.Context) {
// ... code
select {
case notification = <-clientModel.Channels[token]:// we have a command to send to user
    log.Info("Notification")
    err = nil
case <-c.Request.Context().Done(): // connection dropped by client
    log.Info("Cancel")
    err = c.Err()
case <-ctx.Done(): // time elapsed and there was no command to send to client
    log.Info("timeout")
    err = errors.New("timeout exceeded")
}
// ... code
}

Все работает хорошо (если мы установим такое соединение с сервером и отменим его через произвольное время, немедленно Cancel отображается в терминале), пока не увеличится количество клиентов. Приблизительно для 5 клиентов это работает должным образом, но для более чем 10 клиентов (больше нагрузки), хотя ngixn регистрирует отмену в своем журнале доступа (как код ошибки 499), но веб-сервер (то есть gin-gonic) не уведомляет.

PS: nginx конфигурация

`

server {
    # SSL configuration
    listen 443 ssl http2 so_keepalive=10:150:1;
    listen [::]:443 ssl http2 so_keepalive=10:150:1;
    include /etc/nginx/snippets/self-signed.conf;
    include /etc/nginx/snippets/ssl-params.conf;

    root /var/www/project;
    autoindex off;

    location / {
        try_files $uri $uri/ @proxy;
    }

    location ~ /v1/v/[0-9a-zA-Z]+/notification {
        proxy_connect_timeout       86460;
        proxy_send_timeout          86460;
        proxy_read_timeout          86460;
        send_timeout                86460;
        proxy_pass                  http://example_host:8002;
    }
}

`

`user nginx; worker_processes auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
    use epoll;
    multi_accept on;
}

http {
    limit_req_zone $binary_remote_addr zone=req_zone:200m rate=10r/s;
    limit_req_zone $request_uri zone=search_limit:100m rate=5r/s;
    limit_req_zone $binary_remote_addr zone=login_limit:100m rate=20r/m;
    vhost_traffic_status_zone;
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  on;
    gzip_types  text/html text/css text/javascript text/xml text/plain
                image/x-icon image/svg+xml 
                application/rss+xml application/javascript application/x-javascript 
                application/xml application/xhtml+xml 
                application/x-font application/x-font-truetype application/x-font-ttf application/x-font-otf application/x-font-opentype application/vnd.ms-fontobject font/ttf font/otf font/opentype
                font/woff font/ttf
                application/octet-stream;
    gzip_vary on;

    include /etc/nginx/conf.d/*.conf;
}

`

...