My program was written in Python in conjunction with the Bottle framework, but the Bottle comes with Wsgi, which was originally a single-process single-threaded run mode (Bottle runs on the built-in Wsgiref server by default. This single-threaded HTTP server is particularly useful when developing, but its performance is low and may be a performance bottleneck when the server load is increasing, responding to only one request at a time. In order to improve the processing power of the program, it is first to enable multi-threading, that is, to use Gevent in the program (the thread pool for most servers limits the number of threads in the threading pools, avoiding the cost of creating and switching threads.) Although the thread is quite cheap compared to the process (fork). But it's not cheap. You can accept creating a thread for each request. The Gevent module adds support for Greenlet. Greenlet are similar to traditional threads, but they are created with minimal resources. Gevent-based servers can generate thousands of greenlet, and there is no pressure to assign a greenlet to each connection. Blocking the Greenlet does not affect the server accepting new requests. There is theoretically no limit to the number of connections processed at the same time. )。 Just add server= ' gevent ' to run, as follows:
1 import Gevent2 from gevent import Code Snippet ... 4 run (host= ' 0.0.0.0 ', port=8080, server= ' gevent ')
Although multithreaded mode is used, but these threads are running in a process, it is necessary to open multiple processes to further improve the concurrency processing power, so when the script is enabled, in Run (port=), the port number can not be written dead, you should use the variable to pass, the following code (when the script executes, the need to take a parameter , this parameter is an integer greater than 1024, or the error stops the script):
Import gevent,sysfrom gevent import monkey.patch_all () #获取端口号try: portnum = Int (sys.argv[1]) Except exception,e: print "Please start this program with the port number of the integer type" logging.error ("Please start this program with the port number of the integer type") sys.exit (1) if Portnum <= 1024x768: print "port number is greater than 1024! " Logging.error (" The port number is greater than 1024!) ") Sys.exit (1) code snippet ... run (host= ' 0.0.0.0 ', Port=portnum, server= ' gevent ' )
Execute as follows (osyw.py is my Python program name):
Python osyw.py 1124
If the purely manual operation of these, in the production, very inconvenient, so I wrote a shell to manage, the shell defines a number of port numbers, and then to loop to enable or stop the Python process, the script is probably as follows (is rewritten with httpd):
#!/bin/bash## osyw Startup script for the osyw HTTP server## chkconfig:-The 18# description:osyw# Processname:os yw# config: # config:/home/bottle/osyw/# pidfile:/var/run/osyw.pid#### BEGIN INIT info# provides:osyw# short-descriptio N:start and Stop Osyw http server# description:the osyw HTTP Server is a 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个端 Port #pidfile= '/var/run/osyw.pid ' pro_path= '/var/www/osyw/osyw.py ' #程序路径log_path = '/var/www/osyw/log/access.log ' # Access log Path 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 ElseAction "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 "O Syw ${i} stop ... "/bin/true Else action" Osyw ${i} stop ... "/bin/false fi rm-f ${pidfile} else acti On "Osyw ${i} have stopped!"/bin/false fi done}# See how we were Called.case "$" in start) start; stop) stop;; Status) status-p ${pidfile} ' osyw ' retval=$?;; restart) Stop sleep 2 start; condrestart|try-Restar T) 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
:
My code is managed with SVN, so after uploading the code, the SVN hook will invoke the shell script to restart these programs, the following is the SVN hook code:
Export Lang=en_us. UTF-8/USR/BIN/SVN update--username xxxx--password xxxxxxxx/var/bottle/bin/bash/etc/init.d/osyw Restart
Of course, in order to combine the Shell,python program to do some processing, such as automatically turn the program into the daemon, and then write the process ID to the file, the following is the key Python code:
#定义PID路径 Pid_path = '/var/run/osyw_%s.pid '%portnum def daemonize (): "" "Convert this script to daemon" "Try: pid=os.fork () if pid>< C4>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) Other code snippet ... if __name__ = = ' __main__ '
try
: from oscore import setting #导入配置文件 if Setting.status = = ' online ': #如果配置中是线上的, the program is running in the background daemonize () excep T exception:pass app = Default_app () app = Sessionmiddleware (app, session_opts) # Sessionmiddleware is session plugin run (app=app,host= ' 0.0.0.0 ', port=portnum,server= ' gevent ')
Best, with Nginx proxy to load these ports, my nginx and Python programs are installed on the same server:
The above is the Nginx reverse proxy part of the code:
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 ; 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; }
After these, when access to 80 port, Nginx will be the average wheel xun assigned to each port up, the implementation of multi-process, multi-threaded operation mode, more effective to enhance the concurrency processing power
Python bottle uses multiple ports (multiple processes) to increase concurrency