python bottle使用多個連接埠(多個進程)提高並發

來源:互聯網
上載者:User

標籤:

我的程式是用python結合bottle架構寫的,但bottle內建wsgi原本只是單進程單線程運行模式(Bottle 預設運行在內建的 wsgiref 伺服器上面。這個單線程的 HTTP 伺服器在開發的時候特別有用,但其效能低下,在伺服器負載不斷增加的時候也許會是效能瓶頸, 一次只能響應一個請求)。為了提升程式的處理能力,首先要啟用多線程,即在程式中使用gevent( 大多數伺服器的線程池都限制了線程池中線程的數量,避免建立和切換線程的代價。儘管和進程 (fork)比起來,線程還是挺便宜的。但是也沒便宜到可以接受為每一個請求建立一個線程。gevent 模組添加了 greenlet 的支援。 greenlet 和傳統的線程類似,但其建立只需消耗很少的資源。基於 gevent 的伺服器可以產生成千上萬的 greenlet,為每個串連分配一個 greenlet 也毫無壓力。阻塞greenlet,也不會影響到伺服器接受新的請求。同時處理的串連數理論上是沒有限制的。)。只需要在run中加上 server=‘gevent‘,如下:

1 import gevent2 from gevent import  monkey.patch_all()3       程式碼片段……4 run(host=‘0.0.0.0‘, port=8080, server=‘gevent‘)

 

儘管使用了多線程模式,但這些線程都是跑在一個進程裡,所以需要開啟多個進程來進一步提升並發處理能力,因此在啟用指令碼的時候,在run(port=)裡,連接埠號碼不能寫死,應該使用變數來傳遞,如下代碼(在指令碼執行時,在需帶一個參數,這個參數是大於1024的整數,否則報錯停止指令碼):

import gevent,sysfrom gevent import  monkey.patch_all()#擷取連接埠號碼try:    portnum = int(sys.argv[1])except Exception,e:    print "請帶上整數類型的連接埠號碼啟動此程式"    logging.error("請帶上整數類型的連接埠號碼啟動此程式")    sys.exit(1)if portnum <= 1024:    print "連接埠號碼請大於1024!"    logging.error("連接埠號碼請大於1024!")    sys.exit(1)      程式碼片段……run(host=‘0.0.0.0‘, port=portnum , server=‘gevent‘) 

 

執行方式如下(osyw.py是我python程式名):

python osyw.py 1124

 

如果純靠手動操作這些,在生產上,很不方便,所以我寫了個shell來管理,這個shell定義了多個連接埠號碼,然後去迴圈啟用或停止python進程,指令碼大概如下(是用httpd改寫的):

 #!/bin/bash## osyw        Startup script for the osyw HTTP Server## chkconfig: - 88 18# description: osyw# processname: osyw# config: # config: /home/bottle/osyw/# pidfile: /var/run/osyw.pid#### BEGIN INIT INFO# Provides: osyw# Short-Description: start and stop osyw HTTP Server# Description: The osyw HTTP Server is an extensible server #  implementing the current HTTP standards.### END INIT INFO# Source function library.. /etc/rc.d/init.d/functions# Path to the apachectl script, server binary, and short-form for messages.port_list=(8811 8812 8813)     #設定了3個連接埠#pidfile=‘/var/run/osyw.pid‘pro_path=‘/var/www/osyw/osyw.py‘    #程式路徑log_path=‘/var/www/osyw/log/access.log‘    #訪問日誌路徑RETVAL=0start() {        for i in ${port_list[*]}        do                p=`/usr/sbin/lsof -i :${i} |wc -l`                if [ ${p} -ge 2 ]                then                        action "osyw ${i} already exists !" /bin/false                else                        /usr/bin/python ${pro_path} ${i} &>> ${log_path}                RETVAL=$?                        if [ ${RETVAL} == 0 ]                        then                                action "osyw ${i} start ..." /bin/true                        else                                action "osyw ${i} start ..." /bin/false                        fi                fi        done    return $RETVAL}stop() {        for i in ${port_list[*]}        do                pidfile="/var/run/osyw_${i}.pid"                if [ -f ${pidfile} ]                then                        pid=`cat ${pidfile}`                        kill -9 ${pid}                        RETVAL=$?                        if [ ${RETVAL} == 0 ]                    then                    action  "osyw ${i} stop ..." /bin/true                    else                    action  "osyw ${i} stop ..." /bin/false                        fi                        rm -f ${pidfile}                else                        action  "osyw ${i} Has stopped !" /bin/false                fi        done}# See how we were called.case "$1" in  start)        start        ;;  stop)        stop        ;;  status)        status -p ${pidfile} ‘osyw‘        RETVAL=$?        ;;  restart)        stop        sleep 2        start        ;;  condrestart|try-restart)        if status -p ${pidfile} ‘osyw‘ >&/dev/null; then                stop                start        fi        ;;  force-reload|reload)        reload        ;;  *)        echo $"Usage: $prog {start|stop|restart|condrestart|try-restart|force-reload|reload|status|fullstatus|graceful|help|configtest}"        RETVAL=2esacexit $RETVAL

 

 

本人的代碼是用svn管理的,所以上傳代碼後,SVN鉤子會調用shell指令碼來重啟這些程式,以下是SVN鉤子代碼:

export LANG=en_US.UTF-8/usr/bin/svn update --username xxxx --password xxxxxxxx /var/bottle/bin/bash /etc/init.d/osyw restart

 

當然,為了結合shell,python程式裡也要做一些處理,如自動把程式轉為後台守護進程,然後把進程ID寫入檔案,以下是關鍵的python代碼:

 

#定義PID路徑  pid_path = ‘/var/run/osyw_%s.pid‘ % portnum      def daemonize():      """把本指令碼轉為守護進程"""      try:          pid=os.fork()          if pid>0:              sys.exit(0)      except Exception,e:          logging.error(e)          sys.exit(1)        os.chdir(‘/‘)      os.umask(0)      os.setsid()        try:          pid=os.fork()          if pid>0:              sys.exit(0)      except Exception,e:          logging.error(e)          sys.exit(1)        PID = str(os.getpid())      with open(pid_path,‘w‘) as f:          f.write(PID)    其它程式碼片段……    if __name__ == ‘__main__‘:      try:          from oscore import setting    #匯入設定檔        if setting.status == ‘online‘:    #如果配置中是線上的,則程式轉入後台運行            daemonize()      except Exception:          pass        app = default_app()      app = SessionMiddleware(app, session_opts)      #sessionMiddleware是session外掛程式    run(app=app,host=‘0.0.0.0‘, port=portnum,server=‘gevent‘)

 

最好,用nginx代理來負載這些連接埠,我nginx和python程式是安裝在同一台伺服器上的:

以上是nginx反向 Proxy的部分代碼:

 

upstream myweb {#ip_hash;server 192.168.1.240:8811 weight=4 max_fails=2 fail_timeout=30s;server 192.168.1.240:8812 weight=4 max_fails=2 fail_timeout=30s;server 192.168.1.240:8813 weight=4 max_fails=2 fail_timeout=30s;}server {    listen       80;        server_name  192.168.1.240;    location /        {        proxy_pass http://myweb;        proxy_set_header Host  $host;        proxy_set_header X-Forwarded-For  $remote_addr;        proxy_cache_key $host$uri$is_args$args;        }        access_log  off;        }

 

做完這些後,當訪問80連接埠時,nginx就會平均輪洵分配到每個連接埠上去,實現了多進程,多線程的運行模式,更有效提升了並發處理能力

 

python bottle使用多個連接埠(多個進程)提高並發

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.