在服务器端实现无间断部署Python应用的教程

当你开始着手部署应用时,最简单的方式莫过于使用管理员身份重启my_app或者所有服务,使产品升级至当前版本。开始的时候一切都很好,但是最终你会发现一旦应用启动以后,在重启期间去尝试连接会得到众多HTTP 503 错误。

最后你可能发现Gunicorn和uWSGI可以在不关闭套接字的情况下重新加载你的应用,这样在你的应用启动时,网络请求仅仅是被延时了一点点。只要你的应用不会花费很长时间在启动上,它就会工作的很好。不幸的是,现有的许多应用可能会花费1分钟的时间在启动上,对于等待在套接字上的链接来说,这太长了。

Gunicorn使用kill -HUP $PID,通过关闭所有工作进程,然后再启动它们来重新加载。但是工作进程缓慢的初始化过程往往会导致问题的产生。uWSGI使用链式重载,它每次只会启动一个工作进程。我需要对Tornado的支持,它当前并不十分适合uWSGI。

使用负载均衡器

一种常见的技术是从负载均衡器中移除单个服务器,升级/重启应用,然后再把它加载回来。我们正在使用负载均衡器,但是为了调度整个过程,在配置节点的时候需要协调使用HAProxy来管理套接字。我们当前的部署方案是同时部署到所有节点,而不是一个接一个的来,一个相当大的变化。在等待LBs(译注:负载均衡器)将节点移出池期间,可以使用404'ing状态页来欺骗healthcheck。这比我想要的时间要多一点,对于每个服务器来说,两次healthcheck失败间隔5秒钟,这包括了升级完成后web进程恢复的时间。

Gunicorn 重载 ++

Gunicorn会自动重启失败的web进程,所以它可能会杀掉每个进程,在其间休眠,直到所有的子进程执行完毕。这很有效,不过如果应用启动的次数变动显著的话,我们要么会为重启等待过长时间,要么会等待不长的时间并承担一些故障宕机的风险。

因为Gunicorn包含了指向应用的Python钩子,所以完全可能写出一小段代码,在工作进程准备就绪的时候通知重启进程。Gunicorn并不包含需要的钩子,但做出改变非常简单。在新版本发布前它需要一些修改。

现在重启进程发挥了这样的事实优势,就是说单个的soket具有接受连接的多个进程。重启只会极微弱的减少服务能力(1/N),但我们因此可以继续处理流量而无需让连接等待过长时间。

这种进程一般是这样的

for child_pid of gunicorn-master:
 kill child_pid
 wait for app startup

我的第一个版本使用shell和nc来监听应用启动的UDP数据包。尽管将我们的进程管理器集成到shell环境比我预想的要麻烦一点,但它工作的很好。

重启脚本被调用的时候应该带上Gunicorn的PID,就是masterrestart.sh的 $PID

echo 'Killing children of ' $1;

children=$(pgrep -P $1)
for child in $children
do
 echo 'Killing' $child
 kill $child
 response=$(timeout 60 nc -w 0 -ul 4012)
 if [ "$response" != '200 OK' ]; then
  echo 'BROKEN'
  exit 1;
 fi
done

在串联上post_worker_init脚本,以便app运行的时候通知重启脚本。

import socket
import time

def post_worker_init(worker):
 _send_udp('200 OK\n')

def _send_udp(message):

 udp_ip = "127.0.0.1"
 udp_port = 4012

 sock = socket.socket(socket.AF_INET, # Internet
       socket.SOCK_DGRAM) # UDP
 sock.sendto(message, (udp_ip, udp_port))
如果我们有这样一个WSGI( Python Web Server Gateway Interface)应用:

from werkzeug.wrappers import Request, Response

@Request.application
def application(request):
 resp = Response('Hello World!')
 if request.path == '/_status':
  resp.status = '200 OK'
 else:
  resp.status ='404 Not Found'
 return resp

我们甚至可以去做检查/_status页面之类的事情,以此来验证应用是否已运行。

def post_worker_init(worker):
 env = {
  'REQUEST_METHOD': 'GET',
  'PATH_INFO': '/_status',
 }
 def start_response(*args, **kwargs):
  _send_udp(args[0])

 worker.wsgi(env, start_response)

注意不要试图在这个健康检测中运行太多的应用,如果不管什么原因你的post_worker_init产生了一个错误,那么工作进程将会退出,并阻止应用的启动。在你检查可能失效的DB链接的时候这会是一个问题,即使你的应用可以工作,它也无法再次启动。

现在通过一分钟的应用启动,我们实现了滚动重启,而无需停止应用或者丢弃任何链接!

(0)

