视频播放网站CDN内容分发网络实现

news/2024/5/14 0:20:27/文章来源:https://blog.csdn.net/cuibinmo3519/article/details/100433955

视频播放如果只有一台视频服务器,当访问用户过多时,服务器将承受不了负载。

所以我们需要在视频服务器下面增加边缘服务器,下面以视频服务器加三台边缘服务器为例。

网络环境图:


image

 

1. 用户可通过PC机或手机访问网站。

2. 网站将用户请求转向到负载较小的边缘服务器。

3. 边缘服务器接收到用户请求,先在本地检查用户请求文件是否存在。

4. 如果存在则直接返回本地文件进行播放。

5. 如果不存在则将用户请求转向到视频服务器,并将该视频文件下载到本地。

6. 当用户请求边缘服务器上视频文件,将更新文件最后修改时间,最后修改时间超过一定天数则将该文件删除。

 

根据以上介绍我们应该对CDN有了一些了解,下面来看看代码方面怎么实现:

第一步先编写一个用于检查本地文件是否存在的IModule,该IModule存在以下文件:

配置文件:Config.xml

xml version="1.0" encoding="utf-8" ?>
<Config><!-- 本地点播下载IP --&gt<LocalIP>192.168.1.103LocalIP><!-- 本地点播下载端口 --&gt<LocalPort>8002LocalPort><!-- 服务器IP --&gt<ServerIP>192.168.1.6ServerIP><!-- 服务端口 --&gt<ServerPort>80ServerPort><!-- 本地文件保存路径 --&gt<SavePath>C:\\FileSavePath><!-- 待下载文件TXT路径 --&gt<TxtPath>C:\\IisFileCheckModule\\WaitDownFile.txtTxtPath>
Config>

 

文件检查IModule:FileCheckModule.cs

public class FileCheckModule : IHttpModule
{/// <summary>/// 初始化/// summary>/// <param name="app">param>public virtual void Init(HttpApplication app){app.BeginRequest += new EventHandler(app_BeginRequest);app.AuthenticateRequest += new EventHandler(app_AuthenticateRequest);}void app_AuthenticateRequest(object sender, EventArgs e){HttpApplication app = (HttpApplication)sender;if (!String.IsNullOrEmpty(app.Request.Path) && app.Request.Path != "/"){FileCheckConfig config = new FileCheckConfig();//获得文件路径string filePath = config.SavePath + app.Request.Path.Replace("/", "\\");//获得文件名string fileName = Path.GetFileName(filePath);string fileExtension = Path.GetExtension(filePath);if (!String.IsNullOrEmpty(fileExtension)){if (!File.Exists(filePath)){//生成点播或下载路径string downUrl = "http://" + config.ServerIP + app.Request.Path;//在文本文件中新增待下载文件WaitDownFileTxtManage myWaitDownFileTxtManage = new WaitDownFileTxtManage();myWaitDownFileTxtManage.AddNewFileDownText(fileName, filePath, downUrl);//重写用户请求URLapp.Context.Response.Redirect(downUrl);}else{//生成本地点播或下载路径string localUrl = "http://" + config.LocalIP + app.Request.Path;//设置请求文件修改时间为当前时间File.SetLastWriteTime(filePath, DateTime.Now);//重写用户请求URLapp.Context.Response.Redirect(localUrl);}}}}protected void app_BeginRequest(object sender, EventArgs e){}/// <summary>/// 释放/// summary>public virtual void Dispose(){}
}

 

文件检查配置获取:FileCheckConfig.cs

public class FileCheckConfig
{private string localIP;/// /// 本地点播IP地址/// 
    public string LocalIP{get { return localIP; }set { localIP = value; }}private string serverIP;/// /// 服务器IP地址/// 
    public string ServerIP{get { return serverIP; }set { serverIP = value; }}private string savePath;/// /// 文件保存路径/// 
    public string SavePath{get { return savePath; }set { savePath = value; }}private string txtPath;/// /// 待下载文件列表txt文件路径/// 
    public string TxtPath{get { return txtPath; }set { txtPath = value; }}public FileCheckConfig(){XmlDocument doc = new XmlDocument();//string configPath =  ConfigurationManager.AppSettings["ConfigPath"].ToString();
        doc.Load("C:\\inetpub\\IISCdn\\IisFileCheckModule\\Config.xml");XmlNode configNode = doc.SelectSingleNode("Config");LocalIP = configNode.SelectSingleNode("LocalIP").InnerText + ":" + configNode.SelectSingleNode("LocalPort").InnerText;ServerIP = configNode.SelectSingleNode("ServerIP").InnerText + ":" + configNode.SelectSingleNode("ServerPort").InnerText;SavePath = configNode.SelectSingleNode("SavePath").InnerText;TxtPath = configNode.SelectSingleNode("TxtPath").InnerText;}
}

 

