构建和自定义CDN

内容交付网络(CDN)用于站点和应用程序中,主要是为了加快静态元素的加载。发生这种情况是由于在位于不同地理区域的CDN服务器上缓存文件。通过CDN请求数据后,用户从最近的服务器接收数据。

所有内容交付网络的操作原理和功能大致相同。收到下载文件的请求后,CDN服务器一次从原始服务器获取文件并将其提供给用户,同时在给定的时间段内进行缓存。从缓存中回答所有后续请求。所有CDN均具有用于预加载文件,清除缓存,设置其保留期限等选项。

碰巧的是,出于某种原因您需要组织自己的内容交付网络,然后-让我们帮助您制造另一辆自行车。


资料来源:pikisuperstar创建的信息图矢量-www.freepik.com


当您需要自己的CDN时


考虑启动自己的CDN有意义的情况:

  • 当您想省钱时,甚至使用像BunnyCDN这样的廉价CDN时,运行成本也要每月数百美元
  • 如果我们要获得永久性高速缓存或服务器和通道上没有邻居的高速缓存
  • 在您需要的区域中,CDN服务没有服务点
  • 所需的任何特殊内容传送设置
  • 我们希望通过与生产服务器的用户保持更近的距离来加速动态内容的交付
  • 令人担忧的是,第三方CDN服务可能会非法收集或使用有关用户行为的信息(即不符合GDPR的服务)或从事其他非法行为

在大多数其他情况下,建议使用现有的现成解决方案。


您需要运行什么


如果您拥有自己的自治系统(AS),那就太好了。使用它,您可以将同一IP分配给多台服务器,并在网络级别上遵循此说明将用户定向到最近的服务器。值得一提的是,即使使用地址块/ 24,也可以构建内容交付网络。某些服务器提供商允许您发布公告,以供其可用的所有区域使用。

如果您不是一个IP地址块的所有者,那么要运行简单的CDN,您将需要:

  • . ,
  • geoDNS . , ,



使用域名注册,一切都很简单-在任何注册商的任何区域中注册。您还可以将子域用于CDN,例如cdn.namedomain.com之类的。实际上,在我们的示例中,我们将这样做。

至于订购服务器,应在用户读者所在的地区和国家/地区租用服务器。如果该项目是洲际的,则可以方便地选择可以立即为全球提供服务器的托管提供商。示例:OVHLeaseweb100Tb用于专用服务器,VultrDigitalOcean用于虚拟云*。

对于我们的专用CDN,我们在不同的大陆订购了3台虚拟服务器。在vultr在服务器上以每月5美元的价格获得25GB的SSD空间和1TB的流量安装时,选择最新的Debian。我们的服务器:

法兰克福,IP:199.247.18.199

芝加哥,IP:149.28.121.123

新加坡,IP:157.230.240.216

* Vultr和DigitalOcean承诺在添加付款方式后立即向使用本文链接注册的用户提供100美元的贷款。作者还从中得到了一点赞美,这对他现在是非常重要的。请谅解。


配置geoDNS


因此,当用户访问CDN域或子域时,将他定向到所需的服务器(最接近他的服务器),我们需要具有geoDNS功能的DNS服务器。

geoDNS的原理和过程如下:

  1. 定义发送DNS请求的客户端的IP或用于处理客户端请求的递归DNS服务器的IP。这些递归服务器通常是DNS提供程序。
  2. 通过IP客户知道他的国家或地区。为此,使用了GeoIP基础,今天有许多基础。有一些不错的免费选择
  3. 根据客户的位置,他会给他最近的CDN服务器的IP地址。

您可以自己构建带有geoDNS功能 DNS服务器,但是最好将现成的解决方案与世界各地的DNS服务器网络和Anycast配合使用:

  • louDNS $ 9.95 /月,GeoDNS关税,默认情况下有一个DNS故障转移
  • Zilore $ 25 /每月,启用DNS故障转移
  • 亚马逊Route 53 $ 35 / mo起,进行50M净地理请求。DNS故障转移单独收费
  • DNS轻松起价 $ 125 / mo,共有10个DNS故障转移
  • Cloudflare,企业指导中提供的地理导航功能

订购geoDNS时,应注意资费中包含的请求数量,并应考虑到对域的实际呼叫数量可能超出预期数倍。数以百万计的蜘蛛,扫描仪,垃圾邮件制造者和其他恶魔不知疲倦地工作。

