大型网站技术架构解析:高性能服务器与数据库的关键作用

一个小型网站,比如个人网站,可以使用最简单的HTML静态页面来实现,配合一些图片来达到美化的效果。所有页面都存储在一个目录中。这样的网站对系统架构和性能的要求非常高。简单来说,随着互联网业务的不断丰富,网站相关技术经过这些年的发展已经细分为非常精细的方面。尤其是大型网站,所使用的技术涵盖的领域非常广泛,从硬件到软件、编程语言、数据库、Web服务器、防火墙等等,要求非常高,已经不是原来简单的HTML静态网站可以比拟的了。

大型网站技术架构解析:高性能服务器与数据库的关键作用

大型网站,例如门户网站。面对大量用户访问和高并发请求,基本解决方案集中在以下几个环节:使用高性能服务器、高性能数据库、高效编程语言、高性能Web容器。但除了这些方面之外,大型网站面临的高负载、高并发问题并没有根本的解决办法。

上面提供的几种解决思路在一定程度上也意味着较大的投入,而且这样的解决思路存在瓶颈,不具备良好的扩展性。我从低成本、高性能、高扩展性的角度来谈谈。说说我的一些经历吧。

1. HTML 静态

其实大家都知道效率最高、消耗最少的就是纯静态的HTML页面,所以我们网站的页面尽量使用静态页面。这个最简单的方法实际上也是最有效的方法。但是对于内容量大、更新频繁的网站,我们无法一一手动实现,于是我们常见的信息发布系统CMS就出现了,比如我们经常访问的各种门户网站的新闻频道,甚至是他们的其他频道。渠道,都是通过信息发布系统来管理和实施的。信息发布系统可以实现最简单的信息录入,自动生成静态页面。它还可以具有频道管理、权限管理、自动抓取等功能。对于一个大型网站来说,拥有一个高效、可管理的CMS是必不可少的。

除了门户网站和信息发布网站之外,对于交互性要求较高的社区型网站,尽可能使其静态化也是提高性能的必要手段。社区中的帖子和文章可以实时静态化,更新后的重新静态化也是一种广泛使用的策略。猫扑的大杂烩就采用了这种策略,网易社区也是如此。

同时,HTML静态化也是一些缓存策略使用的手段。对于系统中经常使用数据库查询但内容更新很少的应用,可以考虑使用HTML静态化来实现,例如论坛的公共设置信息。这些信息目前所有主流论坛都可以在后台管理并存储在数据库中。事实上,这些信息大量被前端程序调用,但更新频率却很小。后台更新的时候可以考虑将这部分内容静态化,避免大量数据库。访问请求。

2、图像服务器分离

众所周知,对于Web服务器来说,无论是Apache、IIS还是其他容器,图片消耗的资源最多,所以我们有必要将图片与页面分离。这是大型网站基本采用的策略。它们都有独立的图像服务器,甚至多个图像服务器。这样的架构可以减轻提供页面访问请求的服务器系统的压力,并且可以保证系统不会因为图片问题而崩溃。应用服务器和图片服务器可以进行不同的配置优化。例如apache在配置ContentType时可以尽力而为。尽可能少的支持,使用尽可能少的LoadModule,以保证更高的系统消耗和执行效率。

3. 数据库集群和数据库表哈希

大型网站有复杂的应用程序,而这些应用程序必须使用数据库。当面对大量的访问时,数据库的瓶颈很快就会出现。这个时候数据库很快就无法满足应用了,所以我们需要使用数据库。簇或库表哈希。

在数据库集群方面,很多数据库都有自己的解决方案。 Oracle、Sybase等都有很好的解决方案。 MySQL提供的常用的Master/Slave也是类似的解决方案。您使用什么样的DB,请参考相应的解决方案即可实现。

前面提到的数据库集群在架构、成本、可扩展性等方面都受到所使用的DB类型的限制,所以我们需要从应用的角度考虑改进系统架构。库表散列是一种常用且最有效的解决方案。 。我们在应用中安装业务和应用或者功能模块来将数据库分开。不同的模块对应不同的数据库或者表,然后使用一定的策略对某个页面或者功能进行更小的数据库哈希,比如用户表。根据用户ID对表进行哈希,可以以较低的成本提高系统的性能,并且具有良好的扩展性。搜狐的论坛就采用了这样的结构,将论坛的用户、设置、帖子等信息分离到一个数据库中,然后根据版块和ID对数据库以及帖子和用户的表进行哈希处理。最后在配置文件中简单配置即可。这使得系统可以随时添加低成本的数据库来补充系统性能。

4、缓存

任何从事技术工作的人都遇到过缓存这个术语,并且缓存用在很多地方。缓存在网站架构和网站开发中也非常重要。这里我们先说两个最基本的缓存。高级缓存和分布式缓存将在后面介绍。

在架构缓存方面,熟悉Apache的人都会知道,Apache提供了自己的缓存模块,你也可以使用额外的Squid模块进行缓存。这两种方法都可以有效提高Apache的访问响应能力。

对于网站程序开发中的缓存,Linux上提供的Memory Cache是​​一个常用的缓存接口,可以在Web开发中使用。例如,在Java开发时,可以调用MemoryCache来缓存一些数据并进行通信。它被一些大型社区使用。这样的结构。另外,在使用Web语言开发时,每种语言基本上都有自己的缓存模块和方法。 PHP 有 Pear 的缓存模块,而 Java 则更多。我对.net不是很熟悉,但我相信它一定在那里。

5.镜子

镜像是大型网站经常使用的一种方法,用于提高性能和数据安全性。镜像技术可以解决不同网络接入提供商和地区造成的用户访问速度的差异。例如,ChinaNet和EduNet之间的差异,促使许多网站在教育网中建立镜像站点,并定期或实时更新数据。至于镜像的详细技术,这里就不做过多的赘述了。有许多专业的现成解决方案架构和产品可供选择。还有一些廉价的方法可以通过软件来实现它,例如 Linux 上的 rsync 和其他工具。

6.负载均衡

负载均衡将是大型网站解决高负载访问和大量并发请求的最终解决方案。

负载均衡技术已经发展多年,有很多专业的服务商和产品可供选择。我个人遇到过一些解决方案,其中两个可以作为参考。

1)硬件四层交换

四层交换利用三层、四层信息报文的头信息,根据应用区间来识别业务流,并将整个区间段的业务流分配给合适的应用服务器进行处理。四层交换功能就像一个虚拟IP,指向物理服务器。它传输的服务遵循多种协议,包括HTTP、FTP、NFS、Telnet或其他协议。这些服务需要基于物理服务器的复杂负载均衡算法。在IP世界中,服务类型由终端TCP或UDP端口地址决定。在四层交换中,应用范围由源端和终端IP地址、TCP和UDP端口决定。

在硬件四层交换产品领域,有一些知名的产品可供选择,比如Alteon、F5等,这些产品价格昂贵,但物有所值,可以提供非常优异的性能和非常灵活的管理能力。雅虎中国使用三到四台Alteons来处理近2000台服务器。

2)软件四层交换

在大家了解了硬件四层交换机的原理之后,基于OSI模型的软件四层交换机就出现了。此类解决方案实现了相同的原理,但性能稍差。不过,遇到一定的压力还是很容易的。有人说软件实现方式其实更灵活,处理能力完全取决于你配置的熟悉程度。

我们可以使用Linux上常用的LVS来解决软件的四层切换。 LVS 是 Linux 虚拟服务器。提供基于心跳线的实时灾难响应解决方案,提高系统的健壮性,并提供灵活的虚拟VIP。配置和管理功能可以同时满足多种应用需求,这对于分布式系统至关重要。

典型的负载均衡策略是基于软件或硬件四层交换构建Squid集群。这个想法被很多大型网站所采用,包括搜索引擎。这种架构低成本、高性能、功能强大。可扩展性,随时向架构添加或删除节点非常容易。我将详细整理一下这个结构并与大家讨论。

1:专注于高并发、高负载网站的数据库

没错,首先是数据库,这是大多数应用程序面临的第一个SPOF。特别是对于Web2.0应用,首先必须解决数据库的响应。

一般来说,MySQL是最常用的,最初可能是mysql主机。当数据增加到超过100万条时,那么MySQL的性能急剧下降。常见的优化措施是采用MS(主从)模式进行同步复制,即查询和操作在不同的服务器上进行。我推荐的是MM-Slaves方式,2个master Mysql,多个Slave。需要注意的是,虽然有 2 位 Master,但同时只有一位处于 Active 状态。我们可以在某个时间切换。之所以使用两个M,是为了保证M不会再次成为系统的SPOF。

从站可以进一步进行负载平衡,并且可以与 LVS 结合以适当平衡不同从站的选择操作。

上面的架构可以应对一定的负载,但是随着用户数进一步增加,你的用户表数据超过1000万,然后M就变成了SPOF。不能随意扩充Slave,否则复制同步的成本会暴涨。我应该怎么办?我的方法是表分区,从业务层面分区。最简单,以用户数据为例。根据一定的分割方法,如ID,分割成不同的数据库集群。

全局数据库用于元数据查询。缺点是每次查询都会添加一次。比如要查询一个用户nightsailer,首先要到全局数据库组中找到nightsailer对应的集群id,然后再到指定的集群中找到nightsailer的实际数据。

每个集群可以使用 mm 模式或 mm-slaves 模式。这是一个可扩展的结构。随着负载的增加,您可以简单地添加新的 mysql 集群。

需要注意的事项是:

1.禁用所有auto_increment字段

2、需要采用通用算法集中分配ID。

3.需要有更好的方法来监控mysql主机的负载和服务的运行状态。如果你运行着超过30个mysql数据库,你就会明白我的意思。

4. 不要使用持久链接(不要使用pconnect)。而是使用sqlrelay等第三方数据库连接池,或者干脆自己动手,因为php4中的mysql连接池经常出现问题。

2:高并发高负载网站系统架构的HTML静态化

其实大家都知道效率最高、消耗最少的就是纯静态的HTML页面,所以我们网站的页面尽量使用静态页面。这个最简单的方法实际上也是最有效的方法。但是对于内容量大、更新频繁的网站,我们无法一一手动实现,于是我们常见的信息发布系统CMS就出现了,比如我们经常访问的各种门户网站的新闻频道,甚至是他们的其他频道。渠道,都是通过信息发布系统来管理和实施的。信息发布系统可以实现最简单的信息录入,自动生成静态页面。它还可以具有频道管理、权限管理、自动抓取等功能。对于一个大型网站来说,拥有一个高效、可管理的CMS是必不可少的。

除了门户网站和信息发布网站之外,对于交互性要求较高的社区型网站,尽可能使其静态化也是提高性能的必要手段。社区中的帖子和文章可以实时静态化,更新后的重新静态化也是一种广泛使用的策略。猫扑的大杂烩就采用了这种策略,网易社区也是如此。

同时,HTML静态化也是一些缓存策略使用的手段。对于系统中经常使用数据库查询但内容更新很少的应用,可以考虑使用HTML静态化来实现,例如论坛的公共设置信息。这些信息目前所有主流论坛都可以在后台管理并存储在数据库中。事实上,这些信息大量被前端程序调用,但更新频率却很小。后台更新的时候可以考虑将这部分内容静态化,避免大量数据库。访问请求是高度并发的。

网站HTML静态解决方案

当Servlet资源请求到达WEB服务器时,我们会填写指定的JSP页面来响应请求:

HTTP请求---Web服务器---Servlet--业务逻辑处理--访问数据--填写JSP--响应请求

HTML 静态化后:

HTTP请求---Web服务器---Servlet--HTML--响应请求

静态访问请求如下

小服务程序:

public void doGet(HttpServletRequest 请求,HttpServletResponse 响应)

