简介:Serverless架构带来的除了新的架构和新的编程范式之外,还包括思维上的转变,尤其是在开发过程中。有人说要把serverless架构看成是天生的分布式架构,就要用分布式架构的思想来开发serverless应用。诚然,这种说法是正确的。但是在某些情况下,Serverless还是有一些特性的,所以开发的理念需要转变。前言:在Serverless架构下,虽然更关注业务代码,但也需要关注一些配置和成本,必要时需要根据配置和成本对Serverless应用进行配置和代码优化。serverless应用开发理念的变化serverless架构除了带来新的架构和新的编程范式外,还包括思维上的变化,尤其是在开发过程中。有人说要把serverless架构看成是天生的分布式架构,就要用分布式架构的思想来开发serverless应用。诚然,这种说法是正确的。但是在某些情况下,Serverless还是有一些特性的,所以开发的理念需要转变。1、文件上传方式在传统的web框架中,上传文件是非常简单方便的,比如Python的Flask框架:f=request.files['file']f.save('my_file_path')但是在Serverless架构下,Files不能直接上传,原因如下:一般一些云平台的API网关触发器会将二进制文件转为字符串,不方便直接获取和存储;通常,API网关与FaaS平台之间传输的数据包的大小是有限制的,很多平台都将数据包的大小限制在6MB以内;大多数FaaS平台都是无状态的,即使保存在当前实例中,当实例释放时文件也会丢失。因此,传统Web框架中常用的文件上传方案并不适合在Serverless架构中直接使用。在Serverless架构中,上传文件通常有两种方式:一种是转换成Base64格式后上传,持久化到对象存储或NAS,但是API网关和API网关之间传输的数据包有大小限制。FaaS平台,所以这种方式通常适用于上传头像等小文件的业务场景。另一种上传方式是通过对象存储等平台上传。因为客户端直接通过密钥等方式将文件上传到对象存储,存在一定的风险。执行预签名操作,将预签名地址返回给客户端,客户端使用指定方法上传。上传完成后,通过对象存储触发器等方式更新上传结果,如下图所示。Serverless架构下上传文件的例子以阿里云函数计算为例,使用Bottle实现了以上两种常见的上传方式。在函数计算中,首先初始化对象存储相关的对象:初始化对象存储相关的对象:AccessKey={"id":'',"secret":''}OSSConf={'endPoint':'oss-cn-hangzhou.aliyuncs.com','bucketName':'bucketName','objectSignUrlTimeOut':60}#获取/上传文件到OSS临时地址auth=oss2.Auth(AccessKey['id'],AccessKey['secret'])bucket=oss2.Bucket(auth,OSSConf['endPoint'],OSSConf['bucketName'])#对象存储操作getUrl=lambdaobject,method:bucket.sign_url(method,object,OSSConf['objectSignUrlTimeOut'])getSignUrl=lambdaobject:getUrl(object,"GET")putSignUrl=lambdaobject:getUrl(object,"PUT")#GetrandomstringrandomStr=lambdalen:"".join(random.sample('abcdefghijklqrstuvwxyz123456789SAABCDEFGZ*100,len))第一种上传方式,Base64上传后,持久化文件到对象存储:#FileUpload#URI:/file/upload#Method:POST@bottle.route('/file/upload',"POST")defpostFileUpload():尝试:图片库64=bottle.request.GET.get('picture','').split("base64,")[1]object=randomStr(100)withopen('/tmp/%s'%object,'wb')作为f:f.write(base64.b64decode(pictureBase64))bucket.put_object_from_file(object,'/tmp/%s'%object)returnresponse({"status":'ok',})除了Exceptionase:print("Error:",e)returnresponse(ERROR['SystemError'],'SystemError')第二种上传方式是获取预签名对象存储地址,然后在客户端发起上传请求直接上传到对象存储:#Get文件上传地址#URI:/file/upload/url#Method:GET@bottle.route('/file/upload/url',"GET")defgetFileUploadUrl():try:object=randomStr(100)returnresponse({"upload":putSignUrl(object),"download":'https://download.xshu.cn/%s'%(object)})exceptExceptionase:print("Error:",e)返回响应(ERROR['SystemError'],'SystemError')HTML部分:在网络上上传文件