几乎所有DNS服务都包括构建CDN服务必不可少的部分-DNS故障转移。使用它,您可以配置对服务器的监视,并且在没有生命迹象的情况下,可以在DNS答案中用备份服务器自动替换不工作的服务器地址。

为了建立我们的CDN,我们将使用ClouDNS的GeoDNS关税。

在您的帐户中添加一个新的DNS区域,指示您的域。如果我们将在子域上构建CDN,并且已经在使用主域,那么在添加区域后,不要忘记添加现有的工作DNS记录。下一步是为CDN域/子域创建几个A记录,每个记录将应用于我们设置的区域。您可以将大洲或国家/地区指定为区域;美国和加拿大可以使用子区域。

在我们的情况下,CDN将在子域的cdn.sayt.in引发添加sayt.in区域,为该子域创建第一个A记录,并将整个北美地区至芝加哥的服务器:


对其他区域重复上述操作,记住要为默认区域创建一个条目。结果如下:



屏幕快照中的最后一个默认记录意味着所有未确定的区域(这是欧洲,非洲,卫星Internet用户等)将被发送到法兰克福的服务器。

这样就完成了基本的DNS配置。仍然可以访问域名注册商的网站,并用ClouDNS发布的域名替换当前的域名NS。在更新NS的同时,我们将准备服务器。


安装SSL证书


我们的CDN可以在HTTPS上运行,因此,如果您已经拥有域或子域的SSL证书,则将它们上传到所有服务器,例如在目录/ etc / ssl / yourdomain /中。

如果没有证书,则可以从Let's Encrypt获得免费的证书。ACME Shell脚本非常适合此操作。客户端既方便又易于配置,最重要的是-允许您通过ClouDNS的API验证DNS的域/子域。

我们将仅在其中一台服务器(欧洲199.247.18.199)上安装acme.sh,从中将证书复制到所有其他服务器上。要安装,请执行以下操作:

root@cdn:~# wget -O - https://get.acme.sh | bash; source ~/.bashrc

在安装脚本的过程中,将创建CRON任务,以在我们不参与的情况下进一步续订证书。

颁发证书时的域验证将使用该API使用DNS进行,因此,在Reseller API菜单的ClouDNS个人帐户中,您需要创建一个新的用户API并为其设置密码。生成的带有密码的auth-id将写入文件〜/ .acme.sh / dnsapi / dns_cloudns.sh(不要与dns_clou d dns.sh文件混淆)。以下是取消注释和编辑的行:

CLOUDNS_AUTH_ID=<auth-id>
CLOUDNS_AUTH_PASSWORD="<>"

现在,我们要求cdn.sayt.in的SSL证书

root@cdn:~# acme.sh --issue --dns dns_cloudns -d cdn.sayt.in --reloadcmd "service nginx reload"

在将来的参数中,我们指定了一条命令,以在将来每次证书有效期更新后自动重新加载Web服务器配置。

获取证书的整个过程最多可能需要2分钟,请不要中断它。如果发生域验证错误,请尝试再次运行该命令。最后,我们将看到证书的上传位置:



请记住这些路径,将证书复制到其他服务器时以及在Web服务器设置中需要指定它们。我们不注意重新加载Nginx配置文件的错误-在完全配置的服务器上,续订证书时将不存在该错误。

通过SSL对我们来说,剩下的就是将接收到的证书复制到另外两个服务器,同时保存文件的路径。在每个目录上创建相同的目录并进行复制:

root@cdn:~# mkdir -p /root/.acme.sh/cdn.sayt.in/
root@cdn:~# scp -r root@199.247.18.199:/root/.acme.sh/cdn.sayt.in/* /root/.acme.sh/cdn.sayt.in/

