实时接口数据也能就近访问?细说如何用CDN提升App性能

1,258
原文链接: mp.weixin.qq.com

导读:边缘计算是在靠近物或数据源头的一侧,就近提供计算服务。其应用程序在边缘侧发起,产生更快的网络服务响应,满足行业在实时业务、应用智能、安全与隐私保护等方面的基本需求。本文作者介绍了在CDN节点上做实时数据处理的一些方式,值得架构师学习。

CDN-Content Delivery Network

我们先来定义下什么是CDN。内容分发网络(CDN)是一种由分布式服务器构成的系统,它会根据用户所处的地理位置,数据内容(通常是网页)的来源,来向用户分发网页内容。但目前这个互联网发达的时代,CDN已经不仅仅用来分发网页内容。以Cloudflare Workers【1】为例,除了利用它的网络来分发内容,你甚至还可以在它的边缘节点上部署运行你的代码。“可以部署或运行Javascript代码,这能够帮助你将代码与用户终端设备解耦合,比如支持通过编程实现路由、过滤等功能”。在当前这个爆炸式发展的互联网时代,高可扩展性是至关重要的能力。CDN和边缘计算(Edge Computing)将会进一步融合式发展。

实时数据的获取——推、拉

目前很多强调实时性的应用需要推送和拉取的数据。被动推送和主动拉取都是非常常见及简单的工程问题,比如应用初始化的过程中可以从CDN拉取历史数据,然后再由其他服务来推送更新数据。但是,我们想一想能否将这两种机制组合在一起呢?通过代理来连接Fastly和Fanout

Fastly是一个边缘计算平台(Edge Cloud Platform),它可以使应用在网络的边缘节点执行和提供服务。 本质上,它提供的是高度可扩展的“数据拉取-响应”服务,可以实时监听和响应用户的请求。 相比传统的CDN,Fastly也可以缓存静态内容,同时可以部署和运行应用逻辑。另一方面,Fanout则是具备高度可扩展性的数据推送服务,比如用作高性能的反向代理服务,通过长链接为客户端实时推送数据。Fastly和Fanout可以组合使用。它们作为一个整体可以当作源服务器的反向代理,通过Fastly来代理到Fanout的流量,这样客户端就不用直接请求你的源服务器。这会带来一些好处:

  • 高可用和高可扩展性,这点毋庸置疑

  • 缓存初始数据

  • 缓存Fanout的指令,这点需要特别说明:Fanout的一些行为是通过指令来配置的。比如传输模式,订阅的channel等等。通常,这些指令是通过源服务器的response来获取(一类特殊的header,被称为Grip)。Fastly可以在获取一次response后缓存这些指令。

映射网络流

通过组合使用Fanout和Fastly,我们就可以重构这个“推-拉”模型中的网络数据流,下面我们来仔细看看它们是如何工作的:假设我们有一个HTTP Endpoint是 /stream,它会返回一些初始数据,并且在有新数据产生后推送给连接的客户端。配合Fanout,我们可以让这个Endpoint返回带有instruction的response:(以response header为例)

HTTP/1.1 200 OKContent-Type: text/plainContent-Length: 29Grip-Hold: streamGrip-Channel: updates{"data": "current value"}

当Fanout从源服务器收到这样的response,会将它转换成HTTP streaming的response:

HTTP/1.1 200 OKContent-Type: text/plainTransfer-Encoding: chunkedConnection: Transfer-Encoding{"data": "current value"}

这样,Fanout到源服务器的请求就完成了,但是客户端到Fanout的请求(连接)仍然是open的状态,用这样的时序图来表示:

因为Fanout到源服务器是短链接的请求/响应模式,可以通过Fastly来转换成长连接:

这样当再有客户端请求/stream这个endpoint时,源服务器就完全不会参与进来:

换句话说,Fastly会给Fanout返回相同的response,带着特殊的headers已经那些初始数据,Fanout到客户端则维护streaming连接。上述过程,我们只解决了“拉”的过程,还需要实现新数据被实时“推送”给Fanout(客户端)。清除fastly的缓存

当源服务器的数据改变时我们需要清除掉fastly上的缓存来更新它。还是上文的例子,假如/stream endpoint的数据产生变化,我们就需要清除fastly的缓存并同时将新数据广播给fanout。下面这个时序图描述了一个更复杂的场景,已有的客户端将被推送新的数据,之后再来一个新客户端连接:

高效的实现流控

在这种混合架构下,为了提高效率,理想的数据读写模型是:

  • 数据访问:每秒若干新的读

  • 数据更新:每分钟若干写

  • 数据分发:毫秒级投递

如果你的数据每秒都会产生变化,那最好是不要每次数据变更都清除缓存。(容忍一定程度的数据不一致性)例如在高峰时期,我们可以限制清除的频率,大部分读请求还是由缓存数据来响应,稍候再更新数据。Demo

这里提供了托管在GitHub上的demo应用源代码,它利用fastly和fanout提供一个live 

counter服务。请求会先到fanout,然后到fastly,最终传递到一个由Django实现的backend server。这个服务实现了简单的计数器逻辑,当计数器的值更新了,fastly的缓存会被清除掉,同时再通过fanout发送出去。清除和更新的过程都由流控来限制,以尽可能提高缓存的效率。脑洞一下

我们可以设计一个消息内容分发网络,它由完全是地理位置分布的若干组server构成,可以提供近实时的动态内容和静态内容分发。这种新类型的CDN网络可以使得数据处理延伸到网络边缘,不用管应用本身的源服务位于哪里。这将为移动应用和IoT应用形态带来巨大的想象空间。

英文原文:

https://hackernoon.com/powering-your-app-with-a-realtime-messaging-cdn-13d92a6df5f3