企业运维之 CDN 内容分发网络

Posted 123坤

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了企业运维之 CDN 内容分发网络相关的知识,希望对你有一定的参考价值。

1. CDN 是什么?

CDN 是 Content Delivery Network 的简称,即 "内容分发网络” 的意思。一般我们所说的 CDN 加速,一般是指网站加速或者用户下载资源加速。
CDN 基本思路就是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,CDN系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。

CDN加速有什么用?

——对访客用户的好处

对于用户来说,如果一个网站开启了CDN,用户访问速度或者下载速度会比没有开启时更快。一般目前只要好一些的网站,都会开启CDN功能,主要在于提升用户体验。

——对网站的好处

对于网站或者站长来自,开启了CDN不仅可以提升网站打开速度,提升用户体验。更重要的是开启CDN可以减少黑客工具和服务器宽带压力。

开启CDN后的网站,不同地区用户访问会是不同的服务器,而网站的真实服务器(源服务器)一般只有CDN节点回去访问获取,全国各地的用户访问的CDN节点服务器,并不直接访问源服务器,这样就可以介绍网站服务器宽带资源,降低服务器压力。

由于有CDN节点中间阻挡防护,可以更好的保护原服务器的安全。也就是说CDN为用户源站服务器在安全云中提供了一个替身,无论是渗透还是DDoS攻击,攻击的目标都将是CDN节点替身,进而保护了网站源站。

2. CDN 的工作原理

首先CDN是为了改善互联网的服务质量的。

假设百度网站只有一台服务器,如果该服务器也在北京,那么通常来说访问比较快,在北京的用户访问起来比在拉萨的用户访问起来要快。那么这个问题的根本原因是网络传输是依赖于网线的,网线越长,传输时间肯定就越久。

对于这个问题的解决,其实思路很简单,就是百度在全国各地都部署一模一样的服务器就行了,专业一点叫冗余。

虽然听起来很简单,但是实施起来还是比较麻烦的,服务器上的资源分为两种:静态资源与动态资源。

静态资源:这种资源通常是很少变动的,比如图片,视频,css,javascript等等

动态资源:这种资源不同用户不同时刻访问通常是不一样的,比如ftl,jsp等等。

如果要在全国各地都部署服务器,每个服务器上都有相同的动态资源,那么就需要配置相应的数据库,因为动态资源所记录的信息通常会存储在数据库中,那么这就涉及到了数据同步等等问题。这会导致成本很高,这种做法专业一点其实就是集群,而目前来说集群架构最多是三地五中心,不是说全国多地集群不可能,主要是成本太高。

成本比较低的方式就是在每个服务器上只部署静态资源,静态资源通常不涉及到数据库,所以成本也比较低,而且也能提高用户的访问速度。

现在如果要比较CDN系统,我们可以考虑两点:

CDN系统中存储静态资源服务器的性能以及网速怎么样。
CDN系统中全国甚至全球范围内服务器节点的数量以及部署情况。

如果静态资源的服务器节点很多,能够让每个用户在访问这些静态资源时都不用“跑很远的路程”才能获取到,那么自然这是CDN系统的优点。

有需求就有提供服务的人,所以有很多CDN供应商,比如阿里,腾讯等等都有自己的CDN服务。只要你自己的系统接入了这些CDN供应商提供的CDN服务,把自己的静态资源传给CDN服务,那么这些静态资源将自动的分布到全世界各地去。

用户在访问静态资源时通常是通过域名来访问的,域名会被解析成某一个IP地址,DNS系统怎么在做域名解析时,怎么解析出来一个离用户最近的一个IP地址。

普通的DNS系统是做不到的,需要一个特殊的DNS服务器,这个特殊DNS需要知道:

用户当前所在位置;还需要知道用户现在访问的这个域名对应哪些IP地址,以及这个IP地址分别在哪。

对于第一个问题好解决,直接从用户请求里提取出用户的ip地址,比如这个ip地址被解析为北京电信、上海移动等等。