待下载文件信息添加:WaitDownFileTxtManage.cs

public class WaitDownFileTxtManage
{/// /// 配置对象/// 
    FileCheckConfig config = null;public WaitDownFileTxtManage(){config = new FileCheckConfig();//检查文件是否存在
        if (!File.Exists(config.TxtPath)){//创建一个新的txt文件
            StreamWriter sw = File.CreateText(config.TxtPath);sw.Close();}}/// /// 添加一个新的下载文件/// /// 文件名称/// 文件保存路径/// 文件下载路径
    public void AddNewFileDownText(string fileName, string fileSavePath, string fileDownPath){try{string downFile = fileName + ";" + fileSavePath + ";" + fileDownPath;//检查是否已存在相同下载文件
            using (StreamReader sr = new StreamReader(config.TxtPath)){String line;while ((line = sr.ReadLine()) != null){if (line == downFile)return;}}//添加待下载文件
            using (StreamWriter sw = File.AppendText(config.TxtPath)){sw.WriteLine(downFile);sw.Close();}}catch (System.Exception e){WriteLog("添加待下载文件时出现异常:" + e.Message, true);}}/// /// 打印日志方法/// /// 错误信息/// 是否显示时间
    public static void WriteLog(string message, bool isShowDate){string LogPath = "C:\\Log";FileStream MainFileStream = null;string outMess = message;if (isShowDate){string dateStamp = System.DateTime.Now.ToString("HH:mm:ss") + " >> ";outMess = dateStamp + message;}outMess = outMess + "\r\n";//
        string year = System.DateTime.Now.Year.ToString();//
        string month = System.DateTime.Now.Month.ToString();//
        string day = System.DateTime.Now.Day.ToString();string aimPath = LogPath + "/" + year + "/" + month + "/" + day;if (!Directory.Exists(aimPath)){#regiontry{Directory.CreateDirectory(aimPath);}catch (Exception me){me.ToString();}#endregion}try{string currentLogPath = aimPath + "/" + System.DateTime.Now.Hour.ToString() + ".txt";byte[] messB = System.Text.Encoding.Default.GetBytes(outMess);MainFileStream = new FileStream(currentLogPath, System.IO.FileMode.Append, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);MainFileStream.Write(messB, 0, messB.Length);}catch (Exception me){me.ToString();}finally{if (MainFileStream != null){MainFileStream.Flush();MainFileStream.Close();}}}
}

 

这里将待下载文件信息记录在txt文档里,大家在做的时候可以用一个Access数据库实现。

在部署该IModule的时候,需要将IIS处理程序映射中的StaticFile删除

image

然后添加新的脚本映射

image

可执行文件路径为

C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll

这样的话,IModule便部署完成了,IModule接收到用户请求后先会在配置文件配置的本地文件路径中查找视频文件,如果找到文件则会转向到本地IIS中部署的另外一个文件站点;如果未找到文件则将请求转向到视频服务器。

 

第二步我们需要编写一个文件下载服务,该服务存在以下文件:

配置文件:App.config

<appSettings><!-- 服务器地址 --&gt<add key="ServerIP" value="192.168.1.6"/><!-- 本地文件保存路径 --&gt<add key="SavePath" value="C:\\inetpub\\IISCdn\\File"/><!-- 待下载XML文件路径 --&gt<add key="txtPath" value="C:\\inetpub\\IISCdn\\IisFileCheckModule\\WaitDownFile.txt"/><!-- 服务运行间隔时间 --&gt<add key="Interval" value="1"/><!-- 并行下载数 --&gt<add key="QueueCount" value="5"/>
appSettings>

 

下载文件服务,需在服务中添加一个时间控件:FileDown.cs

partial class FileDown : ServiceBase
{//保存下载文件
    Hashtable htDowFile = new Hashtable();//下载文件数
    int queueCount = Convert.ToInt32(ConfigurationManager.AppSettings["QueueCount"]);//当前下载文件数
    int downCount = 0;public FileDown(){InitializeComponent();}protected override void OnStart(string[] args){// TODO: 在此处添加代码以启动服务。
        fileDownTimer.Interval = 10000;fileDownTimer.Start();//记录服务运行日志
        Logger.LogDebug("FileDown", "OnStart", "文件下载服务开始运行。", null);}protected override void OnStop(){// TODO: 在此处添加代码以执行停止服务所需的关闭操作。
        fileDownTimer.Stop();//记录服务运行日志
        Logger.LogDebug("FileDown", "OnStop", "文件下载服务停止运行。", null);}/// /// 时间控件处理事件/// /// /// 
    private void fileDownTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e){//记录文件下载日志
        Logger.LogDebug("FileDown", "fileDownTimer_Elapsed", "开始一轮新的文件下载。", null);fileDownTimer.Stop();WaitDownFileTxtManage myWaitDownFileXmlManage = new WaitDownFileTxtManage();FileDownCommon myFileDownCommon = new FileDownCommon();//从配置文件内获取txt文件路径
        string txtPath = ConfigurationManager.AppSettings["txtPath"].ToString();//循环下载所有文件
        using (StreamReader sr = new StreamReader(txtPath)){String line;while ((line = sr.ReadLine()) != null){string[] fileElement = line.Split(';');string downFileSavePath = fileElement[1] + ".downing";if (!File.Exists(downFileSavePath)){if (downCount <= queueCount){downCount++;ThreadPool.QueueUserWorkItem(DownFile, line);}}}}//记录文件下载日志
        Logger.LogDebug("FileDown", "fileDownTimer_Elapsed", "结束一轮新的文件下载。", null);Double interval = Convert.ToDouble(ConfigurationManager.AppSettings["Interval"].ToString());fileDownTimer.Interval = interval * 60 * 1000;fileDownTimer.Start();}/// /// 下载文件方法/// /// 下载文件
    private void DownFile(object downFile){WaitDownFileTxtManage myWaitDownFileTxtManage = new WaitDownFileTxtManage();string[] fileElement = downFile.ToString().Split(';');string fileName = fileElement[0];string downFileSavePath = fileElement[1] + ".downing";string trueFilePath = fileElement[1];string fileDownPath = fileElement[2];string pathNoFile = downFileSavePath.Substring(0, downFileSavePath.LastIndexOf("\\"));//检查保存路径是否存在
        if (!Directory.Exists(pathNoFile)){Directory.CreateDirectory(pathNoFile);}//记录文件下载日志
        Logger.LogDebug("FileDownCommon", "DownFile", "\"" + fileDownPath + "\"文件开始下载。", null);//打开上次下载的文件或新建文件
        long lStartPos = 0;System.IO.FileStream fs;if (System.IO.File.Exists(downFileSavePath)){fs = System.IO.File.OpenWrite(downFileSavePath);lStartPos = fs.Length;fs.Seek(lStartPos, System.IO.SeekOrigin.Current); //移动文件流中的当前指针
        }else{fs = new System.IO.FileStream(downFileSavePath, System.IO.FileMode.Create);lStartPos = 0;}//打开网络连接
        try{System.Net.WebRequest webRequest = System.Net.WebRequest.Create(fileDownPath);webRequest.Timeout = 10000;System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)webRequest;System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();//System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(fileDownPath);//请求正常
            if (response.StatusCode == System.Net.HttpStatusCode.OK){if (lStartPos > 0)request.AddRange((int)lStartPos); //设置Range值//向服务器请求,获得服务器回应数据流
                System.IO.Stream ns = response.GetResponseStream();byte[] nbytes = new byte[10240];int nReadSize = 0;nReadSize = ns.Read(nbytes, 0, 10240);while (nReadSize > 0){fs.Write(nbytes, 0, nReadSize);nReadSize = ns.Read(nbytes, 0, 10240);}fs.Close();ns.Close();File.Move(downFileSavePath, trueFilePath);//删除下载完成的文件
                myWaitDownFileTxtManage.DeleteDownFile(fileName, trueFilePath, fileDownPath);downCount--;//记录文件下载日志
                Logger.LogDebug("FileDownCommon", "DownFile", "\"" + fileDownPath + "\"文件下载完成。", null);}//文件未找到
            else if (response.StatusCode == System.Net.HttpStatusCode.NotFound){//删除不存在的文件
                myWaitDownFileTxtManage.DeleteDownFile(fileName, trueFilePath, fileDownPath);downCount--;fs.Close();Logger.LogDebug("FileDownCommon", "DownFile", "\"" + fileDownPath + "\"文件在服务器上不存在。", null);}}catch (FileNotFoundException fileEx){fs.Close();downCount--;//删除不存在的文件
            myWaitDownFileTxtManage.DeleteDownFile(fileName, trueFilePath, fileDownPath);//记录异常日志
            Logger.LogError("FileDownCommon", "DownFile", AppError.EROR, 0, fileEx, "\"" + fileDownPath + "\"文件在服务器上不存在。", null);}catch (Exception ex){fs.Close();downCount--;//记录异常日志
            Logger.LogError("FileDownCommon", "DownFile", AppError.EROR, 0, ex, "下载文件\"" + fileDownPath + "\"过程中出现错误:" + ex.ToString(), null);}}
}

 

待下载文件读取:WaitDownFileTxtManage.cs

public class WaitDownFileTxtManage
{//txt文件路径
    string txtPath = "";public WaitDownFileTxtManage(){//从配置文件内获取txt文件路径
        txtPath = ConfigurationManager.AppSettings["txtPath"].ToString();//检查文件是否存在
        if (!File.Exists(txtPath)){//创建一个新的txt文件
            StreamWriter sw = File.CreateText(txtPath);sw.Close();}}/// /// 删除一个下载文件/// /// 文件名称/// 文件保存路径/// 文件下载路径
    public void DeleteDownFile(string fileName, string fileSavePath, string fileDownPath){try{string downFile = fileName + ";" + fileSavePath + ";" + fileDownPath;//将除了要删除的下载文件外的所有下载文件取出
            ArrayList list = new ArrayList();using (StreamReader sr = new StreamReader(txtPath)){String line;while ((line = sr.ReadLine()) != null){if (line == downFile)continue;list.Add(line);}sr.Close();}//重写下载文件
            using (StreamWriter sw = new StreamWriter(txtPath)){for (int i = 0; i < list.Count; i++)sw.WriteLine(list[i].ToString());sw.Close();}}catch (System.Exception e){//记录异常日志
            Logger.LogError("WaitDownFileTxtManage", "DeleteDownFile", AppError.EROR, 0, e, "删除下载文件节点出错:" + e.ToString(), null);}}/// /// 更新下载文件状态/// /// 文件名称/// 文件保存路径/// 文件下载路径/// 旧状态/// 新状态
    public void UpdateDownFileStatus(string fileName, string fileSavePath, string fileDownPath, string oldStatus, string newStatus){try{string downFile = fileName + ";" + fileSavePath + ";" + fileDownPath + ";" + oldStatus;string newDownFile = fileName + ";" + fileSavePath + ";" + fileDownPath + ";" + newStatus;//将除了要删除的下载文件外的所有下载文件取出
            ArrayList list = new ArrayList();using (StreamReader sr = new StreamReader(txtPath)){String line;while ((line = sr.ReadLine()) != null){if (line == downFile)continue;list.Add(line);}}//重写下载文件
            using (StreamWriter sw = new StreamWriter(txtPath)){for (int i = 0; i < list.Count; i++)sw.WriteLine(list[i].ToString());sw.Close();}using (StreamWriter sw = File.AppendText(txtPath)){sw.WriteLine(newDownFile);sw.Close();}}catch (System.Exception e){//记录异常日志
            Logger.LogError("WaitDownFileTxtManage", "UpdateDownFileStatus", AppError.EROR, 0, e, "更新下载文件节点状态出错:" + e.ToString(), null);}}
}

 

