低成本打造一个带宽无限的网站(四)

简介: No.4

分块处理

上一篇曾提到,我们可对资源加密存储,然后在 SW 中进行解密。

理论上这当然可行,但事实上会出现一些问题:我们必须等整个资源下载完成后,才能开始解密操作。这对于用户体验,会产生很大的影响。

假如有个 1MB 的图片,通过 100 KB/s 的速度加载,那么要 10 秒后才能解密再展示;然而正常情况下,图片是边加载边显示的,并不会让用户等很久,然后一次性展示所有的。

为了解决这个问题,一个期待已久的新标准终于到来,那就是 Stream API。

有了流的支持,数据就可以渐进处理,而不必等待完整的。例如,我们使用 fetch 分块读取内容:

// fetch 分块读取演示
async function load(url) {
    let res = await fetch(url);
    console.log('response:', res);

    let reader = res.body.getReader();
    for (;;) {
        let r = await reader.read();
        if (r.done) {
            break;
        }
        console.log('chunk:', r.value);
    }
    console.log('end');
}

load('https://raw.githubusercontent.com/EtherDream/_/master/pic.jpg');

演示:codepen.io/anon/pen/zPKrGX

同时,SW 也支持数据分块输出给下游:

// SW 分块输出
let stream = new ReadableStream({
    async pull(controller) {
      let chunk = read_from_upstream()
      controller.enqueue(chunk)

      if (is_done) {
        controller.close()
      }
    },
});

let res = new Response(stream, ...);
...

两者结合,我们就可以实现边下载、边解密、边输出的效果。于是对于加密的图片、视频等资源,也能循序渐进地展示了!

下载加速

除了解密、解压缩等场合,数据流还可用于传输优化。例如,用户下载大文件的场合。

由于免费空间单个节点的带宽是有限的,因此下载速度不会太快。这时就可以通过 SW 做加速了 —— 我们同时从多个节点获取相应的文件片段,然后依次输出到响应流里:

boost.svg

在用户看来,这只是浏览器默认的单线程下载,但事实上内部已通过 SW 加速,和传统的多线程下载软件并无本质区别!

当然,就算免费空间不支持 Range 请求也没关系,我们可事先把大文件分成多个小文件上传,然后分别加载即可。

动态加速

上一篇提到,通过 SW 可对故障节点「实时无缝」的切换。现在有了数据流,我们可将其发挥到极致,甚至能在传输的过程中进行调整。

例如,SW 默认选择 节点 1 加载资源,但发现速度没有预期的那么快,于是可增加 节点 2 参与加速:

proxy.svg

这样,我们就能根据用户的实际网络情况,在端上动态调整,从而实现更智能的负载均衡!

插入脚本

有时候,我们希望给站点下所有页面的头部插入一个 JS 脚本。

这个功能,如果没有数据流支持的话,那么 SW 必须得下载整个 HTML 才能修改;而现在,我们只需改造最先返回的几个 chunk 即可!

inject.svg)

不过需要注意的是,chunk 是二进制层面截断的,因此可能会把多字节字符截成两半,导致出现乱码。

为此,我们需要用「流模式」解码字符串。例如:

// stream decode example
// 你: 228, 189, 160
// 好: 229, 165, 189
let dec = new TextDecoder();
let chunk1 = new Uint8Array([228, 189, 160, 229, 165]);
let chunk2 = new Uint8Array([189]);

dec.decode(chunk1, {stream: true});     // "你"
dec.decode(chunk2, {stream: true});     // "好"

如果 chunk 末尾的字符不完整,那么不足的部分则被暂存在内部,下次解码时会自动加在开头。

这样,我们就能用字符串方法,方便地操作二进制数据了:

let dec = new TextDecoder();
let enc = new TextEncoder();

input.ondata = function(chunk) {
    // 二进制 -> 字符串
    let str = dec.decode(chunk, {stream: true});

    // 插入脚本元素
    str = str.replace(/<head/i, '<script ...><head');

    // 字符串 -> 二进制
    chunk = enc.encode(str);
    ...
};

当然,这里的逻辑还有点瑕疵 —— 假如 <head 这个字符串正好跨越两个 chunk,那就无法匹配到了。