第二个问题由谁来解决,考虑CDN,CDN提供商知道公司在哪些地方部署了机器以及它们的IP地址,所以CDN提供商会提供这个特殊的DNS服务器,我们叫做 CDN专用DNS服务器。

这样的话,只要用户在使用某个域名访问静态资源时,如果用户直接配置自己电脑的DNS地址为CDN专用DNS服务器。那么自然解决了问题,但是我们不能要求世界上所有的用户都去修改自己电脑的DNS 地址。所以这个时候就要利用DNS中的CNAME了。

当我们使用域名访问某一个网站时,实际上就是将请求包(以Http请求为例)通过网络传输给某台服务器,比如访问“www.baidu.com”时:

首先解析出该域名所对应的IP地址(DNS域名解析)
然后将Http请求包通过网络路由到IP地址所对应的服务器
我们通常说“服务器的IP地址”,这其实不太准确,IP地址是和网卡绑定的,一个服务器可以有多个网卡,也就是可能有多个IP地址。
  1. 域名解析
    解析域名分为两种:

    将一个域名解析为一个IP地址
    将一个域名解析为另外一个域名
    

在域名服务商购买了一个域名之后,需要去映射一个IP地址,可以用Map来表示这个关系:{域名:IP}。
同时也可以给某个域名取一个别名,比如“www.baidu.com”取一个别名“test.baidu.com”,这种关系也可以用Map来表示:{域名:别名}。这里的别名专业一点叫做CNAME。
而域名解析,实际上就是解析出指定域名所对应的IP地址,或者该域名的一个CNAME。

而域名解析是由DNS系统来负责的,DNS服务接受外部请求,从请求里提取域名,

如果这个域名对应的是IP地址,则返回这个IP地址,
如果这个域名对应的是CNAME,则继续查找CNAME域名的IP地址,然后将该地址返回给请求发送者。

请求发送者拿到IP地址之后,完成真正的请求调用。
没有CNAME的情况:

我们知道,当我们使用域名访问某一个网站时,实际上就是将请求包(以Http请求为例)通过网络传输给某台服务器,比如访问“www.baidu.com”时:

首先解析出该域名所对应的IP地址(DNS域名解析)

然后将Http请求包通过网络路由到IP地址所对应的服务器

我们通常说“服务器的IP地址”,这其实不太准确,IP地址是和网卡绑定的,一个服务器可以有多个网卡,也就是可能有多个IP地址。

我们先来看第一步:域名解析
域名解析

解析域名分为两种:

将一个域名解析为一个IP地址

将一个域名解析为另外一个域名

其实解析思路不难,我们在域名服务商购买了一个域名之后,需要去映射一个IP地址,可以用Map来表示这个关系:{域名:IP}。

同时我们也可以给某个域名取一个别名,比如“www.baidu.com”取一个别名“test.baidu.com”,这种关系也可以用Map来表示:{域名:别名}。这里的别名专业一点叫做CNAME,相信大家对这个词有点眼熟,它就是这个意思。

而域名解析,实际上就是解析出指定域名所对应的IP地址,或者该域名的一个CNAME。

而域名解析是由DNS系统来负责的,DNS服务接受外部请求,从请求里提取域名,

如果这个域名对应的是IP地址,则返回这个IP地址,

如果这个域名对应的是CNAME,则继续查找CNAME域名的IP地址,然后将该地址返回给请求发送者。

请求发送者拿到IP地址之后,完成真正的请求调用。

实际上DNS系统是非常庞大的,这里不去多将,大家把它当作一个黑盒子,这个盒子的作用就是上文所描述的,这里用一个简单的图来表示一下。

没有CNAME的情况:

在这里插入图片描述
有CNAME的情况:

在这里插入图片描述
注: 在有CNAME的情况下,CNAME实际上在域名解析的过程中承担了中间人(或者说代理)的角色,这是CDN实现的关键。

