我的程序是用python结合bottle框架写的,但bottle自带wsgi原本只是单进程单线程运行模式(Bottle 默认运行在内置的 wsgiref 服务器上面。这个单线程的 HTTP 服务器在开发的时候特别有用,但其性能低下,在服务器负载不断增加的时候也许会是性能瓶颈, 一次只能响应一个请求)。为了提升程序的处理能力,首先要启用多线程,即在程序中使用gevent( 大多数服务器的线程池都限制了线程池中线程的数量,避免创建和切换线程的代价。尽管和进程 (fork)比起来,线程还是挺便宜的。但是也没便宜到可以接受为每一个请求创建一个线程。gevent 模块添加了 greenlet 的支持。 greenlet 和传统的线程类似,但其创建只需消耗很少的资源。基于 gevent 的服务器可以生成成千上万的 greenlet,为每个连接分配一个 greenlet 也毫无压力。阻塞greenlet,也不会影响到服务器接受新的请求。同时处理的连接数理论上是没有限制的。)。只需要在run中加上 server=‘gevent‘,如下:

1 importgevent

2 from gevent importmonkey.patch_all()

3 代码段……

4 run(host=‘0.0.0.0‘, port=8080, server=‘gevent‘)

尽管使用了多线程模式,但这些线程都是跑在一个进程里,所以需要开启多个进程来进一步提升并发处理能力,因此在启用脚本的时候,在run(port=)里,端口号不能写死,应该使用变量来传递,如下代码(在脚本执行时,在需带一个参数,这个参数是大于1024的整数,否则报错停止脚本):

importgevent,sys

from gevent importmonkey.patch_all()

#获取端口号

try:

portnum = int(sys.argv[1])

exceptException,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=0

start() {

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 "osyw ${i} stop ..." /bin/true

elseaction "osyw ${i} stop ..." /bin/false

fi

rm -f ${pidfile}

elseaction "osyw ${i} Has stopped !" /bin/false

fi

done

}

# See how we were called.

case "$1" instart)

start

;;

stop)

stop

;;

status)

status -p ${pidfile} ‘osyw‘RETVAL=$?

;;

restart)

stop

sleep 2start

;;

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=2esac

exit $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

defdaemonize():

"""把本脚本转为守护进程"""

try:

pid=os.fork()

if pid>0:

sys.exit(0)

exceptException,e:

logging.error(e)

sys.exit(1)

os.chdir(‘/‘)

os.umask(0)

os.setsid()

try:

pid=os.fork()

if pid>0:

sys.exit(0)

exceptException,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()

exceptException:

passapp =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反向代理的部分代码:

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就会平均轮洵分配到每个端口上去,实现了多进程,多线程的运行模式,更有效的提升了并发处理能力

原文:http://www.cnblogs.com/drfdai/p/4518121.html

python开启多个端口服务_python bottle使用多个端口(多个进程)提高并发相关推荐

  1. python同时监听多个端口_python bottle使用多个端口(多个进程)提高并发

    我的程序是用python结合bottle框架写的,但bottle自带wsgi原本只是单进程单线程运行模式(Bottle 默认运行在内置的 wsgiref 服务器上面.这个单线程的 HTTP 服务器在开 ...

  2. linux开启80服务器,Linux服务器之IPTABLES开启80端口

    在服务器部署不同的程序时,总会遇到各种各样的问题,其中本文介绍的iptables开放80端口也是在服务器部署常见的问题之一.常见情况有以下两种: 情况一:在linux服务器部署好web运行环境和程序时 ...

  3. python bottle 制作表单_python bottle框架

    python bottle框架 简介: Bottle是一个快速.简洁.轻量级的基于WSIG的微型Web框架,此框架只由一个 .py 文件,除了Python的标准库外,其不依赖任何其他模块. Bottl ...

  4. python 在主线程开线程_Python开启线程,在函数中开线程的实例

    逻辑处理上分成了多个模块,为了提高效率,前一个模块处理完调用后一个模块操作时使用多线程 我这里遇到的情形是前面取数据后面存到mysql,发现单线程效率很低,改为取数据后开线程存到mysql 开启线程之 ...

  5. python开发webservice服务_Python开发WebService系列教程之REST,web.py,eurasia,Djan

    在Bioinformatics(生物信息学)领域,WebService是很重要的一种数据交换技术,未来必将更加重要.目前EBI所提供的WebService就分别有SOAP和REST两种方式的服务,不管 ...

  6. python调用百度地图实现导航_python调用百度地图WEB服务API获取地点对应坐标值

    本篇博客介绍如何使用Python调用百度地图WEB服务API获取地点对应坐标值,现有一系列结构化地址数据(如:北京市海淀区上地十街十号),目的是获取对应坐标值. 百度地图开发者平台路线规划使用说明网址 ...

  7. python应用领域有开发操作系统吗_python 全栈开发,Day37(操作系统的发展史)

    昨日内容回顾: # C/S和B/S架构 # osi五层模型 # 应用层 # 自定义协议(struct) _ 解决黏包 # 验证客户端合法性 _ hmac os.urandom # 解决TCP协议的se ...

  8. python开启局域网传输

    python开启局域网传输 1.找自己的IP 在命令提示窗口输入:ipconfig <----找自己的IP地址 2.创建要传输文件的文件夹(只允许在该文件夹下访问传输) a.复制文件夹路径 b. ...

  9. python监听文件更改记录_python 监控文件修改

    Pyinotify – Linux中实时监控文件系统更改 Pyinotify 是一个简单而实用的 Python 模块,它用于通过 inotify 实时监控Linux文件系统的更改.用于在Linux中实 ...

最新文章

  1. android 使用广播监听网络状态
  2. Python读取保存在hdf5文件中的脑电数据
  3. HEU 4048 Picking Balls
  4. 7. Leetcode 611. 有效三角形的个数 (数组-双向双指针)
  5. flask request (request.files)
  6. document.getElementById(billNo)的作用
  7. python3 copy_python3 深浅copy对比详解
  8. tcga癌症亚型获取_将亚型多态性与通用多态性相关联的危险
  9. html百分比代码怎么写,参考Bootstrap写的一个带百分比的进度条(附源码)
  10. 基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET - ActiveXForm运行容器...
  11. mysql-练习的数据准备
  12. git command not found
  13. 2018中国大学生程序设计竞赛-网络选拔赛题解
  14. python字符串截取后拼接_Python字符串拼接、截断、搜索、替换,python,截取,查找
  15. datetime与timestamp的区别
  16. 带自动定位的水印相机_水印相机自动定位应该如何设置
  17. retrofit简单的网络请求
  18. shared_preferences本地存储操作
  19. VMware Workstation Pro网络配置(WiFi配置等)
  20. 模拟信号和数字信号讲堂(一),模拟信号和数字信号之模拟信号详解

热门文章

  1. Truncated SVD for faster dection
  2. 压栈, 跳转,执行,返回:从汇编看函数调用
  3. python3 中的 eval 函数
  4. oracle获取序列并赋值,Oracle中序列的使用
  5. win7系统一直反复重启_iPhone7开机白苹果反复重启进不了系统维修过程
  6. ECC椭圆曲线加密算法原理
  7. python在统计专业的应用_Python:使用Counter进行计数统计
  8. ionic 支持float吗_机器人协会 | 一起拼机器人吗?
  9. python数据分析的步骤排序_Python数据分析
  10. axure web组件下载_Element - 饿了么团队出品的神级桌面 UI 组件库