由于 JS 不支持流模式的正则匹配,因此这里可用个土办法:如果 str 匹配不到,则截掉末尾 5 个字符(即 <head 的长度),然后将截出来的尾巴暂存起来,留到下一次,拼到头部。。。

这样,虽然不怎么严格,但实现简单,并且也很高效!

此外,由于我们只需注入一次脚本,因此替换后即可跳过解码、匹配、编码这些步骤了。

小结

在数据流的配合下,SW 可实现非常丰富的玩法。不过目前只有 Chrome 浏览器支持 Stream API,因此兼容性也是个较大的问题。相信随着新标准的普及,今后使用前端加速的网站,一定会越来越多。

然而对于我们的「免费空间」来说,除了兼容性问题之外,还有 SW 的各种使用限制也是一个挑战。因此如何绕过 SW 的使用限制,也是需要我们思考的。

下一篇

目录
相关文章
|
4月前
|
安全 定位技术 数据中心
什么是海外服务器,优势有哪些,延迟大概在多少
至于延迟,这主要取决于用户的地理位置和服务器的地理位置。一般来说,用户和服务器之间的距离越远,网络延迟就越大。对于跨洲访问,延迟可能会在几十到几百毫秒之间。但这也受到许多因素的影响,如网络路由、带宽等。
67 0
|
5月前
|
存储 Python
理解云存储的成本结构与计费模式
【6月更文挑战第1天】云存储成本结构复杂,包括存储容量、数据传输和请求次数的费用。计费模式多样,如按用量、订阅或峰值计费。通过Python示例展示了上传下载文件操作。理解并合理选择云存储方案,避免不必要的费用,成为云存储的明智使用者。一起来探索这个“魔法盒子”吧!
80 1
|
6月前
|
安全 Serverless API
Serverless架构在图像处理中展现出高成本效益,按需付费降低费用,动态调整资源避免浪费
【5月更文挑战第16天】Serverless架构在图像处理中展现出高成本效益,按需付费降低费用,动态调整资源避免浪费。其出色的并发处理能力和自动扩展确保高并发场景的顺利执行。简化开发流程,让开发者专注业务逻辑,同时提供丰富API和集成服务。安全方面,Serverless通过云服务商管理基础架构和多种安全机制保障任务安全。因此,Serverless是处理高并发、动态需求的理想选择,尤其适合图像处理领域。随着技术发展,其应用前景广阔。
69 4
|
弹性计算 运维 监控
阿里云万郁香:多样付费选择构筑成本最优的弹性体验
云上成本优化三部曲:云上资源归属拆解、确定资源需求及购买优先级、选择最佳的付费方式。
阿里云万郁香:多样付费选择构筑成本最优的弹性体验
|
存储 开发者
UPYUN 又拍云进行大幅度降价:数据量持续高速增长致成本降低
今天我们刚刚得到了SegmentFault 与开发者的好伙伴又拍云的官方消息,UPYUN(又拍云)进行了大幅度的价格调整。本次价格调整主要表现在存储空间和流量价格的全面下调,存储空间最高降价67%,流量最高降价40%。据了解,UPYUN本次进行价格调整的根本原因是过去一年UPYUN平台数据量持续高速增长令整体成本降低所致。
172 0
|
存储 边缘计算 缓存
如何降低 PB 级带宽成本?揭秘优酷“云边端”分发网络
2019 年,整个互联网的绝大部分流量来自于视频服务,优酷,每日承载了上亿用户的几十 亿的视频观看,每日消耗的互联网流量高达 Pb 级别。在如此高并发高流量的项目中,如何在保 障用户体验的前提条件下,有效的提升服务器以及带宽的利用效率,实现消峰填谷,降低服务 器和带宽成本,成为我们技术人的工作重心。
如何降低 PB 级带宽成本?揭秘优酷“云边端”分发网络
|
物联网
挑战设备接入量,节省最高92%资费
2020年3月31日前,设备接入达到指定量级,即可获得1.5-0.8折折扣,物联网卡和物联网平台设备接入服务劲省92%资费。
26722 0
挑战设备接入量,节省最高92%资费
|
弹性计算 负载均衡 固态存储
业务系统的带宽能力
业务系统的整体带宽能力,取决于公网带宽、网卡速率以及磁盘吞吐量,本文量化分析阿里云上部署,可能存在的瓶颈,以及提供参考建议
1171 0
业务系统的带宽能力