用户使用某个域名来访问静态资源时(这个域名在阿里CDN服务中叫做“加速域名”),比如这个域名为“image.baidu.com”,它对应一个CNAME,叫做“cdn.ali.com”,那么普通 DNS服务器(区别CDN专用DNS服务器)在解析“image.baidu.com”时,会先解析成“cdn.ali.com”,普通DNS服务器发现该域名对应的也是一个DNS服务器,那么会将域名解析工作转交给该DNS服务器,该DNS服务器就是CDN专用DNS服务器。CDN专用DNS服务器对“cdn.ali.com”进行解析,然后依据服务器上记录的所有CDN服务器地址信息,选出一个离用户最近的一个CDN服务器地址,并返回给用户,用户即可访问离自己最近的一台CDN服务器了。

在这里插入图片描述

3. CDN 的组成

每个CDN节点由两部分组成:负载均衡设备和高速缓存服务器。

负载均衡设备负责每个节点中各个Cache的负载均衡,保证节点的工作效率;同时,负载均衡设备还负责收集节点与周围环境的信息,保持与全局负载DNS的通信,实现整个系统的负载均衡。CDN的管理系统是整个系统能够正常运转的保证。它不仅能对系统中的各个子系统和设备进行实时监控,对各种故障产生相应的告警,还可以实时监测到系统中 总的流量和各节点的流量,并保存在系统的数据库中,使网管人员能够方便地进行进一步分析。通过完善的网管系统,用户可以对系统配置进行修改。

理论上,最简单的CDN网络有一个负责全局负载均衡的DNS和各节点一台Cache,即可运行。DNS支持根据用户源IP地址解析不同的IP,实现 就近访问。为了保证高可用性等,需要监视各节点的流量、健康状况等。一个节点的单台Cache承载数量不够时,才需要多台Cache,多台Cache同时 工作,才需要负载均衡器,使Cache群协同工作。

4. 部署

  1. 常见的业务流程
    client ->| DNS -> CDN -> | proxy -> web server

  2. 安装Varnish

[root@server4 ~]# yum install -y jemalloc-3.6.0-1.el7.x86_64.rpm jemalloc-devel-3.6.0-1.el7.x86_64.rpm varnish-4.0.5-1.el7.x86_64.rpm varnish-libs-4.0.5-1.el7.x86_64.rpm 

安装完成之后,默认的配置文件在/etc/varnish/目录下,配置脚本在/usr/lib/systemd/system/varnish.service
此处需要修改其监听端口,并启动:

[root@server4 varnish]# vim varnish.params

 14 VARNISH_LISTEN_PORT=80

[root@server4 varnish]# vim default.vcl
##添加默认后端服务器
 16 backend default {
 17     .host = "172.25.25.2";	#nginx 所在主机
 18     .port = "80";
 19 }
 20 
[root@server4 varnish]# systemctl start varnish

测试:

[root@westos ~]# curl 172.25.25.4
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@westos ~]# curl -I 172.25.25.4
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Sun, 04 Jul 2021 06:30:40 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Thu, 10 Jun 2021 14:22:31 GMT
ETag: "60c22027-264"
X-Varnish: 5 3
Age: 28
Via: 1.1 varnish-v4
Connection: keep-alive

增加缓存设置
为响应添加 X-Cache首部,显示缓存是否命中:

[root@server4 varnish]# vim default.vcl

 40 if (obj.hits > 0) {
 41         set resp.http.X-Cache = "HIT from westos cache";
 42     }
 43     else {
 44         set resp.http.X-Cache = "MISS from westos cache";
 45         }
 46     return (deliver);
[root@server4 varnish]# systemctl reload varnish

测试:

[root@westos ~]# curl -I 172.25.25.4
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Sun, 04 Jul 2021 06:35:29 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Thu, 10 Jun 2021 14:22:31 GMT
ETag: "60c22027-264"
X-Varnish: 32776
Age: 0
Via: 1.1 varnish-v4
X-Cache: MISS from westos cache	#第一次缓存中没有
Connection: keep-alive

[root@westos ~]# curl -I 172.25.25.4
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Sun, 04 Jul 2021 06:35:29 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Thu, 10 Jun 2021 14:22:31 GMT
ETag: "60c22027-264"
X-Varnish: 13 32777
Age: 1
Via: 1.1 varnish-v4
X-Cache: HIT from westos cache	#第二次以及以后都是从缓存中加载,并没有去访问后端的nginx
Connection: keep-alive

