Nginx 实现简易 CDN
CDN 简介
什么是 CDN
为了解决互联网上越来越多内容的传输、存储、分发等问题,提供给终端用户更好的访问和使用体验,CDN 便是一个高性价比,操作便捷,快速实现的解决方案。CDN(Content Delivery Network),是在现有 Internet 中增加一层新的网络架构,由遍布全国的高性能加速 节点构成。这些高性能的服务节点都会按照一定的缓存策略存储您的业务内容,当您的用户 向您的某一业务内容发起请求时,请求会被调度至最接近用户的服务节点,直接由服务节点 直接快速响应,有效降低用户访问延迟,提升可用性。
CDN 的基本原理
假设您的业务源站域名为 www.test.com ,当域名接入 CDN 开始使用加速服务后,您
的用户发起 HTTP 请求,实际的处理流程如图所示:
详细说明如下:
- 用户向 www.test.com 下的某图片资源,如 1.jpg 发起请求,先要向 Local DNS 发起域名解析请求;
- 当 Local DNS 解 析 www.test.com 时 , 会 发 现 已 经 配 置 了 CNAME www.test.com.cdn.dnsv1.com,解析请求会发送至 Tencent DNS(GSLB),GSLB 为腾讯云自主研发的调度体系,会为请求分配最佳节点 IP;
- Local DNS 获取 Tencent DNS 返回的解析 IP;
- 用户测获取解析 IP;
- 用户向获取的 IP 发起对资源 1.jpg 的访问请求;
- 若该 IP 对应的节点缓存有 1.jpg,则会将数据直接返回给用户(10),此时请求结束。若该节点未缓存 1.jpg,则节点会向业务源站发起对 1.jpg 的请求(6、7、8),获取资源后,结合用户自定义配置的缓存策略(可参考用户指南中缓存时间设置章节内容),将资源存储(9),并返回给用户(10),此时请求结束。
可以使用哪些开源软件自建 CDN
Nginx,Varnish,Squid,Apache Traffic Server,Fikker,WDCDN 等软件/系统都可以实现 CDN 的功能。本文将使用 Nginx 来实现一个简易的 CDN 系统。
使用 Nginx 搭建简易 CDN
开启代理缓存
proxy_temp_path /data/cdn_cache/proxy_temp_dir;
proxy_cache_path /data/cdn_cache/proxy_cache_dir levels=1:2 keys_zone=cache_one:50m inactive=1d max_size=1g;
proxy_connect_timeout 5;
proxy_read_timeout 60;
proxy_send_timeout 5;
proxy_buffer_size 16k;
proxy_buffers 4 64k;
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 128k;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_404;
配置上游服务器
upstream www.example.com.pool
{
server www.example.com weight=10 max_fails=3;
}
配置反向代理
server
{
listen 80;
server_name www.example.com;
access_log /var/log/nginx/www.example.com-access.log main;
location ~ .*\.(gif|jpg|png|html|htm|css|js|ico|swf|pdf)$
{
#Proxy
proxy_redirect off;
proxy_next_upstream http_502 http_504 http_404 error timeout invalid_header;
proxy_set_header Host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://www.example.com.pool;
#Use Proxy Cache
proxy_cache cache_one;
proxy_cache_key "$host$request_uri";
add_header Cache "$upstream_cache_status";
proxy_cache_valid 200 304 301 302 8h;
proxy_cache_valid 404 1m;
proxy_cache_valid any 2d;
}
location /
{
proxy_redirect off;
proxy_next_upstream http_502 http_504 http_404 error timeout invalid_header;
proxy_set_header Host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://www.example.com.pool;
client_max_body_size 40m;
client_body_buffer_size 128k;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_buffer_size 64k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
}
}
缓存刷新
编写一个简单的 Shell 脚本来实现缓存刷新的功能,用法:./nginx_purge.sh URL
#!/bin/bash
cache_purge(){
PURGE_URL=$1
URL_NAME=$(echo -n $PURGE_URL | md5sum | awk '{print $1}')
FILE_NAME=$(echo $URL_NAME | awk '{print "/data/cdn_cache/proxy_cache_dir/"substr($0,length($0),1)"/"substr($0,length($0)-2,2)"/"$0}')
rm -rf $FILE_NAME
}
purge_file(){
PURGE_FILE=$1
for url in $(cat $PURGE_FILE);do
cache_purge $url
done
}
purge_url(){
PURGE_URL=$1
cache_purge $PURGE_URL
}
usage(){
echo $"Usage: $0 <url_file | 'url'>"
}
main (){
if [ "$#" -ne 1 ];then
usage;
else
if [ -f $1 ];then
purge_file $1;
else
purge_url $1;
fi
fi
}
main $1
存在问题
- 不能刷新目录