通过以上几步便完成了一个简单的CDN视频文件内容分发网络。

大家在实现的时候还需要编写一个定时删除边缘服务器上过期文件的服务,该服务比较简单,这里便不做说明了。

希望我的文章对大家有帮助!

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12639172/viewspace-609329/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/12639172/viewspace-609329/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_840728.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

程序员应该访问的最佳网站中文版

原文链接 :https://github.com/tuteng/Best-websites-a-programmer-should-visit-zh/blob/master/README.md 一些对程序员有用的网站 在学习CS的时候有一些你必须知道的有用的站点来获取通知为了你的技术储备和学习新知识。这里是一个你应该访问的不是非常全面的一些站点的列表…

[SEO]让你的Asp.Net网站自动生成Sitemap——XmlSitemap

首先我要说明&#xff1a;Asp.Net内置的Sitemap与这里讲的Sitemap是完全不同的&#xff0c;Asp.Net中的Sitemap主要用于给用户导航&#xff0c;而这里说的Sitemap是用来给搜索引擎爬虫指路。还是直接来看看官方解释吧&#xff1a;什么是Sitemap&#xff1f;Sitemap 可方便管理员…

c# 模拟网站登陆

我们在写灌水机器人、抓资源机器人和Web网游辅助工具的时候第一步要实现的就是用户登录。那么怎么用C#来模拟一个用户的登录拉要实现用户的登录&#xff0c;那么首先就必须要了解一般网站中是怎么判断用户是否登录的。 HTTP协议是一个无连接的协议&#xff0c;也就是说这次对话…