5. 负载均衡及健康检查

需要再启用一台Nginx服务器,来做负载均衡.

[root@server2 local]# rsync -a nginx server3:/usr/local/
[root@server3 ~]# vim .bash_profile 
[root@server3 ~]# source .bash_profile 
[root@server3 ~]# nginx
  1. 默认后端服务器
    然后在 CDN 中加入新加入的后端服务器来做调度;
[root@server4 varnish]# vim default.vcl

 16 backend web1 {
 17     .host = "172.25.25.2";
 18     .port = "80";
 19 }
 20 
 21 backend web2 {
 22     .host = "172.25.25.3";
 23     .port = "80";
 24 }
 25 

让不同的后端来维护不同的网站,在nginx 中配置更多的网站;

[root@server2 conf]# vim nginx.conf

117 server {
118         listen 80;
119         server_name www.westos.org;
120 
121         location / {
122                 root /www;
123                 index index.html;
124         }
125 }
[root@server2 conf]# mkdir /www
[root@server2 conf]# echo www.westos.org > /www/index.html
[root@server2 conf]# nginx -s reload

[root@server3 conf]# vim nginx.conf

117 server {
118         listen 80;
119         server_name bbs.westos.org;
120 
121         location / {
122                 root /bbs;
123                 index index.html;
124         }
125 }
[root@server3 conf]# mkdir /bbs
[root@server3 conf]# echo bbs.westos.org > /bbs/index.html
[root@server3 conf]# nginx -s reload

根据不同的域名,分发到不同的后端主机:

