django提供了自帶的runserver命令啟動服務,這種方式一般用於開發環境以便於除錯程式,併發量比較小的時候也是可以應對的,但是併發量超過這種方式的承載能力時,就需要使用gunicorn啟動django的服務來提高併發能力了。
pip3 install django==2.0.6 gevent==1.4.0 gunicorn==19.7.1
import os
import multiprocessing
reload = false # **更新時不重啟專案
daemon = false # 不守護gunicorn程序
backlog = 2048 # 伺服器中排隊等待的最大連線數,建議值64-2048,超過2048時client連線會得到乙個error。
workers = multiprocessing.cpu_count() * 2 + 1 # 用於處理工作的程序數,這裡使用了文件建議的值
keyfile = '.../server.key' # ssl證書金鑰檔案路徑
certfile = '.../server.crt' # ssl證書檔案路徑
worker_class = 'gthread' # worker程序的工作方式,有sync、eventlet、gevent、tornado、gthread, 預設值sync, django使用gevent容易造成阻塞, 使用gthread的方式好一些。
threads = int(480 / workers) # 資料庫連線數=workers*threads*2
timeout = 60 # 訪問超時時間
graceful_timeout = 60 # 接收到restart訊號後,worker可以在graceful_timeout時間內,繼續處理完當前requests。
keepalive = 30 # server端保持連線時間。
# max_requests = 1000 # 有記憶體洩露時使用此選項重啟work
# max_requests_jitter = 50 # 重啟work的抖動幅度,一般設定為max_requests的5%
pythonpath = '/usr/bin/python3 -u' # 逗號分隔的python執行路徑,可以加上引數,這裡只有乙個路徑,-u表示使用無緩衝的二進位制終端輸出流
access_log_format = '%(t)s %(h)s "%(r)s" %(s)s %(b)s "%(f)s" "%(l)s"' # 日誌檔案格式
accesslog = '-' # 日誌檔案路徑,'-'表示輸出到終端
errorlog = '-' # 錯誤日誌檔案路徑,'-'表示輸出到終端
bind = '0:1999' # 指定監聽的位址和埠,這裡使用nginx**了,所以監聽特殊埠
project_name = 'mysite'
proc_name = 'gunicorn_%s' % project_name # 設定程序名稱
os.environ.setdefault('django_settings_module', '%s.settings' % project_name) # 設定環境變數指定django執行使用的配置檔案
os.environ.setdefault('werkzeug_run_main', 'true') # 設定環境變數告訴wekzeug這個是用於reload的主程序
threads值的計算比較重要,同乙個程序中的執行緒共享乙個資料庫連線池,乙個執行緒需要兩個與資料庫的連線,否則會報錯「mysql error:2014 commands out of sync; you can't run this command now」。
用max_connections表示資料庫支援的最大連線數,用workers表示程序數,threads表示執行緒數,每個程序中的執行緒數計算如下:
threads = max_connections / workers / 2
如果max_connections等於1000,我們預留40個資料庫連線作其他用途:
threads = int(int((max_connections - 40) / 2) / workers)
化間後得到上面的例子:
threads = int(480 / workers)
from myproject.gunicorn_config import threads
...,
'gunicorn',
]databases =
}}
併發量高了,資料庫連線量會過大,報錯「too many connections」,參考我的這篇文章解決。
其中pool_size的值設定為gunicorn_config.py中threads值的兩倍,因為每個執行緒需要建立兩個資料庫連線,否則會報錯「mysql error:2014 commands out of sync; you can't run this command now」。
也就是說,最終併發量上限為資料庫max_connections配置的數值的一半。
使用指令碼啟動的原因是supervisor殺不掉服務的子程序,需要用指令碼殺一下再啟動新的服務。
#!/bin/sh
pname=$1
port=$2
if [ -z "$" ]
then
pname="mysite"
fiif [ -z "$" ]
then
if [ "$pname"x = "mysite"x ]
then
port="1999"
else
echo "error project name \"$pname\""
exit 0
fifips aux | grep $/gunicorn_config.py | grep $ | awk '' | xargs kill -9 > /dev/null 2>&1 # 根據程序名和埠號過濾出程序id,殺死已存在的服務程序
# unbuffer表示使用無緩衝的二進位制輸出流,-p表示unbuffer可以從管道命令"|"的輸出中讀取內容(相容supervisor)
# $/gunicorn_config.py是第三步編寫的配置檔案的位置
# 0:$是指定監聽的位址和埠,這個會覆蓋gunicorn_config.py中的配置,加上這個便於過濾程序id
[program:mysite]
environment=user=root,pythonpath=/usr/bin/
directory=/var/www/mysite/
command=bash start.sh mysite
autostart=true
autorestart=true
stopasgroup=true
stderr_logfile=/var/log/supervisor/mysite_error.log
stdout_logfile=/var/log/supervisor/mysite_out.log
user=root
redirect_stderr=false
startretries=20
stdout_logfile_maxbytes=20mb
stdout_logfile_backups=20
用棧實現佇列 用佇列實現棧
棧的特點 filo firstinlastout 僅能從棧頂插入,刪除元素。最基本的介面包括push 從棧頂壓入元素 pop 從棧頂彈出元素 佇列的特點 fifo firstinfirstout 僅能從隊頭刪除元素,從隊尾插入元素。最基本的介面包括enque 從隊尾插入元素 deque 從隊頭刪除元...
用棧實現佇列,用佇列實現棧。好玩!!!
因為在資料結構中,棧和佇列長得實在是太像了,將他們拿來比較是不可避免的,棧 後進先出,而佇列 先進先出。同樣是只能在一端進行操作,那麼問題來了,能相互實現?能不能得好好分析一下嘛,如果是用兩個棧來實現佇列,好像這操作可以哦。一下,你就明白!顯然用兩個棧可以實現佇列的功能,就是借助另乙個棧來中轉一下,...
232 用棧實現佇列 225 用佇列實現棧
用棧實現佇列 佇列是先進先出,實現佇列的最直觀的方法是用鍊錶。但本題是要求使用棧。本題兩個stack相互倒,負負得正 class myqueue def init self self.instack self.outstack defpush self,x def pop self if len s...