抛出 ServletException、IOException {

if(request.getParameter("chapterId") != null){

String ChapterFileName = "bookChapterRead_"+request.getParameter("chapterId")+".html";

String ChapterFilePath = getServletContext().getRealPath("/") + ChapterFileName;

文件chapterFile = new File(chapterFilePath);

if(chapterFile.exists()){response.sendRedirect(chapterFileName);return;}//如果有这个文件,告诉浏览器重定向

INovelChapterBiz novelChapterBiz = new NovelChapterBizImpl();

NovelChapter novelChapter = novelChapterBiz.searchNovelChapterById(Integer.parseInt(request.getParameter("chapterId")));//章节信息

int lastPageId = novelChapterBiz.searchLastCHapterId(novelChapter.getNovelId().getId(), novelChapter.getId());

int nextPageId = novelChapterBiz.searchNextChapterId(novelChapter.getNovelId().getId(), novelChapter.getId());

request.setAttribute("novelChapter", novelChapter);

request.setAttribute("lastPageId",lastPageId);

request.setAttribute("nextPageId", nextPageId);

new CreateStaticHTMLPage().createStaticHTMLPage(请求, 响应, getServletContext(),

ChapterFileName,chapterFilePath,“/bookRead.jsp”);

生成HTML静态页面的类:

包 com.jb.y2t034.thefifth.web.servlet;

导入 java.io.ByteArrayOutputStream;

导入 java.io.FileOutputStream;

导入java.io.IOException;

导入 java.io.OutputStreamWriter;

导入 java.io.PrintWriter;

导入 javax.servlet.RequestDispatcher;

导入 javax.servlet.ServletContext;

导入 javax.servlet.ServletException;

导入 javax.servlet.ServletOutputStream;

导入 javax.servlet.http.HttpServletRequest;

导入 javax.servlet.http.HttpServletResponse;

导入 javax.servlet.http.HttpServletResponseWrapper;

/**

* 创建HTML静态页面

* 功能:创建HTML静态页面

* 时间:2009年1011

*地点:家里

* @作者马夫克

*/

公共类 CreateStaticHTMLPage {

/**

* 生成静态HTML页面的方法

* @param request 请求对象

* @paramresponse响应对象

* @param servletContext Servlet 上下文

* @param fileName 文件名

* @param fileFullPath 文件完整路径

* @param jspPath 需要生成静态文件的JSP路径(相对即可)

* @抛出IOException

* @抛出ServletException

*/

公共无效createStaticHTMLPage(HttpServletRequest请求,HttpServletResponse响应,ServletContext servletContext,字符串文件名,字符串文件FullPath,字符串jspPath)抛出ServletException,IOException{

response.setContentType("text/html;charset=gb2312");//设置HTML结果流编码(即HTML文件编码)

RequestDispatcher rd = servletContext.getRequestDispatcher(jspPath);//获取JSP资源

最终 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); //用于从ServletOutputStream接收资源

Final ServletOutputStream servletOuputStream = new ServletOutputStream(){//用于从HttpServletResponse接收资源

公共无效写入(字节[] b,int off,int len){

byteArrayOutputStream.write(b, off, len);

公共无效写入(int b){

byteArrayOutputStream.write(b);

};

Final PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream));//将字节流转换为字符流

HttpServletResponse httpServletResponse = new HttpServletResponseWrapper(response){//用于从response中获取结果流资源(重写了两个方法)

公共 ServletOutputStream getOutputStream(){

返回servlet输出流;

公共 PrintWriter getWriter(){

返回打印作家;

};

rd.include(request, httpServletResponse);//发送结果流

printWriter.flush();//刷新缓冲区并输出缓冲区中的数据

FileOutputStream fileOutputStream = new FileOutputStream(fileFullPath);

byteArrayOutputStream.writeTo(fileOutputStream);//将byteArrayOuputStream中的所有资源写入fileOuputStream

fileOutputStream.close();//关闭输出流并释放相关资源

response.sendRedirect(fileName);//发送指定文件流到客户端

三:缓存、负载均衡、存储是高并发、高负载网站所关心的问题。

缓存是另一个大问题。我通常使用memcached作为缓存集群。一般来说,部署10个左右(10g内存池)就够了。要注意一件事,切勿使用

swap,最好关闭Linux的swap。

负载平衡/加速

可能上面提到缓存,有些人首先想到的就是页面静态化,即所谓的静态html。我认为这是常识,并不是重点。页面静态化带来静态服务

负载平衡和加速。我认为Lighttped+Squid是最好的方式。

你可能想看:
« 上一篇
下一篇 »

相关推荐

java中什么是冒泡,冒泡算法

2026年09月06日

30阅读

java中冒号,java双冒号

2026年09月06日

28阅读

java中的->,java中的是什么意思

2026年09月06日

28阅读

java中的super用法,Java中super的说明

2026年09月06日

29阅读

java中反射的应用,java中反射的应用场景

2026年09月06日

27阅读

java中开关的定义,Java关键字有哪些

2026年09月06日

29阅读