基于 Nginx 的 CDN 基础实现

devtools/2025/2/11 22:13:55/

概览

本文是对基于Nginx的CDN网络的学习笔记,阅读的代码为:https://github.com/leandromoreira/cdn-up-and-running

其中,先确定CDN中的一些基础概念:

  • Balancer:负载均衡,即请求数据的流量最开始打到Balancer,由负载均衡算法确定流量导到后续Edge节点,即缓存边缘节点
  • Edge:边缘节点,即具有数据缓存,能够更快响应数据给回客户端的节点,在负载均衡和后端服务之间
  • Backend:后端节点,即实际存储数据的节点

本文阅读学习的仓库,通过Nginx构建所有节点,用到了以下属性

  • vhost_traffic_status:记录并存储每个节点的网络情况,包括处理状态码、处理时间
  • proxy_cache:缓存交互处理,包括缓存路径、过期时间、中断处理、缓存键值存储区域(共享内存)
  • nginx:使用nginx的基础功能,包括 server、location、proxy_pass、upstream 等
  • openresty:配合lua引擎使用的nginx扩展,包括脚本增强、set_by_lua、access_by_lua、balancer_by_lua、content_by_lua 等能力

另外,还是用到 prometheus 作为监控各节点的工具,使用 grafana 作为时间序列数据的可视化工具

实现

Balancer
# vi:syntax=nginx
events {worker_connections 1024;
}error_log stderr;http {resolver 127.0.0.11 ipv6=off;include generic_conf/setup_logging.conf;include generic_conf/lua_path_setup.conf;# 本节点的统计信息,请求时长、status状态等include generic_conf/basic_vts_setup.conf;# 缓存相关设置include generic_conf/setup_cache.conf;init_by_lua_block {loadbalancer = require "loadbalancer"loadbalancer.setup_server_list()}upstream backend {server 0.0.0.1;# 进行流量负载均衡,选定 edge 节点balancer_by_lua_block {loadbalancer.set_proper_server()}keepalive 60;}server {listen 8080;location / {# access 阶段解析dns,并获取 edge 列表,后续在本文件的 backend 进行负载均衡access_by_lua_block {loadbalancer.resolve_name_for_upstream()}# 代理到本文件的backend,进行负载均衡到 edge 节点proxy_pass http://backend;add_header X-Edge LoadBalancer;}# 可通过 /status 接口获取本节点的统计信息include generic_conf/basic_vts_location.conf;}
}

generic_conf/setup_cache.conf 缓存设置如下:

# /cache/ 指定缓存文件存储目录,levels定义缓存目录结构,key_zone 定义存储缓存的键的共享内存区域
# max_size 为缓存最大大小,inactive表示缓存被视为非活的时间,use_temp_path表示不使用临时路径,用缓存目录
# 最终实现:zone_1 共享内存中,存储缓存的键key与数据对应的路径(/cache/中),数据则实际缓存到本机 /cache/ 中
proxy_cache_path /cache/ levels=2:2 keys_zone=zone_1:10m max_size=10m inactive=10m use_temp_path=off;
# 多个请求尝试缓存同一资源,在 lock_timeout 时间窗口内只请求backend一次,其余请求等待资源
proxy_cache_lock_timeout 2s;
# 缓存数据过期或backend失效,允许使用过期的缓存数据
proxy_cache_use_stale error timeout updating;
# 请求backend的超时时间,超过则关闭nginx连接
proxy_read_timeout 2s;
# nginx 向客户端发送数据的超时时间,超过则关闭连接
proxy_send_timeout 2s;
# 如果客户端中止连接,nginx 将继续与后端完成数据获取与缓存本地
proxy_ignore_client_abort on;
Edge实现
# vi:syntax=nginx
events {worker_connections 1024;
}error_log stderr;http {resolver 127.0.0.11 ipv6=off;include generic_conf/setup_logging.conf;include generic_conf/lua_path_setup.conf;# 本节点的统计信息,请求时长、status状态等include generic_conf/basic_vts_setup.conf;# 设置缓存交互策略include generic_conf/setup_cache.conf;# 数据后端,即从哪获取数据缓存到 edge 节点upstream backend {server backend:8080;server backend1:8080;keepalive 10;  # connection pool}server {listen 8080;location / {# 将参数 cache_key 设置为 uriset_by_lua_block $cache_key {return ngx.var.uri}# access 阶段模拟 edge 节点延时access_by_lua_block {local edge = require "edge"edge.simulate_load()}# 获取实际数据的后端 backend 服务器proxy_pass http://backend;# edge 节点缓存处理策略,根据 cache_key 参数获取缓存include generic_conf/define_cache.conf;add_header X-Edge Server;}# 获取当前节点统计信息的接口include generic_conf/basic_vts_location.conf;}
}

edge节点具体实现了缓存策略,根据请求uri作为缓存key,划定某个文件路径存储实际数据value,使用共享内存记录key和缓存路径的映射,利用nginx实现缓存功能

generic_conf/define_cache.conf 缓存处理策略实现:

# 启用名为 zone_1 的共享缓存区域,来存储和检索缓存键key和实际数据的路径映射
proxy_cache zone_1;
# 设置缓存的键为 cache_key 变量
proxy_cache_key $cache_key;
# 启用缓存锁定。当多个请求同时尝试获取同一资源时,只有一个请求会去后端服务器获取数据,其他请求将等待该请求完成
proxy_cache_lock on;
# 设置与后端服务器的 HTTP 协议版本为 1.1,这通常用于启用持久连接
proxy_http_version 1.1;
# 清空 Connection 头
proxy_set_header Connection "";
# 启用代理缓冲。这意味着 Nginx 会在发送响应给客户端之前,先将后端服务器的响应全部接收并缓冲
proxy_buffering on;
# 设置用于缓冲响应的缓冲区数量和大小
proxy_buffers 16 16k;
# 添加一个参数到Header,表示是否命中缓存、正在更新
add_header X-Cache-Status $upstream_cache_status;
Backend
# vi:syntax=nginx
events {worker_connections 1024;
}error_log stderr;http {include generic_conf/setup_logging.conf;include generic_conf/lua_path_setup.conf;# 本节点的统计信息,请求时长、status状态等include generic_conf/basic_vts_setup.conf;server {listen 8080;location / {# 获取数据,模拟延时并返回数据、过期时间、数据键keycontent_by_lua_block {local backend = require "backend"backend.generate_content()}}# 可通过 /status 接口获取本节点的统计信息include generic_conf/basic_vts_location.conf;}
}

backend.generate_content() 后端节点的具体实现:

local simulations = require "simulations"
local backend = {}backend.generate_content = function()-- 模拟 backend 节点延时simulations.for_work_longtail(simulations.profiles.backend)-- 返回数据头,根据 max_age 参数设置过期时间ngx.header['Content-Type'] = 'application/json'ngx.header['Cache-Control'] = 'public, max-age=' .. (ngx.var.arg_max_age or 10)-- 返回数据,记录了 key,即请求 uringx.say('{"service": "api", "value": 42, "request": "' .. ngx.var.uri .. '"}')
endreturn backend

总结

利用Nginx特性实现简易CDN模型,简明概要了CND各个重要模块的主要功能


http://www.ppmy.cn/devtools/158040.html

相关文章

windows server独立部署Qwen2.5-vl-7B

服务器配置信息 CPU:64G GPU:48G(RTX 4090) 一、使用conda下载模型 Qwen2.5-VL-7B-Instruct conda下载 conda create --name qwen python3.11 conda activate qwen 魔塔社区下载模型 pip install modelscope modelscope downl…

课题推荐——基于大数据预测的水面舰艇惯性/星敏感器抗干扰组合导航方法研究

在水面舰艇导航中,星敏感器作为一种重要的高精度定位设备,因其受环境因素(如海面风浪、云层等)影响而导致测量精度下降,尤其是在载体变化和观星高度变化的情况下,星敏感器的性能受到显著影响。这使得其无法…

Git 分布式版本控制工具使用教程

1.关于Git 1.1 什么是Git Git是一款免费、开源的分布式版本控制工具,由Linux创始人Linus Torvalds于2005年开发。它被设计用来处理从很小到非常大的项目,速度和效率都非常高。Git允许多个开发者几乎同时处理同一个项目而不会互相干扰,并且在…

Redis 基本全局命令和单线程架构

Redis 提供了许多命令来管理和操作数据,以下是一些常用的全局命令,这些命令可以帮助你管理和监控 Redis 服务器的状态、配置和数据。 KEYS 语法: KEYS pattern 时间复杂度:O(N) 返回所有满⾜样式(pattern)…

快速搭建 Elasticsearch 8 集群:零基础实战与升级注意事项

引言 随着大数据技术的飞速发展,Elasticsearch 成为许多应用场景中不可或缺的技术,它以其高效的全文搜索引擎和分布式存储架构在企业和个人项目中占据了一席之地。无论是在日志分析、实时搜索还是数据可视化中,Elasticsearch 都发挥着重要的作用。 在这篇文章中,我们将为…

【含开题报告+文档+PPT+源码】基于SpringBoot+Vue旅游管理网站

开题报告 本论文探讨了一款采用现代Web开发技术构建的台州市旅游综合信息与服务平台的设计与实现。该系统基于SpringBoot框架,以其轻量级、快速开发和强大的企业级应用支持能力为核心后端技术支撑,结合Vue.js前端框架及ElementUI组件库,为用…

CSDN 博客之星 2024:肖哥弹架构的社区耕耘总结

#博客之星2024年度总评选—主题文章创作# CSDN 博客之星 2024:肖哥弹架构的社区耕耘总结 肖哥弹架构 是一位专注于技术分享和社区建设的博客作者。今年,我荣幸地再次入选CSDN博客之星TOP300,这不仅是对我过去努力的认可,更是对未…

web3是什么,最简单的介绍

Web3是指第三代互联网技术,也被称为分布式互联网。它是在传统互联网(Web2.0)基础上发展出来的一种新技术体系,旨在通过区块链技术来重新定义人们访问和使用网络服务的方式。以下是关于Web3的详细介绍: 一、核心特点 …