Joomla 3.9.4 发布,免费建站系统

Joomla 3.9.4现已推出。这是针对3.x系列Joomla的安全修复程序版本&#xff0c;它解决了4个安全漏洞&#xff0c;包含28个错误修复和改进。 什么是3.9.4&#xff1f; Joomla 3.9.4包含4个安全漏洞修复程序以及一些错误和改进&#xff0c;包括&#xff1a; 安全问题已修复 高优先…

C# 代码生成器 网站架构设计

自己写的一个 web 版简易 C# Code Generator&#xff0c;可快速产生某个数据库中&#xff0c;所有表 Mapping 的 C# 3.0 类。可当作网站分层开发、表单大量传递用户输入值、在内存里持久化保存值之用&#xff0c;亦可当作 NHibernate 等 O/R Mapping 框架套用时的 C# 代码生成器…

网站秒杀那点破事(转)

2010年光荣的劳动者节日过后某上午&#xff0c;经过一番所谓的唇枪舌剑、唾沫星子狂喷之后&#xff0c;宣布&#xff0c;此次活动相当的烂&#xff0c;一干策划、设计、推广在会议上低下高贵的头&#xff0c;咱&#xff0c;技术部 &#xff0c;某小B就开始了反省了——多好的员…

ASP.NET WebForm开发WAP网站 (转)

随着手机上网的兴起&#xff0c;我们实际项目中可能会遇到专门针对手机开发的网站&#xff0c;虽然ASP.NET 也有专门的WAP控件库&#xff0c;但在某些时候&#xff0c;这也不是完美的解决方案。ASP.NET WebFrom具有高效开发网站的优势&#xff0c;但对于手机上网来说&#xff0…

iis 7根据pid查看对应的网站 对应的应用网站程序池

原文&#xff1a;https://www.cnblogs.com/yzb-bky/p/6408795.html 哎 今天一登服务器&#xff0c;看见cpu100%头疼。。 一看 居然还有个网站占了 2 30%的cpu 很奇怪。于是想查到底是哪个网站&#xff0c;找了一会资料&#xff0c;记录下来 最终找到是某个后台导致的&#…

网站架构模式:前后端分离与前后端不分离

前后端不分离 在前后端不分离的应用模式中&#xff0c;前端页面看到的效果都是由后端控制&#xff0c;由后端渲染页面或重定向&#xff0c;也就是后端需要控制前端的展示&#xff0c;前端与后端的耦合度很高。 这种模式比较适合纯网页应用&#xff0c;但是当后端对接App时&am…

.net 网站 播放flv格式视频

将返回的字符串打印在页面。 /// <summary>/// 适用flv文件/// </summary>/// <param name"videoUrl">视频url</param>/// <param name"height">播放器高度</param>/// <param name"width">播放器宽度…

php支付宝手机网站支付功能,Laravel5.5 支付宝手机网站支付的教程

