### 導航
- [索引](# "總目錄")
- [下一頁](# "使用 URL 處理器") |
- [上一頁](# "應用程序的工廠函數") |
- [Flask 0.10.1 文檔](#) ?
- [Flask 代碼模式](#) ?
# 應用調度
應用調度指的是在 WSGI 層次合并運行多個 Flask 的應用的進程。您不能將Flask 與更大的東西合并,但是可以和 WSGI 應用交叉。這甚至允許您將Django 和 Flask 的應用運行在同一個解釋器下。這么做的用處依賴于這個應用內部是如何運行的。
與 [*模塊方式*](#) 的區別在于,此時您運行的不同 Flask 應用是相互之間完全獨立的,他們運行在不同的配置,而且在 WSGI層調度。
### 如何使用此文檔
下面的所有技巧和例子都將最終得到一個 application 對象,這個對象可以在任何 WSGI 服務器上運行。在生產環境下,請參看 [*部署選擇*](#)相關章節。在開發時,Werkzeug 提供了一個提供了一個內置的開發服務器,可以通過 [werkzeug.serving.run_simple()](http://werkzeug.pocoo.org/docs/serving/#werkzeug.serving.run_simple "(在 Werkzeug v0.10)") [http://werkzeug.pocoo.org/docs/serving/#werkzeug.serving.run_simple] 函數使用:
~~~
from werkzeug.serving import run_simple
run_simple('localhost', 5000, application, use_reloader=True)
~~~
注意,[run_simple](http://werkzeug.pocoo.org/docs/serving/#werkzeug.serving.run_simple "(在 Werkzeug v0.10)") [http://werkzeug.pocoo.org/docs/serving/#werkzeug.serving.run_simple] 函數不是為生產用途設計的,發布應用時可以使用 [*成熟的 WSGI 服務器*](#) 。
為了能使用交互式調試器,調試必須在應用和簡易開發服務器兩邊都被激活。下面是一個帶有調試功能的 “Hello World” 的例子:
~~~
from flask import Flask
from werkzeug.serving import run_simple
app = Flask(__name__)
app.debug = True
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
run_simple('localhost', 5000, app,
use_reloader=True, use_debugger=True, use_evalex=True)
~~~
### 合并應用
如果您有一些完全獨立的應用程序,而您希望他們使用同一個 Python 解釋器,背靠背地運行,您可以利用 [werkzeug.wsgi.DispatcherMiddleware](http://werkzeug.pocoo.org/docs/middlewares/#werkzeug.wsgi.DispatcherMiddleware "(在 Werkzeug v0.10)") [http://werkzeug.pocoo.org/docs/middlewares/#werkzeug.wsgi.DispatcherMiddleware] 這個類。這里,每個 Flask 應用對象都是一個有效的 WSGI 應用對象,而且他們在調度中間層當中被合并進入一個規模更大的應用,并通過前綴來實現調度。
例如,您可以使您的主應用運行在 / 路徑,而您的后臺接口運行在 /backend 路徑:
~~~
from werkzeug.wsgi import DispatcherMiddleware
from frontend_app import application as frontend
from backend_app import application as backend
application = DispatcherMiddleware(frontend, {
'/backend': backend
})
~~~
### 通過子域名調度
有時,您希望使用對一個應用使用不同的配置,對每個配置運行一個實例,從而有多個實例存在。假設應用對象是在函數中生成的,您就可以調用這個函數并實例化一個實例,這相當容易實現。為了使您的應用支持在函數中創建新的對象,請先參考[*應用程序的工廠函數*](#) 模式。
一個相當通用的例子,那就是為不同的子域名創建不同的應用對象。比如您將您的Web服務器設置為將所有的子域名都分發給您的引用,而您接下來使用這些子域名信息創建一個針對特定用戶的實例。一旦您使得您的服務器偵聽所有的子域名請求,那么您就可以使用一個非常簡單的 WSGI 對象來進行動態的應用程序構造。
實現此功能最佳的抽象層就是 WSGI 層。您可以編寫您自己的 WSGI 程序來檢查訪問請求,然后分發給您的 Flask 應用。如果您的應用尚未存在,那么就創建一個并且保存下來:
~~~
from threading import Lock
class SubdomainDispatcher(object):
def __init__(self, domain, create_app):
self.domain = domain
self.create_app = create_app
self.lock = Lock()
self.instances = {}
def get_application(self, host):
host = host.split(':')[0]
assert host.endswith(self.domain), 'Configuration error'
subdomain = host[:-len(self.domain)].rstrip('.')
with self.lock:
app = self.instances.get(subdomain)
if app is None:
app = self.create_app(subdomain)
self.instances[subdomain] = app
return app
def __call__(self, environ, start_response):
app = self.get_application(environ['HTTP_HOST'])
return app(environ, start_response)
~~~
調度器可以這樣使用:
~~~
from myapplication import create_app, get_user_for_subdomain
from werkzeug.exceptions import NotFound
def make_app(subdomain):
user = get_user_for_subdomain(subdomain)
if user is None:
# if there is no user for that subdomain we still have
# to return a WSGI application that handles that request.
# We can then just return the NotFound() exception as
# application which will render a default 404 page.
# You might also redirect the user to the main page then
return NotFound()
# otherwise create the application for the specific user
return create_app(user)
application = SubdomainDispatcher('example.com', make_app)
~~~
### 使用路徑來調度
通過 URL 路徑分發請求跟前面的方法很相似。只需要簡單檢查請求路徑當中到第一個斜杠之前的部分,而不是檢查用來確定子域名的 HOST 頭信息就可以了:
~~~
from threading import Lock
from werkzeug.wsgi import pop_path_info, peek_path_info
class PathDispatcher(object):
def __init__(self, default_app, create_app):
self.default_app = default_app
self.create_app = create_app
self.lock = Lock()
self.instances = {}
def get_application(self, prefix):
with self.lock:
app = self.instances.get(prefix)
if app is None:
app = self.create_app(prefix)
if app is not None:
self.instances[prefix] = app
return app
def __call__(self, environ, start_response):
app = self.get_application(peek_path_info(environ))
if app is not None:
pop_path_info(environ)
else:
app = self.default_app
return app(environ, start_response)
~~~
這種例子與之前子域名調度那里的區別是,這里如果創建應用對象的函數返回了 None,那么請求就被降級回推到另一個應用當中:
~~~
from myapplication import create_app, default_app, get_user_for_prefix
def make_app(prefix):
user = get_user_for_prefix(prefix)
if user is not None:
return create_app(user)
application = PathDispatcher(default_app, make_app)
~~~
? 版權所有 2013, Armin Ronacher.
- 歡迎使用 Flask
- 前言
- 給有經驗程序員的前言
- 安裝
- 快速入門
- 教程
- 介紹 Flaskr
- 步驟 0: 創建文件夾
- 步驟 1: 數據庫模式
- 步驟 2: 應用設置代碼
- 步驟 3: 創建數據庫
- 步驟 4: 請求數據庫連接
- 步驟 5: 視圖函數
- 步驟 6: 模板
- 步驟 7: 添加樣式
- 福利: 應用測試
- 模板
- 測試 Flask 應用
- 記錄應用錯誤
- 配置處理
- 信號
- 即插視圖
- 應用上下文
- 請求上下文
- 用藍圖實現模塊化的應用
- Flask 擴展
- 與 Shell 共舞
- Flask 代碼模式
- 大型應用
- 應用程序的工廠函數
- 應用調度
- 使用 URL 處理器
- 部署和分發
- 使用 Fabric 部署
- 在 Flask 中使用 SQLite 3
- 在 Flask 中使用 SQLAlchemy
- 上傳文件
- 緩存
- 視圖裝飾器
- 使用 WTForms 進行表單驗證
- 模板繼承
- 消息閃現
- 用 jQuery 實現 Ajax
- 自定義錯誤頁面
- 延遲加載視圖
- 在 Flask 中使用 MongoKit
- 添加 Favicon
- 數據流
- 延遲請求回調
- 添加 HTTP Method Overrides
- 請求內容校驗碼
- 基于 Celery 的后臺任務
- 部署選擇
- mod_wsgi (Apache)
- 獨立 WSGI 容器
- uWSGI
- FastCGI
- CGI
- 聚沙成塔
- API
- JSON 支持
- Flask 中的設計決策
- HTML/XHTML 常見問題
- 安全注意事項
- Flask 中的 Unicode
- Flask 擴展開發
- Pocoo 風格指引
- Python 3 支持
- 升級到最新版本
- Flask Changelog
- 許可證
- 術語表