如何在一天之内上线一款WSGI兼容的Python Web App
如何在一天之内上线一款WSGI兼容的Python Web App
这篇指南将通过以下4步来帮助你在一天之内上线一款WSGI兼容的Python Web App:
- 开箱即用的云原生解决方案
- 现实情况
- 准备和实现
- 具体案例
- 存在的问题
开箱即用的云原生解决方案
module_load_balancer模块用于创建WSGI兼容Web App所依赖的环境,非常适合只有Python技术栈的团队。在使用它之前,你需要参考这里来准备研发环境和了解一些注意事项。这个解决方案能够帮助你创建以下环境,你只需要提供图中Web App部分(它是基于Python来编写的并且是WSGI兼容的)。
image现实情况
你拥有一支非常擅长Python的研发团队,然而却缺乏DevOps和软件工程经验。你迫切希望,你的团队能够研发一款面向互联网的服务,并能快速接入互联网。
准备和实现
首先,你需要使用Python研发一个Web App,它是WSGI兼容的,然后将其打包成tar.gz
格式,包中的目录结构如下所示:
.
|-web-app-root
| |-web-app
| | |-wsgiapp.py
| |-requirements.txt
-
web-app-root
是包中的根目录,你可以重命名成其它 -
web-app
是你的Web App所有可执行性文件所在的目录 -
wsgiapp.py
是你的Web App的入口,里面定义了一个WSGI对象 -
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"
}
你只需要指定以下几点
-
ref=<tag>
中的tag
需要替换成该模块的版本号,比如v.0.0.3 -
download_url
指向了WSGI兼容的Web App的tar.gz包,比如"https://github.com/digolds/digolds_sample/archive/v0.0.1.tar.gz" -
package_base_dir
是tar.gz中的根目录 -
app_dir
是WSGI兼容的Web App所有执行文件所在tar.gz中的目录 -
envs
是WSGI兼容的Web App所依赖的环境变量 -
wsgi_app
是WSGI兼容的Web App的调用入口,关于该模块的详细用法,你可以参考这里
指定之后,cd
到main.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件事情:
- 下载你的WSGI兼容的Web App包
- 在互联网上创建一个负载均衡器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_NAME和PASSWORD,因此我通过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,访问这个博客应用,结果页面如下所示:
image存在的问题
这个开箱即用的解决方案依然存在许多问题,如下所示:
- 它目前只支持80端口
- 在创建成功之后,你需要等待大约几分钟的时间,才能上线Web App
- 如果你需要更新Web App,那么你需要重新执行以上步骤,这也就意味着,你需要暂停之前的Web App
- 由于这套方案创建了ALB,一族EC2实例,因此这些资源如果闲置的时候依然会计费