uwsgi --reload отказывается от входящих подключений

python tcp uwsgi

430 просмотра

2 ответа

1399 Репутация автора

Я пытаюсь настроить приложение, размещенное на uwsgi, таким образом, чтобы я получал изящные перезагрузки с помощью uwsgi --reload, но у меня явно не получается. Вот моя тестовая установка uwsgi:

[admin2-prod]
http = 127.0.0.1:9090
pyargv = $* --db=prod --base-path=/admin/
max-requests = 3
listen=1000
http-keepalive = 1
pidfile2 =admin.pid
add-header=Connection: keep-alive
workers = 1
master = true
chdir = .
plugins = python,http,router_static,router_uwsgi,router_http
buffer-size = 8192
pythonpath = admin2
file = admin2/app.py
static-map=/admin/static/=admin2/static/
static-map=/admin/v3/build/=admin2/client/build/
disable-logging = false
http-timeout = 100

(обратите внимание, что раньше я запускал sysctl net.core.somaxconn = 1000)

А вот мой тестовый скрипт на python:

import httplib

connection = httplib.HTTPConnection('127.0.0.1', 9090)
connection.connect()

for i in range(0, 1000):
    print 'sending... ', i
    try:
        connection.request('GET', '/x', '', {'Connection' : ' keep-alive'})
        response = connection.getresponse()
        d = response.read()
        print '    ', response.status
    except:
        connection = httplib.HTTPConnection('127.0.0.1', 9090)
        connection.connect()

Приведенный выше сбой клиента во время --reload:

sending...  920
Traceback (most recent call last):
  File "./test.py", line 15, in <module>
    connection.connect()
  File "/usr/lib64/python2.7/httplib.py", line 836, in connect
    self.timeout, self.source_address)
  File "/usr/lib64/python2.7/socket.py", line 575, in create_connection
    raise err
socket.error: [Errno 111] Connection refused

Из tcpdump похоже, что uwsgi действительно принимает второй входящий TCP-запрос, который происходит после --reload, клиент отправляет GET, сервер TCP ACKing его, но сервер наконец-то RSTed сервером перед отправкой обратно HTTP ответ. Итак, чего мне не хватает, чтобы сервер поставил в очередь это входящее соединение, пока он не будет готов обработать его и получить по-настоящему изящную перезагрузку?

Автор: mathieu Источник Размещён: 13.07.2016 10:51

Ответы (2)


0 плюса

17116 Репутация автора

Ваши исключения случаются, когда процесс uwsgi не может принимать соединения, очевидно ... Итак, ваш процесс должен ждать, пока сервер не будет перезагружен - вы можете использовать цикл с таймаутом в блоке кроме, чтобы правильно обработать эту ситуацию. Попробуй это:

import httplib
import socket
import time

connection = httplib.HTTPConnection('127.0.0.1', 8000)
# connection moved below... connection.connect()

for i in range(0, 1000):
    print 'sending... ', i    
    try:
        connection.request('GET', '/x', '', {'Connection' : ' keep-alive'})
        response = connection.getresponse()
        d = response.read()       
        print '    ', response.status
    except KeyboardInterrupt: 
        break
    except socket.error:    
        while True:
            try:
                connection = httplib.HTTPConnection('127.0.0.1', 8000)
                connection.connect()
            except socket.error:
                print 'cant connect, will try again in a second...'
                time.sleep(1)  
            else:
                break

до перезагрузки:

sending...  220
     404
sending...  221
     404
sending...  222
     404

перезапуск сервера:

cant connect, will try again in a second...
cant connect, will try again in a second...
cant connect, will try again in a second...
cant connect, will try again in a second...

сервер снова:

sending...  223
     404
sending...  224
     404
sending...  225
     404

Обновление для вашего комментария:

Очевидно, что в реальном мире вы не можете переписать код всех http-клиентов, которые подключаются к вашему серверу. Мой вопрос: что я могу сделать, чтобы получить изящную перезагрузку (без сбоев) для произвольных клиентов.

Я думаю, что одно из универсальных решений может справиться с такими проблемами с клиентами - простой прокси между клиентом и сервером. С прокси вы можете перезапустить сервер независимо от клиентов (подразумевается, что прокси всегда включен). И на самом деле это обычно используется - 502 (плохой шлюз) ошибки от прокси веб-приложений - точно такая же ситуация - клиент получает ошибку от прокси, когда сервер приложений не работает! Попробуйте nginx, лак или что-то подобное.


Кстати, uwsgi имеет встроенный плагин «прокси / балансировщик нагрузки / маршрутизатор»:

UWSGI FastRouter

Для расширенных настроек uWSGI включает плагин fastrouter, прокси / балансировщик нагрузки / маршрутизатор, говорящий по протоколу uwsgi. Он встроен по умолчанию. Вы можете поместить его между вашим веб-сервером и реальными экземплярами uWSGI, чтобы иметь больше контроля над маршрутизацией HTTP-запросов к вашим серверам приложений.

документы здесь: http://uwsgi-docs.readthedocs.io/en/latest/Fastrouter.html

Автор: ndpu Размещён: 13.07.2016 01:01

0 плюса

11278 Репутация автора

вы управляете как приложением, так и прокси-сервером в одном и том же экземпляре uWSGI, поэтому при перезагрузке стека вы также убиваете веб-сервер внешнего интерфейса (тот, который вы запускаете с опцией 'http').

Вы должны разделить http-маршрутизатор на другой экземпляр uWSGI или использовать nginx / haproxy или аналогичный. Если у вас есть два разных стека, вы можете перезагрузить приложение, не закрывая сокет

Автор: roberto Размещён: 14.07.2016 08:15
Вопросы из категории :
32x32