CDN基本原理剖析与代码实现测试
一、背景
内容分发网络(Content Delivery Network,缩写 CDN)是一种构建在网络之上的服务,通过在网络的边缘或核心交换区域部署内容代理服务器,利用全局负载调度机制来分发内容,从而构建了一个覆盖范围广泛的网络体系。
1996 年,MIT 提出 CDN 概念。全球第一家 CDN 网络运营商 Akamai 公司于 1999 年开始提供商业服务。2001 年,因互联网泡沫破碎,CDN 产业进入停滞期。2004 年起,随着互联网的回暖和流媒体服务的发展,CDN 又变得热门起来。云计算的兴起推动了 CDN 技术和业务进入新阶段。
通俗原理就是,本质上我们要访问服务器获取内容,普通路径都是走公网到源站点获取。例如我在海南,但是源目标服务器在北京,访问耗时例如是2000ms。但是如果相同的站点,我也在海南的三亚部署了一套, 那么耗时都降到了500ms以下。从地理距离远近我们也能知道,距离越远,延迟肯定越高,访问越慢。
CDN早期本质就是广撒网,花钱在中国各个省、市假设缓存服务器这些服务器我们称为“边缘节点”。 边缘节点,定时同步获取到源站的数据进行本地缓存,或者源站管理员主动推送最新内容到边缘节点更新数据。
用户访问经过了CDN加速后的站点之后,不再从源站例如北京获取了,而是就近访问一个边缘节点,例如三亚的节点,那么你在海南本省拿到数据的地理路径更短,耗时自然更短了。
二、核心技术
1、传统接入CDN的操作步骤
我们一般接入CDN的顺序, 各个提供商都大同小异:
1、进入CDN厂商管理后台,申请接入CDN,此时拿到一个智能DNS解析URL: static.cdn.xx.com
2、将我们的静态资源,如js、css、图片等等发布到CDN边缘节点
3、将我们的域名,例如www.mydomain.com由之前配置的A记录)直接配置源站的IP地址), 现在需要修改DNS记录类型, 改为CNAME类型,并且记录改为智能DNS地址:static.cdn.xx.com
4、最后访问测试看访问是否正常,CDN后台查看缓存命中率等
2、智能DNS调度技术
背景简介上面只是抛砖引玉,简要提了一下,"就近获取缓存内容"。 就近获取是怎么做到的? 为什么就能就近而不是跑到北京的源站获取呢?
这里智能DNS调度起到了关键性的作用。
厂商给的这个地址static.cdn.xx.com就是智能DNS地址。
我们都知道浏览器输入一个网址的时候,一般是域名例如https://www.baidu.com。 那通信过程有什么?
1、因为通信本质是通过IP地址+端口访问的,域名只是做了一个让人类更加便捷记忆的作用,域名查询之后,返回的还是我们底层真实通信需要的目标IP地址
2、HTTP端口默认不写,则是80端口
3、拿到IP和端口之后就可以进行socket连接,发送的HTTP报文,最后服务器返回HTTP响应报文。
到这里,我们发现其实可以在第一步DNS域名解析做手脚或者说留存了可以操作的空间。 因为我们源站域名CNAME指向了智能DNS地址,那么智能DNS调度就是CDN的一个核心技术。
在这里智能DNS根据各种策略、算法等等,根据你的客户端IP进行分析,例如你所处的地理位置从而拿到经纬度,根据经纬度,查找自己部署的边缘节点,哪些节点最优、距离最近等等,最以后返回边缘节点IP。
那接下来的过程和访问你的源站也没什么区别了。
3、内容分发、缓存技术、HTTP反向代理
除了DNS技术,肯定还是涉及到例如源站数据如何准确的同步到边缘节点? 必须要严格保证同步到边缘节点数据是源站最新的数据,并且完全一致。 如果不一致,那么这个加速就没太大意义了。那肯定就要涉及到如何校验数据的完整性。
缓存技术,数据拿到了以后要做缓存,如何高效缓存数据这也是要考虑的。
以及数据已经存在了怎么高效提供HTTP、HTTPS服务,让客户端能快速拿到数据?
CDN技术涉及的技术点还是蛮多的,要做大、做强,需要下很大的功夫。
三、代码实现简要版CDN理解原理
1、配置测试的DNS记录
source-web.abc.com CNAME => static.cdn.abc.com
static.cdn.abc.com NS => ns1.static.abc.com
ns1.static.abc.com A => 110.41.x.x
1、申请测试域名
我申请了测试的顶级域名,abc.com
首先源站URL: source-web.abc.com
2、 智能DNS
设置智能DNS的URL: static.cdn.abc.com
添加NS记录,让static.cdn.abc.com 指向 ns1.static.abc.com
ns1.static.abc.com添加A记录到目的智能DNS解析的主机IP: 110.41.x.x
NS记录的意思是,在DNS查询static.cdn.abc.com的时候,让客户端去询问ns1.static.abc.com权威域名解析服务器也就是对应的110.41.x.x查询结果。
3、源站设置CNAME记录
源站source-web.abc.com 设置CNAME指向static.cdn.abc.com
2、CDN加速后的访问流程图
3、智能DNS的简要实现代码
import socket
import random
from dnslib import DNSRecord, DNSHeader, RR, A, QTYPE
# 假设的 CDN 边缘节点列表,可根据实际情况扩展
cdn_edge_nodes = {
"south": ["118.193.x.x","110.41.x.x"]
}
def get_client_region(client_ip):
# 这里做策略选择,例如地域选择等等
return "south"
def handle_dns_request(data, client_ip):
d = DNSRecord.parse(data)
reply = DNSRecord(DNSHeader(id=d.header.id, qr=1, aa=1, ra=1), q=d.q)
q = d.q
if q.qtype == QTYPE.A:
region = get_client_region(client_ip)
ip = random.choice(cdn_edge_nodes[region])
reply.add_answer(RR(rname=q.qname, rtype=QTYPE.A, rclass=1, ttl=60, rdata=A(ip)))
return reply.pack()
def run_dns_server():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('0.0.0.0', 53))
print("DNS server is running on port 53...")
while True:
data, addr = server_socket.recvfrom(1024)
client_ip = addr[0]
response = handle_dns_request(data, client_ip)
server_socket.sendto(response, addr)
if __name__ == "__main__":
run_dns_server()
该代码直接运行后,在53启动监听,部署在110.41.x.x。为了验证智能DNS调度过程,我这里做了简单的策略,随机返回这2个边缘节点IP地址("118.193.x.x", "110.41.x.x")的其中1个IP,并且这2个边缘节点,内容不一样,便于测试观察。
4、两个边缘节点使用Nginx提供静态HTTP服务
A边缘节点(118.193.x.x): B边缘节点(110.41.x.x) :
5、DNS解析测试
#dig查看解析记录
#执行2次通过智能DNS返回了不同的IP地址, 类似模拟地域不同返回不同的边缘节点IP地址
dig source-web.abc.com
这里可以看到在相同的主机测试命令dig source-web.abc.com, 拿到的边缘IP地址不一样。
6、测试访问情况
同一个主机客户端,第一次访问source-web.abc.com拿到的是A边缘节点的内容, 60s后再次测试,此时返回的是B边缘节点内容。 (这里只是为了方便查看测试内容, 正式的CDN来说,缓存的结果应该都是完全一致的才行)
四、总结
CDN技术其实还是蛮具有挑战性的,因为需要的技术比较杂、也比较多。涉及数据分发、缓存、HTTP反向代理、DNS解析、高可用、高强度的数据一致性完整性保证、网络安全等等。
CDN一般做静态资源加速是常见的场景,随着CDN技术的发展,还可以做动态加速(边缘节点,接收客户端的请求后,通过线路优化、避免网络拥堵等等,再反向代理到源站,拿到动态执行结果), 也还可以做安全加速,通过边缘节点消化DDOS流量,降低源站带宽占用,保护源站。 还有边缘节点还可以反向拨测源站点,查看各个地域到源站点网络波动情况来验证源站的网络情况等等。