syslog源码_Gunicorn源码分析01--目录结构
1. Gunicorn基本介紹
Gunicorn是一個(gè)基于Python實(shí)現(xiàn)的動(dòng)態(tài)Web服務(wù)器,實(shí)現(xiàn)了WSGI協(xié)議,可以與Django、Flask等Web框架集成。
與Apache、Nginx等靜態(tài)Web服務(wù)器相比,Gunicorn動(dòng)態(tài)處理能力強(qiáng)??梢酝ㄟ^HTTP或者Unix Socket來與之通信,以此實(shí)現(xiàn)動(dòng)靜分離。
Gunicorn由于源碼調(diào)用了fcntl、fork等接口,因此只能跑在類Unix系統(tǒng)上,Windows上跑不了。
Gunicorn通過pre-worker模型來實(shí)現(xiàn)并發(fā),worker的工作模式有sync、gthread、gevent等,即可以通過多線程、或者協(xié)程來處理請求。
Gunicorn是可配置的,可以通過命令行參數(shù)或者配置文件的形式,來完成對其配置。
Gunicorn的日志功能豐富,可以輸出到控制臺(tái)、日志文件或者syslog服務(wù)器,另外日志分為http請求訪問日志和程序運(yùn)行時(shí)的錯(cuò)誤日志,這點(diǎn)借鑒了Apache的思路。
2. Gunicorn源碼結(jié)構(gòu)【版本為 20.0.4】
可發(fā)現(xiàn)源碼文件34個(gè),總行數(shù)為7867行,不到萬行。定義了147個(gè)類,75個(gè)函數(shù),43個(gè)全局變量。├── app 【與Web框架通信相關(guān)】 │ ├── base.py │ ├── __init__.py │ ├── pasterapp.py │ └── wsgiapp.py ├── arbiter.py 【master進(jìn)程,在gunicorn中叫arbiter】 ├── config.py 【配置相關(guān),可以通過命令行參數(shù)、配置文件等方式來配置guniconrn】 ├── debug.py ├── errors.py ├── glogging.py 【產(chǎn)生的日志,可以發(fā)送到屏幕或者日志文件(access和error)】 ├── http 【處理客戶端發(fā)送過來的http請求】 │ ├── body.py │ ├── errors.py │ ├── __init__.py │ ├── message.py │ ├── parser.py │ ├── unreader.py │ └── wsgi.py ├── __init__.py ├── instrument │ ├── __init__.py │ └── statsd.py ├── pidfile.py 【gunicorn運(yùn)行時(shí)的進(jìn)程編號,可以寫到一個(gè)文件】 ├── reloader.py ├── sock.py 【gunicorn作為動(dòng)態(tài)Web服務(wù)器,需要使用socket】 ├── systemd.py ├── util.py 【工具性函數(shù)和類】 └── workers 【pre-worker模型中,worker有syncgthreadggevent等模式】├── base_async.py├── base.py├── geventlet.py├── ggevent.py├── gthread.py├── gtornado.py├── __init__.py├── sync.py└── workertmp.py3. Gunicorn源碼關(guān)系圖
4. 如何啟動(dòng) Gunicorn Server
從源碼關(guān)系圖中可知,Gunicorn server有兩種啟動(dòng)方式【源碼關(guān)系圖中最左側(cè)】
(1)通過【python main.py】的方式【圖中左側(cè)下半部】
該方式,主要用于在開發(fā)Gunicorn時(shí),測試Gunicorn是否能正常工作
main.py【如下官網(wǎng)的例子】
該文件是我們自己手動(dòng)實(shí)現(xiàn)的py文件,里面至少要實(shí)現(xiàn)一個(gè)app handler函數(shù)或者app handler類和一個(gè)app server類。app handler函數(shù)/類:
用于讀取客戶端請求數(shù)據(jù),解析處理后,產(chǎn)生響應(yīng);app handler函數(shù)需要的參數(shù):一個(gè)為字典變量【environ】,表示環(huán)境變量。另一個(gè)為函數(shù)指針,不是函數(shù)調(diào)用,該函數(shù)【start_response()】用來產(chǎn)生響應(yīng)體的狀態(tài)和頭部。
同理app handler類的_call__ 方法也是接收環(huán)境變量和函數(shù)指針兩個(gè)參數(shù),與上面相同。另外,該類需要實(shí)現(xiàn)_iter__ 方法,該方法是個(gè)生成器,產(chǎn)生HTTP響應(yīng)。
app server類:
需要繼承【gunicorn.app.base.BaseApplication】;app server類的參數(shù):一個(gè)是app handler函數(shù)或者類,另一是server配置參數(shù)字典;app server類需要實(shí)現(xiàn)兩個(gè)方法:【load()】和【load_config()】(用于加載配置到server)。# main.pyimport multiprocessing import gunicorn.app.basedef app_handler(environ, start_response):status = '200 OK'response_headers = [('Content-Type', 'text/plain'),]start_response(status, response_headers)# response_body = ['Works finen']response_body = []for key, value in environ.items():response_body.append(f'{key}: {value}')response_body.append('nWorks finen')return response_body.encode('utf-8')class APPHandler(object):def __init__(self, environ, start_response):self.environ = environself.start_response = start_responsedef __call__(self, environ, start_response):self.environ = environself.start_response = start_responsedef __iter__(self):data = 'Hello, World!n'status = '200 OK'response_headers = [('Content-type', 'text/plain'),('Content-Length', str(len(data))),('Foo', 'Bu00e5r'), # Foo: B?r]self.start_response(status, response_headers)yield data.encode("utf-8")class APPServer(gunicorn.app.base.BaseApplication):def __init__(self, app, options=None):self.options = options or {}self.application = appsuper().__init__()def load_config(self):config = {key: value for key, value in self.options.items()if key in self.cfg.settings and value is not None}for key, value in config.items():self.cfg.set(key.lower(), value)def load(self):return self.applicationif __name__ == '__main__':options = {'bind': ['0.0.0.0:6000', '[::]:6000'],'workers': multiprocessing.cpu_count(),}APPServer(app_handler, options).run()# APPServer(APPHandler, options).run()(2)通過【gunicorn project.wsgi --chdir /path/to/project-root -c /path/to/project-cfg.py】【源碼關(guān)系圖中左側(cè)上半部】
該方式,就是生產(chǎn)環(huán)境中使用Gunicorn來啟動(dòng)項(xiàng)目的正確姿勢,其實(shí)該命令與以下命令一致。
python -m gunicorn.app.wsgiapp project.wsgi --chdir /path/to/project-root -c /path/to/project-cfg.pypython -m gunicorn.app.wsgiapp
該命令會(huì)讓python解釋器去【sys.path】所列舉的目錄中,去查找模塊【gunicorn.app.wsgiapp】,所以直接運(yùn)行【gunicorn】和運(yùn)行【python -m gunicorn.app.wsgiapp】效果一樣。說白了【gunicorn】作為可執(zhí)行腳本運(yùn)行時(shí),其實(shí)就是調(diào)用【python】去執(zhí)行源碼文件【gunicorn/app/wsgiapp.py】,至于如何實(shí)現(xiàn)該功能,以后補(bǔ)上。
project.wsgi
一般是特定web框架,提供給Gunicorn的接口文件,比如Django中的 SomeProject.wsgi模塊project-root
為具體的Web項(xiàng)目根路徑。project-cfg.py
為項(xiàng)目的外部配置文件,必須是.py格式,用于對Gunicorn進(jìn)行個(gè)性化配置,當(dāng)然也可以通過命令行參數(shù)的方式加以配置。例如Django項(xiàng)目中的wsgi接口文件如下,假設(shè)該django項(xiàng)目位于【/tmp/myporject/】,內(nèi)容如下
myapp1 myapp2 myproject manage.py那么我們可以通過以下命令啟動(dòng)此Django項(xiàng)目
gunicorn --chdir /tmp/myproject/ myproject.wsgi# wsgi.py""" WSGI config for django_demo project.It exposes the WSGI callable as a module-level variable named ``application``.For more information on this file, see https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/ """import osfrom django.core.wsgi import get_wsgi_applicationos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_demo.settings')application = get_wsgi_application()總結(jié)
以上是生活随笔為你收集整理的syslog源码_Gunicorn源码分析01--目录结构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: reportviewer控件mysql_
- 下一篇: koa连接mysql怎么做_koa-连接