相关推荐

  • Python计算程序运行时间的方法

    本文实例讲述了Python计算程序运行时间的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: import time def start_sleep():     time.sleep(3) if __name__ == '__main__':     #The start time     start = time.clock() #A program which will run for 3 seconds     start_sleep() #The End time

  • Python 抓取动态网页内容方案详解

    用Python实现常规的静态网页抓取时,往往是用urllib2来获取整个HTML页面,然后从HTML文件中逐字查找对应的关键字.如下所示: 复制代码 代码如下: import urllib2 url="http://mm.taobao.com/json/request_top_list.htm?type=0&page=1" up=urllib2.urlopen(url)#打开目标页面,存入变量up cont=up.read()#从up中读入该HTML文件 key1='<a

  • Python编程中的反模式实例分析

    本文实例讲述了Python编程中的反模式.分享给大家供大家参考.具体分析如下: Python是时下最热门的编程语言之一了.简洁而富有表达力的语法,两三行代码往往就能解决十来行C代码才能解决的问题:丰富的标准库和第三方库,大大节约了开发时间,使它成为那些对性能没有严苛要求的开发任务的首选:强大而活跃的社区,齐全的文档,也使很多编程的初学者选择了它作为自己的第一门编程语言.甚至有国外的报道称,Python已经成为了美国顶尖大学里最受欢迎的编程入门教学语言. 要学好一门编程语言实属不易,在初学阶段,就

  • 在服务器端实现无间断部署Python应用的教程

    当你开始着手部署应用时,最简单的方式莫过于使用管理员身份重启my_app或者所有服务,使产品升级至当前版本.开始的时候一切都很好,但是最终你会发现一旦应用启动以后,在重启期间去尝试连接会得到众多HTTP 503 错误. 最后你可能发现Gunicorn和uWSGI可以在不关闭套接字的情况下重新加载你的应用,这样在你的应用启动时,网络请求仅仅是被延时了一点点.只要你的应用不会花费很长时间在启动上,它就会工作的很好.不幸的是,现有的许多应用可能会花费1分钟的时间在启动上,对于等待在套接字上的链接来说,

  • 在Docker上开始部署Python应用的教程

    几周前, Elastic Beanstalk声明在AWS云中配置和管理Docker容器.在本文中,我们通过一个简单的注册表单页面应用去理解Docker部署过程,该表单使用Elastic Beanstalk Python环境. 关于注册表单应用 几个月之前,我们就已经开发完这个应用并且发表在博客上.有4部分视频和一篇文章"Using DynamoDB and SNS with Elastic Beanstalk in any Supported AWS Region".今天,我们将在这部

  • 无间断滚动效果 htc

    marquee.htc 复制代码 代码如下: //  描述        : 无间断滚动字幕 //  版本        : 2.0 //  作者        : 宝玉(WebUC.NET) //  最新更新    : 2004-10-26 //  备            : <public:component> <public:attach event="oncontentready" onevent="f_Init()" /> <

  • 兼容IE和Firefox火狐的上下、左右循环无间断滚动JS代码

    html里的marqueen也能实现内容的滚动,但滚动是间断的,在滚动一个周期中,会有一段空白出现.如果滚动的区域比较大,空间的出现,会让页面看起来很不美观.运用JavaScript可以使这一问题得到改观,实现无间断的滚动. 上下循环滚动代码: 复制代码 代码如下: <div id="demo" onmouseover="clearInterval(inter)" onmouseout="inter=setInterval(qswhMarquee,3

  • 无间断滚动的新闻文章列表 多浏览器兼容

    Fifty Studio│无间断滚动的新闻文章列表 @import url("/tutorials/demo/css/ie.css"); #demo{overflow:auto; } } CSS 布局演示 CSS Layout by Forestgan 2006-11-1 发表 三列自适应宽度液态布局│Three Column Liquid Layouts Internet Explorer 7 对CSS的兼容--Box Model Changes 未知大小的图片在一个已知大小容器中的

  • apache部署python程序出现503错误的解决方法

    前言 本文主要给大家介绍了解决apahce部署python程序出现503错误的相关内容,下面话不多说了,下一起看看详细的介绍吧. 发现问题 今天更新服务器后,发现使用apache部署的某个python程序无法访问了,返回503错误,报错日志如下: [Thu Apr 13 10:54:40 2017] [error] [client 127.0.0.1] (13)Permission denied: mod_wsgi (pid=1814): Unable to connect to WSGI da

  • 无间断滚动的新闻文章列表,兼容IE、Firefox和Opera,符合W3C标准。可作Marquee

    <!--Quirks Mode--> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv=&

  • Linux部署python爬虫脚本,并设置定时任务的方法

    去年因项目需要,用python写了个爬虫.因爬到的数据需要存到生产环境的PG数据库.所以需要将脚本部署到CentOS服务器,并设置定时任务,自动启动脚本. 实施步骤如下: 1.安装pip(操作系统自带了python2.6可以直接用,但是没有pip) # 下载pip安装包 wget "https://pypi.python.org/packages/source/p/pip/pip-1.5.4.tar.gz#md5=834b2904f92d46aaa333267fb1c922bb" --

  • iOS实现文字水平无间断滚动效果

    IOS跑马灯效果,实现文字水平无间断滚动,示例代码如下: ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIViewController{ NSTimer *timer; UIScrollView *scrollViewText; } @property (nonatomic ,strong) NSArray *arrData; @end ViewController.m // // ViewContr

  • Docker如何部署Python项目的实现详解

    Docker 是一个开源项目,为开发人员和系统管理员提供了一个开放平台,可以将应用程序构建.打包为一个轻量级容器,并在任何地方运行.Docker 会在软件容器中自动部署应用程序. 在本篇中,我将介绍如何 docker 化一个 Python Django 应用程序,然后使用一个 docker-compose 脚本将应用程序作为容器部署到 docker 环境. 环境 操作系统 dbnuo@localhost ~ sw_vers ProductName: Mac OS X ProductVersion

随机推荐