1、安装使用Laravel扩展库yansongda/laravel-pay通过composer进行安装$ composer require yansongda/laravel-pay生成配置文件$ php artisan vendor:publish --provider"Yansongda\\LaravelPay\\PayServiceProvider" --taglaravel-pay2、配置支付信息&#xff0c;填写…

如何下载bilibili类似网站里面的视屏,之后转音频

现在想要免费完整听一首自己喜欢的歌实属不易&#xff0c;以下就是我们这些穷b党层层破关的步骤&#xff01;要是有帮助的话&#xff0c;还望大侠记得双击&#xff0c;么么哒&#xff01; 1 首先到达你所要下载视屏的网页&#xff0c;复制该网站的url 2 登录解析第一大网硕鼠网…

python网站开发实例 flask_【9】Python接口开发:flask Demo实例

举例1&#xff0c;返回当前时间接口 初始化&#xff1a;所有的Flask都必须创建程序实例&#xff0c; web服务器使用wsgi协议&#xff0c;把客户端所有的请求都转发给这个程序实例 程序实例是Flask的对象&#xff0c;一般情况下用如下方法实例化 Flask类只有一个必须指定的参数&…

seo按天扣费系统_企业为什么要做SEO优化?杭州志卓云搜宝为您解答!

信息化时代&#xff0c;企业要想持续稳定发展&#xff0c;自身实力固然重要&#xff0c;不过企业对外形象的展示作用也不容小觑。企业网站作为门面担当&#xff0c;好的网站会获得更多的展现机会&#xff0c;吸引更多的目标客户点击访问&#xff0c;从而达到品牌建设及流量变现…

Linux运行脚本忽略警告,Linux用shell脚本监控网站运行状态并发告警邮件

#!/bin/bash#DATEdate "%Y.%m.%d-%H:%M:%S"ACCESS_DIR/root/curl/accessERRO_DIR/root/curl/erroSUCCESS_DIR/root/curl/successFILEdate "%Y.%m.%d-%H"WRONG(){cat $ERRO_DIR/$FILE | awk -F {print $2$3"\n"}#有错误状态码的域名}CURL(){for…

java linux 操作_新I/O(nio) - Java I/O操作入门教程_Linux编程_Linux公社-Linux系统门户网站...

JDK1.4开始&#xff0c;加入了Java.nio.*包&#xff0c;在这个包中加入了新的JAVA I/O类库&#xff0c;以便加快I/O操作的速度。在nio中读写之所以提高&#xff0c;只要是采用了更接近操作系统执行I/O操作的结构——通道和缓冲区。在《Thinking in Java》中有举了一个例子来说明…

使用Teleport Ultra批量克隆网站,使用Easy CHM合并生成chm文件

1.要下载的页面 http://www.howsoftworks.net/javaapi/ 2. 下载Teleport Ultra 3.使用Teleport Ultra批量克隆网站4.下载Easy CHM 5.使用Easy CHM合并生成chm文件

大型网站技术架构:摘要与读书笔记

转载 http://www.cnblogs.com/xybaby/目录 一个网站的进化史 初始阶段的网站架构应用服务和数据服务分离使用缓存改善网站性能使用应用服务器集群改善网站的并发处理能力数据库读写分离使用反向代理和CDN 加速网站晌应使用分布式文件系统和分布式数据库系统使用NoSQL 和搜索…

加速下载必知必会-国内的镜像网站备忘

1 国内的知名镜像网站备忘 大的综合镜像站仓库&#xff0c;为各中需求&#xff0c;包括下载软件、jar包、依赖等都提供了特别多的方便&#xff0c;下面是个人收藏的一些镜像站&#xff1a; #### 1 ali云 https://developer.aliyun.com/mirror/ #### 2 清华大学开源镜像站 htt…

跟随阿里架构师的脚步,探析阿里大型网站架构设计模式

设计和规划一个网站的总体架构涉及方方面面的东西&#xff0c;备选的方案也很多&#xff0c;如何在五花八门&#xff0c;纷繁复杂的技术中构建最适合用户的网站架构&#xff0c;变成了一件极具争议和挑战性的工作。一个好的架构可以以最低的成本&#xff0c;在满足用户需求的同…