本文做者:IMWeb IMWeb团队 原文出处:IMWeb社区 未经赞成,禁止转载html
导语: 提及当前最火的技术,除了最新的区块链,AI,还有一个不得不提的概念是Serverless。Serverless做为一种新型的互联网架构直接或间接推进了云计算的发展,从AWS Lambda到各厂商争先推出Serverless服务框架,Serverless一路高歌。在这个风口,前端好像都要作点什么?前端
1、Serverless简介node
2、一个轻量web Application迁移实践linux
本章简单介绍一下Serverless的演变过程、Serverless是什么,其优缺点以及适合的应用场景。git
云计算的发展从IaaS,PaaS,SaaS,到最新的BaaS,FasS,在这个趋势中serverless(去服务器化)愈来愈明显。github
Bare Metal(IDC):web
物理机托管redis
IAAS:docker
IaaS(Infrastructure as a Service) 基础设施即服务,__服务商提供底层/物理层基础设施资源(服务器,数据中心,环境控制,电源,服务器机房),用户须要经过IaaS提供的服务平台购买虚拟资源,选择操做系统,安装软件,部署程序,监控应用。数据库
目前知名的IaaS平台有AWS,Azure,Google Cloud Plantform,腾讯云服务,阿里云以及开源的OpenStack等。
PAAS:
PaaS(Platform as a Service) 平台即服务,服务商提供基础设施底层服务,提供操做系统(Windows,Linux)、数据库服务器、Web服务器、负载均衡器和其余中间件,相对于IaaS客户仅仅须要本身控制上层的应用程序部署与应用托管的环境。
目前知名的PaaS平台有 Amazon Elastic Beanstalk,Azure,Google App Engine,腾讯容器服务,VMware Cloud Foundry等。
BAAS:
BaaS(Backend as a Service) 后端即服务,服务商为客户(开发者)提供整合云后端的服务,如提供文件存储、数据存储、推送服务、身份验证服务等功能,以帮助开发者快速开发应用。
FAAS:
FaaS(Function as a Service) 函数即服务,服务商提供一个平台,容许客户开发、运行和管理应用程序功能,而无需构建和维护基础架构。 按照此模型构建应用程序是实现“无服务器”体系结构的一种方式,一般在构建微服务应用程序时使用。
虚拟化与隔离
从最先的物理服务器开始,咱们都在不断地抽象或者虚拟化服务器。
服务器发展
咱们使用 XEN、KVM等虚拟化技术,隔离了硬件以及运行在这之上的操做系统。 咱们使用云计算进一步地自动管理这些虚拟化的资源。 咱们使用 Docker 等容器技术,隔离了应用的操做系统与服务器的操做。 如今,咱们有了 Serverless,咱们能够隔离操做系统,乃至更底层的技术细节。
无状态
但也决定了Serverless的无状态特性,由于每次函数执行,可能使用的都是不一样的容器,没法进行内存或数据共享。若是要共享数据,则只能经过第三方服务,好比 Redis,COS 等。
无运维
使用 Serverless 咱们不须要关心服务器,不须要关心运维。这也是 Serverless 思想的核心。
事件驱动编程 Serverless 的运行才计算,便意味着他是事件驱动式计算。
低成本
使用 Serverless 成本很低,由于咱们只须要为每次函数的运行付费。函数不运行,则不花钱,也不会浪费服务器资源。
Serverless 是一种 “无服务器架构”,让用户无需关心程序运行环境、资源及数量,只要将精力 Focus 到业务逻辑上的技术。
FAAS(函数即服务) + BAAS(后台即服务) 能够称为一个完整的 Serverless 的实现。
Serverless Cloud Function(SCF)架构
Python 2.7 & 3.六、Node.js 6.10 & Node.js 8.九、Java 八、Php 5 & Php 七、Go 1.八、C#&C++(规划中)
虽然目前来讲Serverless仍是有很多的局限性,Serverless一直在发展完善中,广大开发者和服务提供者都在寻找Serverless的无限可能。
本章基于腾讯云函数从架构迁移和开发部署流程去说明一个Web Application的迁移实践。
咱们先来看看一个通常Web Application在SCF上的的架构。
静态资源
静态资源(JS/CSS/IMG/HTML)放在COS(对象存储),COS能够自定义域名和开启CDN加速(具体请查看腾讯云文档《配置自定义域名支持 HTTPS 访问》),经过URL直接访问,这和原来的Web Application没有什么区别。
若是咱们是一个单页面异步应用,也就是咱们的页面html也是静态资源,你能够选择放在SCF中去返回,就像一个普通的web server返回静态资源同样,可是纯静态资源用SCF去返回总以为大材小用,既耗费了运行资源,性能也不够好。还能够放在COS上去存储,而且COS也能够支持自定义域名和开启CDN加速。
可是这样一来主域和动态数据的域名就存在跨域的问题,经过下面的方法就能够轻易解决这个问题。
支持跨域访问:能够经过API网关设置支持CORS或者后端程序设置CORS。
性能优化:在页面中header头中使用preconnect进行动态API的预链接,能够大大减小DNS/TCP/SSL的时间,别小看这个时间,由于目前腾讯云的云函数对应的API网关只支持一地接入,地域比较远的地方,这个时间能够达到几百ms。
API网关+应用逻辑
从原来的nodeServer到云函数的架构变化主要以下:
其中API GATEWAY EVENT的格式
你能够选择在代码中直接去解析使用API GATEWAY EVENT,以及封装HTTP响应体。HTTP基本上使用获得的相关的数据字段,API GATEWAY EVENT中字段都有,只是以不一样的数据结构出现。若是咱们已经很习惯express的开发框架,并且很依赖一些好用的中间件,若是咱们须要重建这部分中间件,这会是不小工做量。--那咱们有没有方案兼容原来的写法?
不管是迁移仍是新开发的项目其实均可以采用这个架构:
咱们能够将API网关事件转换成http请求,经过本地socket和函数起nodeserver进行通讯。
那么中间通过了一层服务的转发,性能会不会有所损耗呢?在统计耗时来看,有了这一层转发,总共云函数平均耗时也在20ms以内,那么中间即便有性能损耗也在10ms以内了,并且是经过本地的socket进行通讯的,相对于网络耗时来讲,就是大巫见小巫了。
中间转发代理层已经有一些可用的框架(serverlessplus, scf-framework),你们能够尝试一下,用法都比较简单。
数据存储
因为Serverless的架构是事件触发,用完即释放,那么你必定要考虑的是,你的本地存储和缓存必须依赖于第三方服务如cos和redis,不过能够经过实例保留或者它自己会有3分钟的释放延迟时间,你依然能够利用本地存储和内存缓存做为你的第一级缓存。
一、DB
和原来的DB使用没有太大的区别。
通常咱们选择与公司内网打通的VPC内申请资源,这样安全系数比较高,与外网彻底隔离,经过选择相同的子网,才能连通。
资源申请在下文开发部署篇会说到。
也能够选择纯外网的DB资源,而后经过创建虚拟子网,和腾讯云函数设置同一个子网内,云函数就能够经过内网IP进行访问。另外DB也能够设置外网域名地址,经过外网访问,这样本地开发的时候也能够访问到了,通常测试时使用。
数据库实例界面:
二、内存缓存
如上面所说,实例会有一个延迟销毁时间,若是短期内命中同一个实例,实例中内存变量是能够被缓存住的。须要缓存的内容能够两级缓存,先从内存中读取,读取不到再到Redis中读取。
Redis的使用和DB相似,申请资源,设置子网,经过IP PORT进行链接使用。
能够经过下面封装的npm包进行Redis简单使用。
npm i qcloud-serverless-redis
三、文件存储
Serverless可写的目录是/tmp/, 可是会随着实例释放而释放,因此只能临时放一下。
总共大小只有512M,建议临时文件用完要主动删除。
若是要长期存储的文件,可使用COS进行存储。
具体COS操做能够参考腾讯云文档 如: Node.js SDK 快速入门
我这里也简单封装了一个cos的npm包,能够快速尝试一下cos的存取功能,具体用法看里面的README
tnpm i @tencent/serverless-cos
登陆相关
这个解决方案同数据存储相似,能够经过第三方服务来保存状态或者经过token加解密来进行状态保存。
下面这个方案是经过token的加解密来进行登陆状态检查的,登陆验证过程是调用了原有的后台服务。
而小程序是没有cookie这个概念的,也就是小程序不会帮你set-cookie,保存cookie,发送cookie,这些都须要你本身模拟来作。如今的通用方案通常是前端接收后端返回的内容,保存在localStorage中,每次请求的时候校验有效期,并将token设置到header中的cookie模块,后端能够正常拿到cookie进行验证。
性能调优
第一章说到Serverless其实不适合对时延有比较高要求的场景,那么实际上性能如何,是否有优化的空间,是否可以知足咱们的即时响应的需求呢?
咱们先来看一下一个云函数启动的过程,包括哪些步骤。
函数发生调用,调度系统看函数实例是否存在,若是实例存在,那么就能够执行函数,返回结果。这个时间是很是短的,在毫秒级别。
若是不存在,那么须要建立容器,下载部署代码。这些过程耗时百毫秒到几秒不等,称为冷启动。
优化函数的性能,也就须要从函数生命周期的各个阶段去优化。
这些都是平台作的优化,那么开发者能够作什么呢?
更多能够参考个人另一篇文章《前端学serverless系列——性能调优》
1)云上调试
目前发布到云函数是要包含node_modules文件夹的,就算不须要,也要压缩,而后经过网络传输上去。若是改一行代码,就要上传一次来执行,那不是要崩溃?并且在线的IDE也是只能编辑index.js,可是代码都不是写在入口文件那的。在线IDE目前只能支持单文件入口函数的编辑,升级IDE也在规划开发中的。
2)本地调试1.0
须要提早安装tcf,docker
具体安装请参考 TCF命令行工具
本地执行命令:
tcf local invoke --template template.yaml --event event/apigateway.json
调试起来比第一种方案快了许多,虽然在公司的网络必定要开一个代理,不然会拉取不下来docker镜像。
这个运行方式的原理是,加载一个和云函数环境差很少的一个镜像,而后在docker中去执行。
然而仍是会遇到很多问题:
好比链接的数据库必定要是外网地址,由于docker的网络环境和本地并不能连通,与云上的环境也不能连通。
好比我在本地安装的npm包,也不能正常执行,由于我本地是mac系统,而镜像是linux系统。
好比云函数原本内置了一些npm包,我写了个脚本,删除了这部分npm包,在云上能够正常执行,在本地调试的时候发现又缺乏npm包,缘由是云上的环境和镜像中的环境不安全一致。不过这个问题也已经解决。
3)本地调试2.0
随着开发者的反馈,云函数的同事又推出了TCF升级版本。能够支持native调试,其实就是用本地的环境进行调试。这样至少链接数据库没有连通问题,以及调试的时候没有操做系统差别问题。那么最后一个问题只能是须要一个专门的编译机了。通常状况下,若是依赖的npm库若是不涉及到操做系统差别的话,npm包都是能够通用的。
具体用法能够查看文档: github.com/tencentyun/…
tcf native invoke --template template.yaml --event event/apigateway.json
4)node server调试:
若是你的项目是基于koa或者express之类的框架,能够直接增长一个server的入口,本地调试的时候就直接起一个server,和普通node server同样的进行调试。
可使用tcf命令进行发布,tcf命令行发布支持两种
具体能够查看文档: 如何用tcf发布部署代码
前面说到用命令行工具很方便的将代码发布到云函数平台上。
//示意代码
tcf package & tcf deloy
可是只是发布上去就能够了吗?
开发测试和线上环境如何隔离呢,如何回滚呢?
云函数自己有版本功能,云函数详情页面右上角能够发布新版本。
API网关也默认有测试、预发布、发布3个环境,能够指定云函数的版本。
那么咱们测试的时候能够指定$LATEST版本,测试经过以后能够发一个云函数的版本,而后配置API网关的预发布环境进行预发布验证,预发布验证以后,再发布到线上环境。
具体操做路径:点击API网关具体的服务进到详情页,在API管理下,针对每一个API进行编辑。
选择要对应的版本:
编辑完成以后,API须要发布到对应环境才会生效。
操做回滚也很方便,直接切换到历史到版本就能够。不过要注意的是,写好备注,不要像我同样写“test” ^_^
到这里,看起来就能够将测试和线上的环境区分开。
可是实际上,测试和线上链接的资源是不同的,好比DB,咱们一般是经过读取环境变量来判断链接什么资源,而不是经过改代码,而一个云函数只有一个配置。
那么咱们能够利用命名空间来将测试和发布环境隔离,发布能够经过函数复制来完成,可选不复制配置,配置在线上和测试环境设置不同,代码经过判断环境变量来链接线上和测试的资源。
建立命名空间:
复制函数到其余命名空间:
设置环境变量:
根据环境变量读取不一样到配置:
//根据环境变量读取不一样的配置
const devConfig = require('./config.dev');
const testConfig = require('./config.test');
const prodConfig = require('./config.prod');
const env = process.env.NODE_ENV;
console.log('process.env.NODE_ENV', process.env.NODE_ENV);
switch (env) {
case 'prod':
module.exports = prodConfig;
break;
case 'test':
module.exports = testConfig;
break;
default:
module.exports = devConfig;
}
复制代码
总结一下:
1)测试和线上放在两个不一样到命名空间,隔离测试和线上代码。
2)上线经过复制函数来完成。
3)测试和线上环境经过函数配置设置不一样的环境变量来区分。
4)回滚经过设置函数版原本完成。
API网关会有一个默认的域名,这让咱们不须要本身去申请一个域名才可使用API网关。可是,通常若是是用户在浏览器中访问的URL,确定是须要本身/简短点的域名更让人信任。
API网关-自定义域名
若是是支持https的话,须要在腾讯云上上传https证书。
另外,还能够自定义路径映射,好比将发布的路径从 http://yourdomain/release 到 http://yourdomain/ 访问更简短。也能够将/test测试路径改得更复杂一些,避免用户访问到,固然你不发布测试环境更保险。
涉及到后台服务,那么日志的打印是必不可少的,调试,查问题,甚至统计可能都须要用到日志。那么云函数的日志能够怎么来使用呢?
在云函数的界面,我看能够看到一个云函数的日志界面,能够支持实时日志显示,还有选择时间,还有只选择失败的日志。
可是咱们看到惟一的检索框,只能根据RequestID来检索,每一个请求有一个RequestID。那么requestID去哪里获取,貌似只能从这条日志中去获取,若是你传给了其余服务或者前端,其余服务追查问题的时候,能够追溯到这里。
这明显太不方便了。
日志服务在我用的时候尚未出,在我写这篇文章的时候已经上线了。
若是当前函数已经配置了日志服务,能够[前往日志服务]对日志进行更方便的检索。
在函数配置界面下方,能够配置将日志投递到日志服务。新建日志服务
建立日志集:
日志集上能够建立多个日志主题。
一个日志能够如何消费呢,能够看下下面到这个操做栏:
LogListener是用于有本身到服务器的采集方式,而云函数的采集只须要在函数配置中指定一下要投递的日志集和日志主题便可。
索引配置:能够配置分词符
投递配置:能够将日志投递到COS
实时消费:能够用Ckafka消费
检索示例:
云函数和API网关有一些自带的监控,能够知足查看需求,若是须要更详细的视图配置和告警功能的话,可使用云监控。
云函数首页总览:
云函数监控信息界面:
API网关监控:
若是须要更加丰富的统计监控告警,能够查阅云监控
其中自定义监控对后台服务来讲也是很是须要的,能够上报一些业务类型的指标或者告警。可查看文档:自定义监控
注意事项
一、项目中用到的node_modules还不能在线安装,只能从本地打包上传。
二、不少人本地的开发环境是windows或者是mac,有一些node_module依赖是和操做系统相关的,那么在本地安装的node_modules,在云函数上或镜像中并不能使用。
三、本地调试的docker环境是网络隔离的,那么若是你要链接相关的baas服务,那么你须要支持外网访问的baas服务。若是是node的话,已经能够支持tcf native 来调试,不用docker调试了。
四、服务端设置cookie目前只能设置一个。这个腾讯云也在计划修复中。
等~
最后
咱们如今使用HTTP协议的时候,须要经过API GATEWAY中转一层,能不能去掉这一层中转呢?
若是咱们的业务应用比较复杂的话,须要拆成多个云函数来承载,对于这样的现有项目能不能0改造迁移呢?
如今部署云函数的时候,须要将lib库也打包上传,咱们但愿能和代码仓库打通,在git push的时候,可以在线编译,而且自动部署。
这些问题将会在腾讯云serverless2.0中解决,即将发布,不妨期待一下。
尝试的路还在继续,欢迎有兴趣有需求的开发者一块儿讨论一块儿探索一块儿建设。