[root@server4 varnish]# vim default.vcl

 26 sub vcl_recv {
 27 if (req.http.host ~ "^(www.)?westos.org") {
 28                 set req.http.host = "www.westos.org";
 29                 set req.backend_hint = web1;
 30                 #return(pass);
 31         }
 32         elseif (req.http.host ~ "^bbs.westos.org") {
 33                 set req.backend_hint = web2;
 34                 #return(pass);
 35         }
 36         else {
 37                 return(synth(404,"Not in cache"));
 38         }
[root@server4 varnish]# systemctl reload varnish

测试:

[root@westos ~]# curl 172.25.25.4
<!DOCTYPE html>
<html>
  <head>
    <title>404 Not in cache</title>
  </head>
  <body>
    <h1>Error 404 Not in cache</h1>	#此时在访问时,除了以上的域名之外其他都不能访问。
    <p>Not in cache</p>
    <h3>Guru Meditation:</h3>
    <p>XID: 15</p>
    <hr>
    <p>Varnish cache server</p>
  </body>
</html>
做本地解析来访问:
[root@westos ~]# vim /etc/hosts 
[root@westos ~]# ping www.westos.org
PING server4 (172.25.25.4) 56(84) bytes of data.
64 bytes from server4 (172.25.25.4): icmp_seq=1 ttl=64 time=0.136 ms
^C
--- server4 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.136/0.136/0.136/0.000 ms
[root@westos ~]# ping bbs.westos.org
PING server4 (172.25.25.4) 56(84) bytes of data.
64 bytes from server4 (172.25.25.4): icmp_seq=1 ttl=64 time=0.291 ms
^C
--- server4 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.291/0.291/0.291/0.000 ms
[root@westos ~]# curl www.westos.org
www.westos.org
[root@westos ~]# curl bbs.westos.org
bbs.westos.org

缓存默认是有时间的,当在缓存时间内时,如果后端发生变化,此时是不能判断到的。需要手动干预。

2.负载均衡
根据不同的域名, 分发到不同的后端主机。

在生产环境中,同一个域名映射的主机不是一个;
在server3 上配置两个网页;

[root@server3 conf]# vim nginx.conf
server {
        listen 80;
        server_name bbs.westos.org;

        location / {
                root /bbs;
                index index.html;
        }
}

server {
        listen 80;
        server_name www.westos.org;

        location / {
                root /www;
                index index.html;
        }
}
[root@server3 conf]# echo www.westos.org -server > /www/index.html
[root@server3 conf]# nginx -s reload

在 vanish 所在主机上配置负载均衡:

[root@server4 varnish]# vim default.vcl

 26 import directors;	#在4版本需要导入模块,
 #directors模块包含:round_robin,fallback,random,hash四个对象即四种负载均衡模式。
 27 sub vcl_init {
 28         new web_cluster = directors.round_robin();
 # 初始化时,初始化一个负载均衡器。
 29         web_cluster.add_backend(web1);
 30         web_cluster.add_backend(web2);
 31 }
 33 sub vcl_recv {
 34 if (req.http.host ~ "^(www.)?westos.org") {
 35                 set req.http.host = "www.westos.org";
 36                 set req.backend_hint = web_cluster.backend();	#修改此处
 37                 return(pass);	#不让其缓存
 38         }
 39         elseif (req.http.host ~ "^bbs.westos.org") {
 40                 set req.backend_hint = web2;
 41                 #return(pass);
 42         }
 43         else {
 44                 return(synth(404,"Not in cache"));
 45         }
[root@server4 varnish]# systemctl reload varnish

测试:负载均衡效果已经出来了

[root@westos ~]# curl www.westos.org 
www.westos.org
[root@westos ~]# curl www.westos.org 
www.westos.org -server
[root@westos ~]# curl www.westos.org 
www.westos.org
[root@westos ~]# curl www.westos.org 
www.westos.org -server
[root@westos ~]# curl www.westos.org -I
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Sun, 04 Jul 2021 07:20:29 GMT
Content-Type: text/html
Content-Length: 23
Last-Modified: Sun, 04 Jul 2021 07:10:36 GMT
ETag: "60e15eec-17"
Accept-Ranges: bytes
X-Varnish: 32804
Age: 0
Via: 1.1 varnish-v4
X-Cache: MISS from westos cache	#没有缓存
Connection: keep-alive

有了负载均衡之后,就需要健康检测;如果此时一个页面出错了,他vanish 还是会调度的。

  1. 健康检查
[root@server4 varnish]# vim default.vcl

 17 probe backend_healthcheck {
 18     .url = "/index.html";
 19     .window = 3;
 20     .threshold = 2;
 21     .interval = 3s;
 22 }
 23 
 24 backend web1 {
 25     .host = "172.25.25.2";
 26     .port = "80";
 27     .probe = backend_healthcheck;
 28 }
 29 
 30 backend web2 {
 31     .host = "172.25.25.3";
 32     .port = "80";
 33     .probe = backend_healthcheck;
 34 }

此时再次测试时,当后端一个出错时,会自动检测到,只调度到一个上。当再次上线时又会恢复。

  1. 定义缓存文件的缓存时长

  2. 使服务端可以获取客户端的原始IP

如果按照这样操作,所有的请求都是CDN发往Server端的,也就是说对Server端来说看到的IP永远是CDN的IP

如果服务端需要根据访问量等信息做业务分析, 这时候如果不做设置, 则服务端获取到的永远都是CDN的IP, 无法满足业务需求。

nginx 在做反向代理时,在拿后端的数据时,后端不可以拿到客户端的IP,用的cookie 来解决该问题;
CDN 也是一个反向代理,CDN 如何拿到客户端的地址呢?

在 server2 上定义nginx负载均衡器:

[root@server2 conf]# vim nginx.conf

 17 http {
 18         upstream westos {
 19         server 172.25.25.3:80;
 20         }
121 server {
122         listen 80;
123         server_name www.westos.org;
124 
125         location / {
126                 #root /www;
127                 #index index.html;
128                 proxy_pass http://westos;
129         }
130 }

修改 server4 的配置信息:去掉健康检测,去掉

以上是关于企业运维之 CDN 内容分发网络的主要内容,如果未能解决你的问题,请参考以下文章

运维实战 CDN内容分发网络

运维必学:全局负载均衡与CDN内容分发

摩杜云将出席2021亚太内容分发大会暨CDN峰会

企业运维之 openstack 的私有网络以及图形化配置

企业运维之 openstack 的私有网络以及图形化配置

CDN节点是啥