环境安装
在此案例中,使用阿里云服务器。(Linux)
使用官方安装脚本自动安装
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
- 安装fun
npm install @alicloud/fun -g
- 配置fun,按提示输入信息
fun config
基础:创建Helloworld文件
1. 创建一个文件夹,如image_crawler2. 创建一个文件template.yml,内容ROSTemplateFormatVersion: '2015-09-01'Transform: 'Aliyun::Serverless-2018-04-03'Resources:localdemo:Type: 'Aliyun::Serverless::Service'Properties:Description: 'local invoke demo'image-crawler:Type: 'Aliyun::Serverless::Function'Properties:Handler: index.handlerCodeUri: code/Description: 'Hello world with python2.7!'Runtime: python2.73. 创建一个code文件夹,在文件夹中编写helloworld代码def handler(event, context):return 'hello world!'4. 运行函数fun local invoke image-crawler

进阶:设置oss转存任务,如一个image_crawler
- 获取网页源代码,按上述语句运行image-crawler,可看到变化。
import loggingimport jsonimport urlliblogger = logging.getLogger()def handler(event, context):logger.info("event: " + event)evt = json.loads(event)url = evt['url']html = get_html(url)logger.info("html content length: " + str(len(html)))return 'Done!'def get_html(url):page = urllib.urlopen(url)html = page.read()return html
- 运行以下语句可看到变化
echo '{"url":"http://huaban.com/search/?q=%e5%a3%81%e7%ba%b8"}' | fun local invoke image-crawler
- 添加函数,从源代码中抽取图片路径
def get_img(html):reg = r'https:\/\/[^\s,"]*\.jpg'imgre = re.compile(reg)return re.findall(imgre, html)
- 调整替换原先的handler函数,使之从“获取网页源代码”功能转变为“获取图片路径功能”。
def handler(event, context):logger.info("event: " + event)evt = json.loads(event)url = evt['url']html = get_html(url)img_list = get_img(html)logger.info(img_list)return 'Done!'
- 将图片上传到OSS中,在 template 中配置环境变量(需提前创建好 oss bucket):
EnvironmentVariables:OSSEndpoint: oss-cn-hangzhou.aliyuncs.comBucketName: fun-local-test
- 然后就可以直接在函数中获取到这两个环境变量了:
endpoint = os.environ['OSSEndpoint']bucket_name = os.environ['BucketName']
- 设置OSS的STS权限控制,参考如下代码
creds = context.credentialsif (local):auth = oss2.Auth(creds.access_key_id,creds.access_key_secret)else:auth = oss2.StsAuth(creds.access_key_id,creds.access_key_secret,creds.security_token)bucket = oss2.Bucket(auth, endpoint, bucket_name)
- 遍历所有图片文件,并且转存到OSS中
count = 0for item in img_list:count += 1logging.info(item)# Get each picturepic = urllib.urlopen(item)# Store all the pictures in oss bucket, keyed by timestamp in microsecond unitbucket.put_object(str(datetime.datetime.now().microsecond) + '.png', pic)
- 完整的代码
import logging,datetimeimport json,re,oss2import requests,urllib,oslogger = logging.getLogger()endpoint = os.environ['OSSEndpoint']bucket_name = os.environ['BucketName']local = 1def handler(event, context):logger.info("event: " + event)evt = json.loads(event)url = evt['url']print(url)creds = context.credentialsif (local):auth = oss2.Auth(creds.access_key_id,creds.access_key_secret)else:auth = oss2.StsAuth(creds.access_key_id,creds.access_key_secret,creds.security_token)bucket = oss2.Bucket(auth, endpoint, bucket_name)html = get_html(url)img_list = get_img(html)logger.info(img_list)iii(img_list,bucket)return 'Done!'def iii(img_list,bucket):count = 0for item in img_list:count += 1logging.info(item)pic = urllib.urlopen(item)if pic != None:bucket.put_object(str(datetime.datetime.now().microsecond) + '.jpg', pic)def get_img(html):reg = r'http:\/\/[^,"]*\.jpg'imgre =re.compile(reg)return re.findall(imgre,html)def get_html(url):page = requests.get(url)html = page.contentreturn html
- 此时运行如下命令可看到成功效果。
echo '{"url":"http://huaban.com/search/?q=%e5%a3%81%e7%ba%b8"}' | fun local invoke image-crawler
部署
- 添加OSS权限到yaml中,此次是添加了policies:AliyunOSSFullAccess。注意localdemo这个函数计算项目及image-crawler这个函数,fun-local-test这个OSS项目bucket需要事先在阿里云官网后台配置过。
ROSTemplateFormatVersion: '2015-09-01'Transform: 'Aliyun::Serverless-2018-04-03'Resources:localdemo:Type: 'Aliyun::Serverless::Service'Properties:Description: 'local invoke demo'Policies: AliyunOSSFullAccessimage-crawler:Type: 'Aliyun::Serverless::Function'Properties:Handler: index.handlerCodeUri: code/Description: 'Hello world with python2.7!'Runtime: python2.7EnvironmentVariables:OSSEndpoint: oss-cn-hangzhou.aliyuncs.comBucketName: fun-local-test
- 使用fun deploy 即看到运行成功。

- 登录阿里云函数计算后台,可以看到这个项目代码,可以线上修改配置。
思考:函数计算适合做什么用途?
定时任务,如爬虫类。(图片转存、文字转存等)
pipeline类别,如接受A信息,转存到B信息及格式。根据if,else等来分类的任务。
微信,钉钉等公众号的后端(Flask),免去搭建服务器。
可以一个函数就解决的任务与项目,特别简单的项目。
阿里云官方函数计算后台提供Flask-web类型的函数计算模块,可以快速搭建外网api可访问的接口与页面。
似乎不适合多轮交互的情况(也可能是我不知道)。
威胁建模与安全方面考虑:
通过这种方式,若是允许外网访问(触发器允许HTTP),似乎易受CSRF、越权漏洞攻击。
近期阿里云函数计算更新模块,所有HTTP通过浏览器访问会默认变成将Response下载到本地,因此不会存在XSS风险。(除非本地又渲染了)
Json劫持模块还没测试,如果返回值写的是Jsonp,那么因写法太灵活,也是易受Json劫持漏洞攻击的。
如果以一个serverless租户的身份写扫描器去扫描宿主机,会不会影响到其他租户的安全与稳定性?(待测试)
