这篇文章适合所有的python开发新手、老鸟以及想准备学习开发python的程序猿。本文以一个基于django开源的个人博客移植到函数计算为例,向您讲解如何使用阿里云函数计算快速构建或移植基于wsgi applicaiton开发的web service。通过本文,您将会了解以下内容:
在本教程中,我们讲解如何利用函数计算一步一步来构建web的server端,该案例是基于github上一个star很高的一个开源个人博客,在本案例中,不讨论基于wsgi applicaiton的程序开发,本文旨在展示函数计算做web backend 能力,具体表现为以下几点:
后台:http://1986114430573743.cn-hongkong.fc.aliyuncs.com/2016-08-15/proxy/blog-service/blog/admin
正常来说,用户开发server端服务,常常面临开发效率,运维成本高,机器资源弹性伸缩等痛点,而使用Serverless架构可以很好的解决上述问题。下面是传统架构和Serverless架构的对比:
阿里云函数计算是一个事件驱动的全托管计算服务。通过函数计算,您无需管理服务器等基础设施,只需编写代码并上传。函数计算会为您准备好计算资源,以弹性、可靠的方式运行您的代码,并提供日志查询,性能监控,报警等功能。借助于函数计算,您可以快速构建任何类型的应用和服务,无需管理和运维。
从上面的示例图中,整体架构十分简单明了, 用FC替代了web服务器,但是换来的是免运维,弹性扩容,按需付费等一系列优点
是的,函数计算具有http trigger 功能, 详情
如入口函数代码所示, 在调用django application之前设置好
HTTP_HOST
和SCRIPT_NAME
,HTTP_HOST
和SCRIPT_NAME
具体意义可以参考wsgi pep-0333
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_FC_URL = STATIC_URL
如入口函数代码所示, 在调用django application之前设置好settings.STATIC_URL,同时在urls.py 设置好路由:
urlpatterns += static(settings.STATIC_FC_URL, document_root=settings.STATIC_ROOT)
- 正常的数据库迁移,先导出数据库数据,然后直接导入,很多客户端工具或者命令行工具都支持
- 初始化数据库,直接配置好对应的配置文件,使用
python manage.py migrate
命令即可
python 3.6, django 1.11 配置mysql数据库
可以将文件上传到oss,然后在html页面上引用oss link
# coding=utf-8
import sys
import os
# load local django
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "blogproject"))
import django
print (django.__version__)
from urllib.parse import urlparse
from blogproject.wsgi import application
from django.conf import settings
base_path = None
def handler(environ, start_response):
# 如果没有使用自定义域名
if environ['fc.request_uri'].startswith("/2016-08-15/proxy"):
request_uri = environ['fc.request_uri']
parsed_tuple = urlparse(request_uri)
li = parsed_tuple.path.split('/')
global base_path
if not base_path:
base_path = "/".join(li[0:5])
settings.STATIC_URL = base_path + settings.STATIC_FC_URL
context = environ['fc.context']
environ['HTTP_HOST'] = '{}.{}.fc.aliyuncs.com'.format(context.account_id, context.region)
environ['SCRIPT_NAME'] = base_path + '/'
return application(environ, start_response)
创建并激活虚拟环境,在命令行进入到保存虚拟环境的文件夹,输入如下命令创建并激活虚拟环境:
virtualenv blogproject_env
# windows
blogproject_env\Scripts\activate
# linux/mac
source blogproject_env/bin/activate
如果不想使用虚拟环境,可以跳过这一步
git clone https://github.com/zmrenwu/django-blog-tutorial.git
pip install -t . -r requirements.txt
修改相应的配置文件,确保在本地能正常运转
使用本地的django库,修改的文件manage.py
, 在函数逻辑之前增加两句如下代码:
sys.path.insert(0,os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import django
修改setting.py 中的DATABASES,修改成连接自己本地mysql
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django-blog', #数据库名
'USER': 'root', #用户名
'PASSWORD': 'Passw0rd', #密码
'HOST': '127.0.0.1',
'PORT': '3306',
'CHARSET':'utf8',##设置字符集,不然会出现中文乱码
}
}
ALLOWED_HOSTS = ['*']
python manage.py migrate
如果这里正常执行,应该会自己本地mysql数据库能看到相关table创建成功
python manage.py createsuperuser
python manage.py runserver
在浏览器输入:127.0.0.1:8000
由于函数运行时的IP是不固定的,您需要设置RDS允许所有IP访问。但是这样会有风险,不建议这样做。在本教程中,我们将创建一个rds mysql 数据库,并将它置于一个专有网络VPC环境内,函数计算会支持VPC功能,用户可以通过授权的方式安全地访问VPC中的资源。
配置函数计算访问 VPC 内的资源, 假设配置完毕后,我们这里的vpc config 如下:
VpcConfig:
VpcId: 'vpc-j6c4u85w9m4ovnvf45x76'
VSwitchIds: [ 'vsw-j6cuqvtuc041zyvm415xx' ]
SecurityGroupId: 'sg-j6c35vamnn01ekx91xx'
InternetAccess: true
npm install git://github.com/aliyun/fun.git --save -g
main.py
入口函数代码
setting.py
和urls.py
注:涉及到setting的修改,可以使用函数计算的环境变量功能, 不用将这些配置信息写死到代码中,大大提高了函数灵活性。环境变量是在函数级别的,以键值对的方式存储作为函数配置的一部分,即一个服务的不同函数拥有不同的环境变量,并且互不影响。环境变量的主要用途是代码和配置相分离,提高代码的灵活性和可移植性。比如
DATABASES
DATABASES = {
'default': {
'ENGINE': os.environ['CUSTOM_DB_ENGINE'], # engine,django.db.backends.mysql
'NAME': os.environ['CUSTOM_DB_NAME'], # 数据库名, django-blog
'USER': os.environ['CUSTOM_DB_USER_NAME'], # 用户名,root
'PASSWORD': os.environ['CUSTOM_DB_USER_PWD'], # 密码,Passw0rd
'HOST': os.environ['CUSTOM_DB_HOST'] # 比如 '127.0.0.1',
'PORT': os.environ['CUSTOM_DB_PORT'] # 比如'3306',
'CHARSET':'utf8', #设置字符集,不然会出现中文乱码
}
}
template.yml
和.env
template.yml example
ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
blog-pro:
Type: 'Aliyun::Serverless::Log'
Properties:
Description: 'blog log pro'
fc-log:
Type: 'Aliyun::Serverless::Log::Logstore'
Properties:
TTL: 362
ShardCount: 1
blog-service:
Type: 'Aliyun::Serverless::Service'
Properties:
Description: 'django blog demo'
Policies:
- AliyunOSSFullAccess
LogConfig:
Project: 'blog-pro'
Logstore: 'fc-log'
VpcConfig:
VpcId: 'vpc-j6c4u85w9m4ovnvfxxxxx'
VSwitchIds: [ 'vsw-j6cuqvtuc04xxxxxx5m6' ]
SecurityGroupId: 'sg-j6c35vabbbbbbbx91vh6'
InternetAccess: true
blog:
Type: 'Aliyun::Serverless::Function'
Properties:
Handler: main.handler
CodeUri: './'
Description: 'django blog http function'
Runtime: python3
Timeout: 60
MemorySize: 512
Events:
http-test:
Type: Http
Properties:
AuthType: ANONYMOUS
Methods: ['GET', 'POST', 'PUT']
.env example
DEFAULT_REGION=cn-hongkong
ACCOUNT_ID=12345
ENDPOINT=http://12345.cn-hongkong.fc.aliyuncs.com
ACCESS_KEY_ID=LTAItxxxx
ACCESS_KEY_SECRET=WIcnJJO7ZGoTUyyyyyyyyyy
fun deploy
, template.yml 里面的相关资源就能准确创建和配置http://${account_id}.${region}.fc.aliyuncs.com/2016-08-15/proxy/$(seevice_name}/{function_name}/
比如:
http://1221968287646227.cn-hongkong.fc.aliyuncs.com/2016-08-15/proxy/blog-service/blog/
用户可以在github地址下载完整的案例代码
函数计算有如下优势:
除了上面所列的优势,FC 可以做为web backend,只需要修改一些配置文件就可以将wsgi 框架开发的工程迁移到FC,从而从传统的web网站运维,监控等繁琐的事务中解放出来