微信号:ArchNotes

介绍:高可用架构公众号.

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

2018-09-21 08:00 Justin Baker

导读:边缘计算是在靠近物或数据源头的一侧,就近提供计算服务。其应用程序在边缘侧发起,产生更快的网络服务响应,满足行业在实时业务、应用智能、安全与隐私保护等方面的基本需求。本文作者介绍了在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 OK
Content-Type: text/plain
Content-Length: 29
Grip-Hold: stream
Grip-Channel: updates

{"data": "current value"}

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

HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: 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


相关阅读:

本文作者Justin Baker,由魏佳翻译,转载本文请注明出处,技术原创及架构实践文章,欢迎通过公众号菜单「联系我们」进行投稿。


高可用架构

改变互联网的构建方式

长按二维码 关注「高可用架构」公众号



 
高可用架构 更多文章 从单机到2000万QPS: 知乎Redis平台发展与演进之路 一文读懂熔断器和重试机制 NoSQL还是SQL?这一篇讲清楚 一文读懂Java 11的ZGC为何如此高效 周末推荐:八个优质技术公众号
猜您喜欢 跟着Jason学UML(一) 类图 菊花绽放:微信是如何识别小程序码的? 使用DiffUtil高效更新RecyclerView 工程师 oncall 那点事 为什么Kafka那么快