На веб-сайте, который использует 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;
}
`