javascript
cdn边缘javascript敏捷交付实践 -凯发ag旗舰厅登录网址下载
本文由百度智能云-视频云-内容分发加速技术架构师——高岩 在百度开发者沙龙线上分享的演讲内容整理而成。内容从cdn应用serverless的意义出发,详细介绍edgejs serverless服务。
文/ 高岩
整理/ 百度开发者中心
视频回放:https://developer.baidu.com/live.html?id=11
本次分享的主题是:cdn边缘javascript敏捷交付实践,内容主要分为以下三个方面:
- cdn应用serverless的意义
- edgejs severless服务
- 沉浸式cdn编程体验
01 cdn应用serverless的意义
cdn基本介绍
cdn含义:
是指一组分布在不同地理位置的服务器,协同工作以提供互联网内容的快速交付。
cdn服务已得到不断普及。如今,大多数web流量都通过cdn提供服务,几乎所有的门户网站、常用的视频 app(例如,爱奇艺、抖音)都会用 cdn 架构实现更加快速的内容分发,让用户更快地看到视频内容,带来更好的用户体验。
这是因为 cdn 允许快速传输、加载互联网内容所需要的资源。以门户网站为例,我们需要加载 html 页面、javascript、文件 css 等资源;而视频网站则需要加载缩略图、视频文件。
cdn 还可帮助保护网站免受某些常见的恶意攻击,例如分布式拒绝服务(ddos)攻击。
使用cdn优势:
缩短网站加载时间
通过将内容分发到访问者附近的cdn服务器(以及其他优化措施),访问者体验到更快的页面加载时间。由于访问者更倾向于离开加载缓慢的网站,cdn 可以降低跳出率并增加人们在该网站上停留的时间。换句话说,网站速度越快,用户停留的时间越长。
减少带宽成本
网站托管的带宽消耗成本是网站的主要费用。通过缓存和其他优化,cdn 能够减少源服务器必须提供的数据量,从而降低网站所有者的托管成本。
增加内容可用性和冗余
大流量或硬件故障可能会扰乱正常的网站功能。由于cdn具有分布式特性,因此与许多源服务器相比,cdn 可以处理更多流量并更好地承受硬件故障。
改善网站安全性
cdn 可以通过提供鉴权、安全证书的改进以及其他优化措施来提高安全性。
vcdn的发展
早在2009年,伯克利曾针对当时兴起的云计算做过评论,并提出了以下6个潜在的优点:
基于云计算的理念,可以实现一个虚拟化cdn(vcdn), 即可在专有、裸金属、虚拟化或基于容器的基础设施上运行cdn。vcdn作为云上的一个应用,是cdn和云紧密结合的产品。其主要功能特性包括:
硬件虚拟化:虚拟化基础架构使软件和硬件功能得以分解,服务器运维大大简化。
低延迟:在共享基础设施上运行cdn功能,可以更快的调起其他应用,比如可以实时进行图片处理。
弹性伸缩:可以按需使用cdn,在流量高峰和低峰,进行自动的弹性扩容和缩容。
但是云计算技术发展到今天,虚拟化并不能解决所有的问题,
在对性能有特别高要求的场景下,面临的主要难点如下:
- 虚拟机/容器,构建业务应用运维成本较高。
- 不能做到按需付费,仍然需要独占虚拟机。
- 开发复杂,需要很多其它的依赖,在开发业务的过程中,需要数据库、对象存储等框架。需要自己掌控运维和使用情况,开发难度较高。
serverless介绍与特点
为了解决上述问题,亚马逊的 aws 在 2015 年推出了 lambda 服务,提出了cloud function的概念,引起了业界对于 serverless 的关注广泛。
serverless 主要包含 faas、baas 两种形态。其中,faas 将 function 作为服务,baas 将后端服务作为服务。
在应用了 vcdn 后,也可以用 baas 的方式运行服务。serverless 旨在让开发人员不需要再关注服务器,云会帮自动实现服务器的运维和伸缩。
具体而言,serverless 具有以下特点:
cdn应用serverless的意义
早在 2018年,云管理公司 rightscale 开展的一项调查显示,serverless 是增长最快的公共云服务。
据统计,aws 上超过一半的用户已经在使用 serverless 服务。serverless 一直在高速发展,呈现出越来越大的影响力。
serverless 将无处不在,cdn也必须拥抱serverless理念,提供边缘可编程能力,使用户可以在控制台上通过 api 设置代码,形成编程能力,更有效地控制 cdn。
在 cdn 业务中实践 serverless 理念可以提供敏捷交付的能力,具有以下优势:
- 编程能力 对于刚接触cdn的客户来说,可编程能力,即便不理解cdn的具体运作流程,也能快速编写出可用的代码。
- 敏捷交付 对于cdn研发人员,serverless节省了他们部署和运维的时间,让他们能够更加专注于解决和优化应用本身的问题。
- 场景下沉结合编程能力,可以和其他场景更方便的结合在一起。
- 边缘计算在cdn的边缘,可以进行更加自由的计算,节省端上处理的时间和延迟。
02 edgejs serverless服务
edgejs serverless服务目标
serverless 的目标是使用户可以更容易地编写和部署代码,而无需关注底层结构。尽管目前的 cdn 业务可以实现按需付费,但是仍然不够灵活。
为此,我们推出了 edgejs serverless 服务。该服务在百度智能云 cdn 上使用javascript 语言去提供的一种可编程的配置能力,实现高并发、低成本的敏捷交付,使 cdn 能够体现出 serverless 的思想,进行靠拢或者是计划。
该服务具有以下特点:
- 嵌入式 javascript runtime,而非独立的 runtime。出于对性能的考虑,在支持 js 标准库的同事,避免了独立runtime 带来的冷启动时间。
- 提供请求对象 request,可以在代码中进行随意更改。
- 提供对外访问能力。
作为一种 serverless 服务,edgejs 需要实现用户隔离、具备较高的性能,能够动态编码。具体而言,edgejs 具有以下特性:
edgejs serverless服务的特性
edgejs致力于让cdn更易用,向serverless服务能力迈进。所以edgejs的定位一开始就是完全免费,在cdn按需使用的带宽费用之外,不会产生额外的费用。
在降低cdn使用门槛的初衷下,必须还得保持cdn的高可用、低延迟、就近服务的能力。
edgejs的设计,是完全嵌入到cdn接入层的javascriptruntime,无需冷启动时间,没有性能损失,并支持标准es6语法的javascriptapi,各种特性陆续补齐中。
而且相比传统交付,开发上线至少周级别的交付周期,edgejs真正能做到秒级交付,用户在控制台配置上代码,就可以秒级生效。当然建议在正式发布前,先使用预发布功能来灰度验证。edgejs,可以根据请求进行各种特征处理,这极大丰富了cdn接入的场景。
为了更好地配合 cdn 业务,edgejs 具有以下特性:
- 使用 edgejs 在边缘进行计算(如一些特殊的鉴权等不能缓存的动态需求),将预计算任务部署在边缘设备上,大大减轻源站的压力
- 做到秒级交付,使用户在控制台上配置代码,秒级生效。
- 根据请求进行各种特征处理,极大丰富 cdn接入场景(包括不限于跨域访问、重定向、访问控制、单请求限速、自定义鉴权、m3u8改写、请求改写、a/btest自定义错误页面等。
除此之外,edgejs还可以利用fetch等能力,和远端进行协同,包括不限于远程鉴权、云服务协同和请求画像打点上传。这些能力已经远超cdn的传统场景,向serverless服务能力靠拢。
在cdn庞大的算力加持下,可以减轻源站的性能压力和支出。而且,当增加了新的特征或者增加了新的计算方法,可以随时修改javascript代码,进行实时控制。
03 沉浸式cdn编程
url改写与复杂文件名改写
cdn 控制台本身支持一些 url 改写的基本功能,但这些预定义的功能灵活性较低。我们可以通过 edgejs 根据用户的要求确定配置。edgejs 使用标准的 js 语法,需要用户建立一个请求对象 request。
如上图所示,我们首先将 url 中的大写字母转成小写,接着我们将请求的 variables 参数改成小写。variable 映射的是 unix 的变量,而这的规则完全一致的。
edgejs 支持复杂的文件名改写,这里涉及到三种情况:
(1)参数 attname 存在且不为空字符串
(2)参数 attname 存在且为空字符串
(3)参数 attname 不存在。
回源鉴权头
在一些对象存储场景下,我们可以通过 edgejs 构建回源鉴权头 authorization。首先生成一个随机数,获取当前时间,并生成请求 url。接着,我们利用以上三者根据 crypto 算法生成鉴权头。
我们可以通过请求的 headersin 特性获取请求头。有些特殊的请求头只能存在一份,如果重复则会被忽略(例如,host、connection,详见凯发ag旗舰厅登录网址下载官网)。此外,重复的 cookie 的请求头会返回所有的重复部分,并以分号分隔开来。如果我们想要获取所有的请求头,我们需要使用 rawheadersin 特性,如果请求头有多个,则会输出数组。
r.headersin{}
请求头对象,可写foo请求头可以使用r.headersin.foo或者r.headersin[‘foo’]来访问
“host”, “connection”, “if-modified-since”, “if-unmodified-since”, “if-match”, “if-none-match”, “user-agent”, “referer”,
“content-length”, “content-range”, “content-type”, “range”, “if-range”, “transfer-encoding”, “te”, “expect”,
“upgrade”, “accept-encoding”, “via”, “authorization”, “keep-alive”, “x-real-ip”, “accept”, “accept-language”, “depth”,
“destination”, “overwrite”, "date"这些请求头只能有一个,重复的会被忽略
重复的“cookie”请求头,会返回所有的重复部分,并以分号(;)分隔,
重复的其他请求头,会返回所有的重复部分,并以逗号(,)分隔,
r.headersin.foo =‘foo’,赋值会覆盖所有的重复部分。
r.headersin [‘foo’]= [‘a’, ‘b’],赋值数组,会产生两个重复的请求头:
foo:a和foo:b
r.rawheadersin{}
请求头kv array,只读。
比如请求头host:localhost;foo: bar ;foo: bar2
r.rawheadersin输出类似于[‘host’, ‘localhost’], [‘foo’, ‘bar’], [‘foo’, ‘bar2’]
获取所有的请求头foor.rawheadersin.filter(v=>v[0].tolowercase()
== ‘foo’).map(v=>v[1])
输出[‘bar’, ‘bar2’]
文件名改写
edgejs serverless 服务通过请求的 headersout 特性可以实现文件名改写、跨域访问、设置相同的响应头等功能。
如上图所示,我们可以使用请求参数 filename 命名下载文件,使用请求头 origin 赋值给跨域响应头 access-control-a。在设置相同的响应头时,我们可以通过赋值数组,产生重复的响应头。
r.headersout{}响应头对象,可写foo响应头可以使用r.headersout.foo或者r.headersout[‘foo’]来访问。
“server”, “date”, “content-length”, “content-encoding”,
“location”, “refresh”, “last-modified”,
“content-range”, “accept-ranges”,
“www-authenticate”, “expires”, “e-tag”, “etag”, “content-type”, “x-override-charset”,
“cache-control”, “link”, “age”,
“retry-after”,这些响应头只能有一个,重复的会被忽略
重复的"set-cookie"响应头,会返回一个数组,例如,r.headersout[‘set-cookie’].foreach
(element=> console.log(element));
重复的其他响应头,会返回所有的重复部分,并以逗号(,)分隔
r.headersout.foo =‘foo’,赋值会覆盖所有的重复部分。
r.headersout [‘foo’]= [‘a’, ‘b’],赋值数组,会产生两个重复的响应头:
foo:a和foo:b
r.rawheadersout{}
响应头kv array,只读
用法类似于r.rawheadersin{}
自定义错误页面
我们可以使用 edgejs 实现自定义的错误页面,当源站返回 404 时,可以重定向到一个对用户友好的页面。
如上图所示,我们通过 respheader 回调实现上述功能。类似地,我们可以通过 respheader 实现 a/b 测试,
如果源站返回了特殊头 a,可以命中一个升级的逻辑,重定向到一个应用升级的页面。
ip黑名单
edgejs 支持通过百度自有的库提供一些常用的访问控制功能:
(1)ip 黑名单,如果客户端地址在 192.168.1.1/32 或 192.168.2.1/24 等ip段内,则返回 403。
(2)referer 白名单,如果 referer 不匹配某些通配符的形式,则返回 403。
(3)ua 黑名单,如果 ua 包含 curl 或 applewebkit,则返回 403。
代码示例:
r.remoteaddress
客户端地址,只读
baidu_utils库
function ipincidr(ipv4,cidrs)
参数:
ipv4为点分十进制的ipv4地址,比如’192.168.2.100’
cidrs为cidr地址列表,比如[‘192.168.1.1/32’,‘192.168.2.1/24’]
使用示例:
if (baidu_utils.ipincidr (‘192.168.2.100’,[‘192.168.1.1/32’,‘192.168.2.1/24’])) {
r.return(403);
}
function matchwildcard(str,rule)
参数:
str为待匹配的字符串,比如’http://www.baidu.com/’
rule为有通配符的字符串,比如’http://.baidu.com/’
使用示例:
if (baidu_utils.matchwildcard(‘http://www.baidu.com/’, ‘http://.baidu.com/’)
{
r.return(403);
}
鉴权
百度云基于 edgejs 提供了 b 类防盗链等鉴权功能。原始的 url 包含协议头 http、域名、文件名。在加密之后,url 变成了协议头、域名、时间戳、md5 编码,文件名。
在上图的第一段代码中,cdn 服务器收到请求之后,首先拆分 url,得到时间戳、md5 、文件名。
在第二段代码中,时间戳的格式并非 unicode,而是可读的格式,我们需要进行时间戳格式的转换,将秘钥与时间戳、文件名拼接,并进行 md5 加密编码的比对。
子请求
cdn本身是一个缓存体系,对于hls或者dash来说,其索引文件中包含的防盗链信息,在用户请求的时候很可能过期了,所以在用户请求的m3u8或者mpd的防盗链验证通过之后,需要将这个请求中的防盗链信息改写到索引文件内容中。
fetch
fetch
ngx.fetch(url, [options])
类似于javascript原生的fetch,请求url,并返回解析response对象的promise。参考using_fetch
目前仅支持http协议,重定向需要调用者处理
类似于js fetch,options支持body/ headers / method。
ssl选项如下:
ssl_name 指定sni,默认为url中的域名
ssl_verify是否开启证书校验,默认开启
response
标准的javascript内置对象
我们可以通过 edgejs serverless 服务实现 fetch 功能,请求远程鉴权服务器,根据远程服务器的响应进行处理,如果得到非 2xx 状态码,则返回 403 禁止访问。fetch 返回的是一个 promise 对象,包含类方法,可以将异步的操作变为序列化的操作,只要需要关心业务逻辑。与 fetch 一同上线的还有 await、subtlecrypto 等功能。
以上是老师的全部分享内容,有任何问题可以在讨论区提出。
点击进入获得更多技术信息~~
扫描二维码,备注:音视频开发,立即加入音视频开发技术交流群。
总结
以上是凯发ag旗舰厅登录网址下载为你收集整理的cdn边缘javascript敏捷交付实践的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得凯发ag旗舰厅登录网址下载网站内容还不错,欢迎将凯发ag旗舰厅登录网址下载推荐给好友。
- 上一篇:
- 下一篇: