如何在一天之内上线一款WSGI兼容的Python Web App

2018-07-12| EC2, Load Balance| 首页: https://2cloudlab.com
work-single-image

如何在一天之内上线一款WSGI兼容的Python Web App

这篇指南将通过以下4步来帮助你在一天之内上线一款WSGI兼容的Python Web App

  • 开箱即用的云原生解决方案
  • 现实情况
  • 准备和实现
  • 具体案例
  • 存在的问题

开箱即用的云原生解决方案

module_load_balancer模块用于创建WSGI兼容Web App所依赖的环境,非常适合只有Python技术栈的团队。在使用它之前,你需要参考这里来准备研发环境和了解一些注意事项。这个解决方案能够帮助你创建以下环境,你只需要提供图中Web App部分(它是基于Python来编写的并且是WSGI兼容的)。

现实情况

你拥有一支非常擅长Python的研发团队,然而却缺乏DevOps和软件工程经验。你迫切希望,你的团队能够研发一款面向互联网的服务,并能快速接入互联网。

准备和实现

首先,你需要使用Python研发一个Web App,它是WSGI兼容的,然后将其打包成tar.gz格式,包中的目录结构如下所示:

.
  |-web-app-root
  |  |-web-app
  |  |  |-wsgiapp.py
  |  |-requirements.txt
  1. web-app-root是包中的根目录,你可以重命名成其它
  2. web-app是你的Web App所有可执行性文件所在的目录
  3. wsgiapp.py是你的Web App的入口,里面定义了一个WSGI对象
  4. requirements.txt是你的Web App所依赖的Python库

其次,你需要创建main.tf文件,内容如下:

terraform {
  required_version = "= 0.12.19"
}

provider "aws" {
  version = "= 2.58"
  region = "ap-northeast-1"
}

module "load_balance" {
  source       = "github.com/2cloudlab/module_load_balancer//modules/load_balancer?ref=<tag>"
  download_url = <your-WSGI-Compatible-Python-Package-URL>
  package_base_dir         = <your-root-folder-name-in-web-app-package>
  app_dir = <your-web-app-folder>
  envs     = <your-app-environment-variables>
  wsgi_app = <WSGI-Entry>
}

output "alb_dns_name" {
  value       = module.load_balance.alb_dns_name
  description = "The domain name of the load balancer"
}

你只需要指定以下几点

  1. ref=<tag>中的tag需要替换成该模块的版本号,比如v.0.0.3
  2. download_url指向了WSGI兼容的Web App的tar.gz包,比如"https://github.com/digolds/digolds_sample/archive/v0.0.1.tar.gz”
  3. package_base_dirtar.gz中的根目录
  4. app_dir是WSGI兼容的Web App所有执行文件所在tar.gz中的目录
  5. envs是WSGI兼容的Web App所依赖的环境变量
  6. wsgi_app是WSGI兼容的Web App的调用入口,关于该模块的详细用法,你可以参考这里

指定之后,cdmain.tf所在的目录,然后执行以下命令来创建WSGI兼容的Web App:

terraform init
terraform plan
terraform apply

成功之后,你将看到以下类似的输出:

Apply complete! Resources: 10 added, 0 changed, 0 destroyed.

Outputs:

alb_dns_name = alb-1-712872544.us-west-1.elb.amazonaws.com

等待几分钟之后,你的WSGI兼容的Web App就已经在互联网中运行了,此时,你可以在浏览器里输入alb_dns_name所对应的值,来查看结果。

以上脚本帮你做了2件事情:

  1. 下载你的WSGI兼容的Web App包
  2. 在互联网上创建一个负载均衡器ALB(用于分发请求)、一族EC2实例(每个实例对应一台虚拟机,并运行着你的WSGI兼容的Web App、Nignx、gunicorn、supervisor)、一个Auto Scale资源(用于自动增加或减少EC2实例)

具体案例

下面,我将通过一个案例来说明这个模块的使用。假设,你想上线一款轻博客服务,它是用Python来实现的,而且兼容WSGI规范,这个博客应用的源码托管在这里,它对外发布的完整的tar.gz包存储在这里:“https://github.com/digolds/digolds_sample/archive/v0.0.1.tar.gz",包中的目录结构如下所示:

.
  |-digolds_sample-0.0.1
  |  |-.gitignore
  |  |-deployment
  |  |  |-load-balancer
  |  |  |  |-main.tf
  |  |  |  |-service.sh
  |  |  |-nosql
  |  |  |  |-main.tf
  |  |-personal-blog
  |  |  |-controllers
  |  |  |  |-articles_controller.py
  |  |  |  |-main_controller.py
  |  |  |  |-sign_in.py
  |  |  |-favicon.ico
  |  |  |-middlewares
  |  |  |  |-logger_middleware.py
  |  |  |-model
  |  |  |  |-articles_content.py
  |  |  |  |-in_memory_db.py
  |  |  |-static
  |  |  |  |-images
  |  |  |  |  |-digolds.png
  |  |  |-views
  |  |  |  |-blogs.html
  |  |  |  |-edit-article.html
  |  |  |  |-home.html
  |  |  |  |-sign-in.html
  |  |  |  |-single_article.html
  |  |  |  |-__base__.html
  |  |  |-wsgiapp.py
  |  |-requirements.txt

其中wsgiapp.py中的内容如下所示,尤其是要注意最后一行,我定义了一个WSGI对象wsgi_app

#!/usr/bin/env python

__author__ = 'SLZ'

'''
digwebs framework demo.
'''

import logging
logging.basicConfig(level=logging.INFO)

from digwebs.web import get_app
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
digwebs_app = get_app({'root_path':dir_path})
digwebs_app.init_all()
if __name__ == '__main__':
    import os
    os.environ['TABLE_NAME'] = 'personal-articles-table'
    os.environ['INDEX_NAME'] = 'ContentGlobalIndex'

    os.environ['USER_NAME'] = 'slz'
    os.environ['PASSWORD'] = 'abc'
    digwebs_app.run(9999, host='0.0.0.0')
else:
    wsgi_app = digwebs_app.get_wsgi_application()

接下来,编写一个main.tf文件,其内容如下所示:

terraform {
  required_version = "= 0.12.19"
}

provider "aws" {
  version = "= 2.58"
  region = "ap-northeast-1"
}

data "terraform_remote_state" "dynamodb" {
  backend = "local"

  config = {
    path = "../nosql/terraform.tfstate"
  }
}

module "load_balance" {
  source       = "github.com/2cloudlab/module_load_balancer//modules/load_balancer?ref=v0.0.4"
  download_url = "https://github.com/digolds/digolds_sample/archive/v0.0.1.tar.gz"
  package_base_dir         = "digolds_sample-0.0.1"
  app_dir = "personal-blog"
  envs     = ["USER_NAME=slz", "PASSWORD=abc"]
  wsgi_app = "wsgiapp:wsgi_app"
}

output "alb_dns_name" {
  value       = module.load_balance.alb_dns_name
  description = "The domain name of the load balancer"
}

在上面的脚本中,你要特别注意以下变量与之前的目录结构的关系:

  • download_url
  • package_base_dir
  • app_dir

另外由于这个博客应用会用到环境变量USER_NAMEPASSWORD,因此我通过envs来设置博客应用所需的环境变量。

最后,我在wsgiapp.py文件里定义了一个WSGI对象wsgi_app,因此变量wsgi_app的值应该如下所示:

wsgi_app = "wsgiapp:wsgi_app"

cd到文件main.tf所在的目录,执行以下指令来上线这个博客应用:

terraform init
terraform apply

成功之后,你将看到以下输出结果:

Apply complete! Resources: 10 added, 0 changed, 0 destroyed.

Outputs:

alb_dns_name = alb-1-712872544.us-west-1.elb.amazonaws.com

你必须等待几分钟左右,然后在浏览器中输入alb_dns_name所指向的url,访问这个博客应用,结果页面如下所示:

存在的问题

这个开箱即用的解决方案依然存在许多问题,如下所示:

  1. 它目前只支持80端口
  2. 在创建成功之后,你需要等待大约几分钟的时间,才能上线Web App
  3. 如果你需要更新Web App,那么你需要重新执行以上步骤,这也就意味着,你需要暂停之前的Web App
  4. 由于这套方案创建了ALB,一族EC2实例,因此这些资源如果闲置的时候依然会计费

听起来还不错 ?

如果你所在的企业遇到了以下问题:
研发流程混乱不堪或者效率低下、经历了持续上升的运维成本、无法及时向用户发布新的服务或产品以及想使用云计算技术但缺乏经验!
那么,请毫不犹疑地

联系我们