2015-06-16 52 views
1

我有一個WSGI應用程序使用CherryPy在ngnix服務器後面使用uWSGI託管。如何避免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; 
} 

/etc/uwsgi/apps-enabled/sample.js的uwsgi配置:

{ 
    "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應用程序,並將其指向另一個源代碼副本,爲ngnix添加一個額外的location /sample.test/ { ... }指向新的uwsgi應用程序,並在不影響生產版本的情況下使用備用URL對其進行破解。

但它利用uwsgi_modifier1 30按理說它是一個醜陋的黑客攻擊:

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

注:用於支持所謂的「uwsgi_modifier1 30」的做法古uWSGI版本。不要做。它確實是一個醜陋的黑客

現在,我可以這樣做:

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原生支持的便攜性。這意味着你可以安裝一個應用程序給定的路徑前綴並沒有什麼別的配置(當然,只要你建立與cherrypy.url 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 repo的克隆,分別檢查出穩定和devel分支),也許通過使用'sys.path'玩遊戲。的virtualenv? – Celada

+0

不過謝謝你的回答。我把第一句話簡單化了一下。我保留了uWSGI,因爲它的生命週期管理,性能,調整和監視功能最適合我們的應用程序,但我最終從混合中刪除了CherryPy。該應用程序有一個單一的URL端點,所以除了原始的WSGI('def application(env,start_response)')之外,我真的不需要任何東西,如果我確實需要更多,那麼沒有自己的內置HTTP服務器的更輕的庫可能更加合適。 – Celada

+0

@Celada(1)如果是指CherryPy的實例同時服務於*穩定*和* dev的*是受到來自*開發*頻繁的更新,然後我分享你的關心。在這種情況下,我會建議用一個子域替換路徑前綴,比如* dev.example.com *,* beta.example.com *等。它也是OP的最簡單答案。 (2)你一定可以做* sys.path * hackery來導入相同模塊的版本。雖然只是作爲最後的手段。 – saaj

相關問題