为了定期更新证书,我们将使用以下命令在两台服务器上创建每日CRON任务:
scp -r root@199.247.18.199:/root/.acme.sh/cdn.sayt.in/* /root/.acme.sh/cdn.sayt.in/ && service nginx reload

在这种情况下,必须通过键(即,无需输入密码。不要忘记这样做。


安装和配置Nginx


要返回静态内容,我们将使用配置为缓存代理服务器的Nginx。更新软件包列表,并将其安装在所有三台服务器上:

root@cdn:~# apt update
root@cdn:~# apt install nginx

使用默认配置,而不是默认配置:
nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
    worker_connections 4096;
    multi_accept on;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    types_hash_max_size 2048;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    access_log off;
    error_log /var/log/nginx/error.log;

    gzip on;
    gzip_disable "msie6";
    gzip_comp_level 6;
    gzip_proxied any;
    gzip_vary on;
    gzip_types text/plain application/javascript text/javascript text/css application/json application/xml text/xml application/rss+xml;
    gunzip on;            

    proxy_temp_path    /var/cache/tmp;
    proxy_cache_path   /var/cache/cdn levels=1:2 keys_zone=cdn:64m max_size=20g inactive=7d;
    proxy_cache_bypass $http_x_update;

server {
  listen 443 ssl;
  server_name cdn.sayt.in;

  ssl_certificate /root/.acme.sh/cdn.sayt.in/cdn.sayt.in.cer;
  ssl_certificate_key /root/.acme.sh/cdn.sayt.in/cdn.sayt.in.key;

  location / {
    proxy_cache cdn;
    proxy_cache_key $uri$is_args$args;
    proxy_cache_valid 90d;
    proxy_pass https://sayt.in;
    }
  }
}


在配置中,编辑:

  • max_size-缓存大小不超过可用磁盘空间
  • 非活动状态 -没有人访问的缓存数据的存储时间
  • ssl_certificatessl_certificate_key -SSL证书和密钥文件的路径
  • proxy_cache_valid-缓存数据的存储时间
  • proxy_pass -CDN将从中请求缓存文件的原始服务器的地址。在我们的示例中,这是sayt.in

如您所见,一切都很简单。由于inactiveproxy_cache_valid指令的相似性,因此复杂性只能在设置缓存时间时出现我们将在示例中对其进行分析。这是inactive = 7dproxy_cache_valid 90d发生的情况

  • 如果在7天内未重复请求,则在此时间段后,数据将从缓存中删除
  • 如果该请求至少每7天重复一次,则缓存中的数据将在90天后被视为过时,并且在下一个请求时,Nginx将通过从原始服务器获取数据来对其进行更新

完成nginx.conf的编辑后,重新加载配置:

root@cdn:~# service nginx reload

我们的CDN已完全准备就绪。每月$ 15 我们在三大洲拥有3 TB的流量,每个站点有1 TB的流量。


检查CDN的操作


让我们看一下来自不同地理位置的CDN。为此,任何ping服务都适用。
发射点主办知识产权平均时间,毫秒
德国柏林赛迪网199.247.18.1999.6
荷兰,阿姆斯特丹赛迪网199.247.18.19910.1
法国巴黎赛迪网199.247.18.19916.3
英国伦敦赛迪网199.247.18.19914.9
加拿大多伦多赛迪网149.28.121.12316.2
美国,旧金山赛迪网149.28.121.12352.7
美国达拉斯赛迪网149.28.121.12323.1
美国,芝加哥赛迪网149.28.121.1232.6
美国,纽约赛迪网149.28.121.12319.8
新加坡赛迪网157.230.240.2161.7
日本东京赛迪网157.230.240.21674.8
澳大利亚,悉尼赛迪网157.230.240.21695.9
效果不错。现在,我们将测试图像test.jpg放在主站点的根目录中,并通过CDN检查其下载速度。说快内容交付迅速。

如果要清除CDN点上的缓存,我们将编写一个小脚本。
清除
#!/bin/bash
if [ -z "$1" ]
then
    echo "Purging all cache"
    rm -rf /var/cache/cdn/*
else
    echo "Purging $1"
    FILE=`echo -n "$1" | md5sum | awk '{print $1}'`
    FULLPATH=/var/cache/cdn/${FILE:31:1}/${FILE:29:2}/${FILE}
    rm -f "${FULLPATH}"
fi


要删除整个缓存,只需运行它,就可以像这样清除一个单独的文件:

root@cdn:~# ./purge.sh /test.jpg


而不是结论


最后,我想提供一些有用的技巧,以便立即克服这一问题,这一次使我的头发麻了:

  • 为了提高CDN容错能力,建议配置DNS故障转移,以帮助在服务器发生故障时快速更改A记录。这是在域的DNS记录的控制面板中完成的
  • CDN, . CDN, 6-7 : , (), (), , ,
  • CDN. , , -
  • , ,
  • 尝试检查从不同位置到您的服务器的ping这样您就可以看到最靠近CDN点的区域并正确配置GeoDNS
  • 根据任务的不同,针对特定的缓存要求配置Nginx并考虑服务器上的负载并不是没有道理的。有关Nginx缓存的文章- 此处以及重负载下的工作加速:此处此处对我有很大帮助。

All Articles