2015-06-16 1 views
1

У меня есть приложение WSGI, использующее CherryPy, размещенное с использованием uWSGI за сервером ngnix.Как я могу избежать uwsgi_modifier1 30 и сохранить независимость WSGI от моего приложения?

Я бы хотел, чтобы приложение само по себе было «портативным». То есть приложение не должно знать и не заботится о том, к какому URL он сопоставляется, и должен даже работать, если он сопоставляется с несколькими разными URL-адресами. Я хочу DRY, сохраняя информацию о сопоставлении URL только в одном месте. К сожалению, единственный способ, который я нашел для этого, - использовать uwsgi_modifier 30, который has been called an ugly hack. Могу ли я избежать этого взлома?

Для настоящих целей я создал небольшое приложение под названием sample, которое демонстрирует мой вопрос.

ngnix конфигурация выглядит следующим образом:

location /sample/ { 
    uwsgi_pass unix:/run/uwsgi/app/sample/socket; 
    include uwsgi_params; 
    uwsgi_param SCRIPT_NAME /sample; 
    uwsgi_modifier1 30; 
} 

uwsgi конфигурация в /etc/uwsgi/apps-enabled/sample.js:

{ 
    "uwsgi": { 
     "uid": "nobody", 
     "gid": "www-data", 
     "module": "sample:app" 
    } 
} 

... и само приложение:

#!/usr/bin/python 

import cherrypy 

class Root(object): 
    @cherrypy.expose 
    def default(self, *path): 
     return "hello, world; path=%r\n" % (path,) 

app = cherrypy.Application(Root(), script_name=None) 

Он работает:

  • URL-адрес, по которому приложение сопоставляется (/sample), отображается только в одном месте: в файле конфигурации ngnix.
  • приложение не видит, что префикс и не придется беспокоиться об этом, он получает только то, что появляется после /sample:

    $ curl http://localhost/sample/ 
    hello, world; path=() 
    $ curl http://localhost/sample/foo 
    hello, world; path=('foo',) 
    $ curl http://localhost/sample/foo/bar 
    hello, world; path=('foo', 'bar') 
    

Чтобы мотивировать причину моего вопроса, скажем, у меня есть версия разработки приложения. Я могу сделать второе приложение uwsgi и указать его на другую копию исходного кода, добавить дополнительный location /sample.test/ { ... } в ngnix, указывая на новое приложение uwsgi, и взломать его с использованием альтернативного URL-адреса, не затрагивая производственную версию.

Но он использует uwsgi_modifier1 30, который якобы уродливой хак:

http://uwsgi-docs.readthedocs.org/en/latest/Nginx.html

Примечание: древние версии uWSGI используются для поддержки так называемого «uwsgi_modifier1 30» подход. Не делай этого. это действительно некрасиво хак

Теперь я могу это сделать:

location /something/ { 
    uwsgi_pass unix:/run/uwsgi/app/sample/socket; 
    include uwsgi_params; 
} 

... и это ...

{ 
    "uwsgi": { 
     "uid": "nobody", 
     "gid": "www-data", 
     "pythonpath": "", # no idea why I need this, btw 
     "mount": "/something=sample:app", 
     "manage-script-name": true 
    } 
} 

Но это требует, чтобы я жёстко путь (/something) в 2 местах вместо 1. Могу ли я этого избежать? Или я должен придерживаться первоначальной настройки, которая использует uwsgi_modifier1 30?

ответ

0

Мой ответ действительно об упрощении вещей, потому что следующее и количество конфигурации, которое у вас есть, указывают на одно - перебор.

CherryPy ⇐ WSGI ⇒ uWSGI ⇐ uwsgi ⇒ Nginx ⇐ HTTP ⇒ Client 

CherryPy имеет готовый к производству сервер, который изначально говорит HTTP. Протокол посредника, а именно WSGI, не требуется. Для низкого трафика вы можете использовать его самостоятельно. Для высокого трафика с Nginx в передней, как:

CherryPy ⇐ HTTP ⇒ Nginx ⇐ HTTP ⇒ Client 

CherryPy имеет представление о приложении, и вы можете serve several applications с одним экземпляром CherryPy. CherryPy также может обслуживать другие WSGI applications. Недавно я отвечаю на вопрос related question.

Переносимость

Переносимость ваш говорим о изначально поддерживается CherryPy. Это означает, что вы можете подключить приложение к префиксу заданного пути, и настроить его еще нечем (ну, пока вы создаете URL-адреса с cherrypy.url и обычно имейте в виду, что приложение может быть установлено на разные префиксы пути).

server.py

#!/usr/bin/env python3 

import cherrypy 


config = { 
    'global' : { 
    'server.socket_host' : '127.0.0.1', 
    'server.socket_port' : 8080, 
    'server.thread_pool' : 8 
    } 
} 
# proxy tool is optional 
stableConf = {'/': {'tools.proxy.on': True}} 
develConf = {'/': {'tools.proxy.on': True}} 

class AppStable: 

    @cherrypy.expose 
    def index(self): 
    return 'I am stable branch' 

class AppDevel: 

    @cherrypy.expose 
    def index(self): 
    return 'I am development branch'  

cherrypy.config.update(config) 
cherrypy.tree.mount(AppStable(), '/stable', stableConf) 
cherrypy.tree.mount(AppDevel(), '/devel', develConf)  

if __name__ == '__main__': 
    cherrypy.engine.signals.subscribe() 
    cherrypy.engine.start() 
    cherrypy.engine.block() 

server.conf (факультативно)

server { 
    listen 80; 

    server_name localhost; 

    # settings for serving static content with nginx directly, logs, ssl, etc. 

    location/{ 
    proxy_pass   http://127.0.0.1:8080; 
    proxy_set_header Host    $host; 
    proxy_set_header X-Real-IP  $remote_addr; 
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
    } 

} 
+0

Для второй части, что наводит на мысль монтажа как стабильные и развития версии в одном процессе CherryPy, я определенно есть опасения по поводу этого, потому что (1) экземпляр CherryPy нужно будет перезапускать часто по мере развития, неоправданно влияя на стабильную версию в одно и то же время, и (2) это довольно сложно чтобы сделать это в первую очередь, так как я хотел бы импортировать дважды тот же модуль в одном и том же процессе Python (например, два разных клона одного и того же git-репо, проверенные на стабильные и девеловые ветви соответственно), возможно, играя в игры с 'sys.path'. virtualenv? – Celada

+0

Однако спасибо за ваш ответ. Я сделал первое предложение об упрощении вещей. Я сохранил uWSGI, потому что его управление жизненным циклом, производительность, а также возможности настройки и мониторинга наилучшим образом подходят для нашего приложения, но я закончил удаление CherryPy из состава. Приложение имеет одну конечную точку URL-адреса, поэтому мне действительно ничего не нужно здесь, кроме необработанного WSGI ('def application (env, start_response)'), и если мне понадобится больше, то более легкая библиотека без собственного встроенного HTTP-сервера может быть более подходящий. – Celada

+0

@Celada (1) Если экземпляр CherryPy, предназначенный для обслуживания как * stable *, так и * dev *, подвержен частым обновлениям от * dev *, тогда я разделяю вашу озабоченность. В таком случае я бы предложил заменить префикс пути субдоменом, например * dev.example.com *, * beta.example.com * и т. Д. Это также самый простой ответ OP. (2) Вы можете сделать * sys.path * hackery, чтобы импортировать версию того же модуля. Хотя только в крайнем случае. – saaj