2015-08-09 4 views
3

Я пытаюсь развернуть веб-приложение aiohttp, но не могу понять, как получить приложение для обслуживания через unix-сокет, который, как мне кажется, мне нужен, чтобы получить nginx и стрельба, чтобы поговорить друг с другом.Развертывание приложения aiohttp.web с использованием gunicorn и nginx

Простой пример приложения из aiohttp документации сохраняется как app.py:

import asyncio 
from aiohttp import web 

@asyncio.coroutine 
def hello(request): 
    return web.Response(body=b'Hello') 

app = web.Application() 
app.router.add_route('GET', '/', hello) 

if __name__ == "__main__": 
    loop = asyncio.get_event_loop() 
    handler = app.make_handler() 
    f = loop.create_server(handler, '0.0.0.0', 8080) 
    srv = loop.run_until_complete(f) 
    try: 
     loop.run_forever() 
    except KeyboardInterrupt: 
     pass 
    finally: 
     loop.run_until_complete(handler.finish_connections(1.0)) 
     srv.close() 
     loop.run_until_complete(srv.wait_closed()) 
     loop.run_until_complete(app.finish()) 
    loop.close() 

Запуск этого с gunicorn непосредственно работает:

gunicorn -k aiohttp.worker.GunicornWebWorker -b 0.0.0.0:8000 app:app 

Но когда я пытаюсь связать его вместо сокета UNIX, Я получаю следующие ошибки.

gunicorn -k aiohttp.worker.GunicornWebWorker -b unix:my_sock.sock app:app 

Traceback:

[2015-08-09 12:26:05 -0700] [26898] [INFO] Booting worker with pid: 26898 
[2015-08-09 12:26:06 -0700] [26898] [ERROR] Exception in worker process: 
Traceback (most recent call last): 
    File "/home/claire/absapp/venv/lib/python3.4/site- packages/gunicorn/arbiter.py", line 507, in spawn_worker 
    worker.init_process() 
    File "/home/claire/absapp/venv/lib/python3.4/site-packages/aiohttp/worker.py", line 28, in init_process 
    super().init_process() 
    File "/home/claire/absapp/venv/lib/python3.4/site-packages/gunicorn/workers/base.py", line 124, in init_process 
    self.run() 
    File "/home/claire/absapp/venv/lib/python3.4/site-packages/aiohttp/worker.py", line 34, in run 
    self.loop.run_until_complete(self._runner) 
    File "/usr/lib/python3.4/asyncio/base_events.py", line 268, in run_until_complete 
    return future.result() 
    File "/usr/lib/python3.4/asyncio/futures.py", line 277, in result 
    raise self._exception 
    File "/usr/lib/python3.4/asyncio/tasks.py", line 236, in _step 
    result = next(coro) 
    File "/home/claire/absapp/venv/lib/python3.4/site-packages/aiohttp/worker.py", line 81, in _run 
    handler = self.make_handler(self.wsgi, *sock.cfg_addr) 
TypeError: make_handler() takes 4 positional arguments but 11 were given 
[2015-08-09 12:26:06 -0700] [26898] [INFO] Worker exiting (pid: 26898) 

я наткнулся на что-то в вопросе aiohttp (https://github.com/KeepSafe/aiohttp/issues/136) , который использует сокет для создания сокета, чтобы поместить в качестве параметра в функции loop.create_server(), но Я просто не мог заставить работать. (Я также не знаю, является ли приложение в его коде одним и тем же веб-объектом.).

Кто-нибудь знает, как я могу это сделать? Благодаря!

ответ

1

Проблема в том, что GunicornWebWorker не поддерживает сокеты домена unix. Он исходит от GunicornWebWorker.make_handler(self, app, host, port), который хочет параметры: host и port. Очевидно, у вас их нет, если вы используете unix-сокет, но вместо этого имеете путь к соке.

Давайте посмотрим на начало GunicornWebWorker._run():

def _run(self): 
    for sock in self.sockets: 
     handler = self.make_handler(self.wsgi, *sock.cfg_addr) 
    ... 

В случае -b localhost:8000sock.cfg_addr является ['localhost', 8000], но -b unix:my_sock.sock это просто 'my_sock.sock'. Здесь происходит ошибка TypeError: make_handler() takes 4 positional arguments but 11 were given. Это unpacks строка, а не список.

Быстрый способ исправить это подкласс GunicornWebWorker и переопределить GunicornWebWorker.make_handler() игнорировать host и port. Они все равно не используются. Вы можете сделать это следующим образом:

class FixedGunicornWebWorker(worker.GunicornWebWorker): 
    def make_handler(self, app, *args): 
     if hasattr(self.cfg, 'debug'): 
      is_debug = self.cfg.debug 
     else: 
      is_debug = self.log.loglevel == logging.DEBUG 

     return app.make_handler(
      logger=self.log, 
      debug=is_debug, 
      timeout=self.cfg.timeout, 
      keep_alive=self.cfg.keepalive, 
      access_log=self.log.access_log, 
      access_log_format=self.cfg.access_log_format) 

Примечание Вам нужно иметь пакет с фиксированным рабочим в вашем PYTHONPATH. В противном случае Гуникорн не сможет его найти. Например, если вы поставите фиксированного рабочего внутри fixed_worker.py файла в тот же каталог, запустить gunicorn из, вы можете использовать его как:

$ PYTHONPATH="`pwd`:$PYTHONPATH" gunicorn -k fixed_worker.FixedGunicornWebWorker -b unix:my_sock.sock app:app 

UPD Также открыт issue в aiohttp хранилище.

+0

Это [исправлено] (https://github.com/KeepSafe/aiohttp/commit/1ac5e26122e91ef5a658524ebfe885a332307a51) –