分享

【图文并茂】一步步带你了解Web站点架构

 jfsir 2016-06-25

1.1 http反向代理服务器

在web站点前端,我们需要搭建一个反向代理服务器,用于负责接受用户的请求,请求包括动态和静态的内容请求。一般反向代理服务器的部署方案有HAProxy和Nginx,这里将使用HAProxy来描述。


1.2 http代理服务器高可用

为了提高系统安全及高可用性,我们需要在前端的http反向代理服务器配置高可用,解决方案有HAProxy+Keepalived。


1.3 http代理服务器负载均衡

虽然我们有两个节点的HAProxy,但是一般只有有一台HAProxy可为用户提供服务,而另外一台将会空闲,这样会造成资源浪费,为了提高资源最大化,我们需要为HAProxy做负载均衡。操作方法就是在DNS上配置两条A记录,这样就能实现将用户请求通过DNS分发给两个不同的节点,而每个节点都通过相同的方式向后端服务器发起调度。


1.4 动态内容服务器

如果我们打算部署一个动态内容,而且主站也是使用应用程序来实现,那我们需要部署一套动态内容网站(例如LAMP),那么对其我们也需要对其考虑高可用性以及负载均衡以及高可用的问题。那么当用户访问主页,例如index.jsp,index.php等动态网页时,此时就应该由动态服务器基于响应。


小知识:用户在访问站点时,只是请求一个资源(主页资源),而这个主页资源包含了很多资源,有大多数都是静态内容,这些内容都是位于当前站点上或者是其他站点上一些静态资源,比如图片,CSS等。而这些信息需要被单独的资源再次请求。所以打开一个站点,访问主页的那一刻,只是第一次请求的入口,后续他会在同一个站点或者是同一个站点的链接所指向的位置发起多次请求。

1.5 数据库节点服务器

对于动态内容来讲,如果其访问的是一个主页,而这个主页又包含一些动态内容,比如包含某些查询,那么此时就需要查询数据库,所以我们还需要部署数据库节点(常见的数据库系统有MySQL、Mariadb、Oracle等)


备注说明:

对于一个站点来讲将,存储有分为以下几类

  • 1、关系型数据,需要存储在类似MySQL这种关系型数据库中

  • 2、文件数据,存储在文件系统中

  • 3、键值数据,一般存储在缓存服务器中,或者类似NoSQL非关系型数据库中

1.6 MySQL主从架构

如果我们查询的请求比较多,一台MySQL服务器将无法支撑这么庞大的查询请求,那么此时为提高查询能力,我们需要部署主从架构,实现一主多从模型


1.7 缓存服务器

我们了解到MySQL本身具有缓存功能,但由于前端应用服务器不止一台,而MySQL也已部署成为一主多从架构,因为存在多个MySQL从节点,从而导致前端应用程序无法命中MySQL缓存的问题,那么此时就需要增加缓存服务器(例如:Memcache服务器)
如果我们只有一台MySQL读节点,那么只需使用MySQL本地的缓存即可,而无需额外增加缓存服务器。


使用MySQL主从架构添加缓存时,使用的是缓存模式中的“旁路”缓存模式(下面有介绍缓存的工作模式),而在此处缓存的内容主要是缓存MySQL的查询对象,也就是MySQL对象查询的缓存结果。

1.8 关于缓存工作模式介绍

缓存工作模式有两种

  • 1、基于代理模式的工作

  • 2、基于旁路的工作模式

1.8.1 代理(例如HAProxy,Nginx)


用户向缓存服务器请求资源,如果缓存服务器发现本地并没有对应缓存记录,会由自己向后端服务器请求资源,将请求到的结果先缓存在本地,缓存完成之后再响应给用户。

1.8.2 旁路(例如Memcache)


用户首先向缓存服务器请求,如果缓存服务器未有缓存记录会立即响应用户。这时客户端会自行去找后端服务器,那么后端服务器无论有无资源都会响应给客户端。假设此时有对应缓存记录,那么后端服务器会将结果返回给客户端。客户端会根据需要来判定是否这个数据缓存到缓存服务器中。所以数据缓不缓存并不取决于缓存服务器,而取决于请求方(也就是客户端)

1.9 MySQL主从架构读写分离

由于MySQL已经部署成为主从架构,那么又衍生另一个问题,如果用户请求发送到MySQL服务器,应如何区分读和写的请求,应使用哪个节点去响应客户端请求呢?此时我们需要解决读写分离的问题。这里给出两种方法供大家参考:

  • 1、前端应用程序配置

在前端应用程序做设定来做读写分离,设定写操作发送到主节点,读操作发至各从节点上。但是这样会存在一个问题,如今互联网发展速度之快,我们很有可能为了满足业务扩展需求,会改变架构规划调整,此时就需要在前端应用程序端进行代码修改,而且这样要求前端应用程序开发工程师的技术水平,对于系统的扩展性不高,所以一般也不建议使用这样地方。

  • 2、搭建读写分离服务器(例如:Amoeba服务器)

搭建读写分离服务器,告诉前端应用程序,无论是读请求还是写请求都发至读写分离服务器,由此服务器负责代理区分读写操并做好读写分离,转发至各对应的主从节点上。


1.10 对存在多个从节点缓存情况

如果架构中存在多个从节点(读节点),我们需要做好读节点的负载均衡。虽然多从节点能分摊读操作压力,但同时也降低了缓存命中的几率,我们前面说明MySQL的前端Memcache是使用旁路的工作模式进行缓存的,虽可以做到部分缓存,但是当Memcache没有对应缓存条目的时候,应用程序会向后端的MySQL查询,MySQL自身也有缓存功能,但是由于存在对个从节点,而每个从节点之间做了负载均衡,所以应用程序可能查询同一条数据的时候无法定位到同一个MySQL从节点,这样就很难缓存命中,从而造成MySQL从节点的资源浪费,为了提高MySQL本地缓存可以得到有力的应用,进一步提到缓存的命中,那么一般有下面两种的模式

  • 1、简单的取模方式

前端应用在向后端发起数据请求时,某个语句如果发往同一个节点,那么他就始终发往同一个节点。所以可以根据语句做均衡,以后只要是这个语句,就会发送到这个节点上(做法:使用取语法就行了,每个语句在在向后段发起请求时。只需要在应用程序中,对这个查询语句做hash计算,取得他的校验码,对服务器的个数做取模计算。所以某语句特征码一样,那么他的取模计算也是一样的。因此同一条语句将会始终发往同一个服务器。)

这种方案存在问题:万一某个节点挂了,那么你剩下的将会需要重新取模,那么程序可能被调整。而且有可能导致之前的缓存全部失效了。所以这种方案并不理想

  • 2、一致性hash

这种算法很独特,他不是对服务器节点数取模,而是把服务器每个节点都计算hash类似,对2^32取模,把每个服务器节点顺时针分布在一个虚拟环上。然后当客户端请求数据的时候,就会根据顺时针的来去查找节点,如果真的有一个节点挂了,也只是影响那段区域的缓存数据。


但是这个有可能导致不均衡,但是这个是在所难免的。但是我们可以使用虚拟节点机制,这样节点就能分布到不同区域下,每个虚拟节点都是单独计算的,所以他们落的地方就不同,这样就容易均衡。


当做好MySQL从节点之间的缓存取模配对,当用户请求时会先去查询Memcache中的缓存,有缓存命中则会立即返回,如果未命中,客户端会向后端从节点发起查询请求,此时从节点会查询自身本地的缓存记录,如有有命中,将记录返回给客户端,若没有命中缓存,则会查看查询数据库表中的数据信息。

1.11 主节点单点瓶颈

在主从模型中,写节点成为了整个架构单点故障所在,那么我们需要做到MySQL的部署成双主模型,来实现主节点的高可用。这种解决方案有: MySQL+Proxy,MySQL-MMM, DRBD等技术,建议使用MySQL-MMM技术。


额外说明:除了上面介绍的方法,我们还可以有一个思路,就是做双写模型,就是在应用程序层面做设置,当收到写操作时,将写操作在两个主节点都写一份,而其他从节点只需要同步其中一台主节点,当一个主节点故障后,立即将从节点同步到新的主节点上完成同步即可,但是这些设置都必须在前端应用程序层面上做操作,道理和上面介绍的一样,这种方式对于以后系统架构扩展性不高,不建议使用这样的方法,所以这里仅仅是给一个思路。

1.12 上传文件存储

在应用程序当中,我们需要存储的可能不单单是结构化数据(也就是MySQL数据)。例如用户通过应用程序上传数据,而这些数据应该存储在文件系统中,能够提供文件系统的有类似NAS设备,如果用户需要上传数据,这个上传请求就会给予http请求中的put方法上传的数据保存在文件系统中,通过应用程序向文件系统发起数据请求,通过调用文件服务的API接口(或服务)来完成存储。


1.13 用户的读请求

如果用户的操作是读请求的话,此时我们应该做到动态与静态服务器的分离,通过HAProxy来完成动静分离,此前我们已经有动态应用服务器,那么此处我们需要构建静态服务器(一般会使用Nginx来构建静态服务器)并且我们需要对静态服务器配置高可用,那么可用的方案有 Nginx + Keepalived。使用HAProxy来完成动态内容和静态内容分离,通过静态内容服务器所请求的内容一般都是文件系统里的内容,静态内容服务器会向后端的文件系统拿到用户请求的内容后,会构建成http响应报文,然后响应给HAProxy,然后HAProxy再次构建响应报文发回给用户


1.14 静态内容缓存

考虑到文件检索的速率,那么对于静态服内容也需要构建缓存,虽然我们可以使用动态部分的Memcache缓存服务器的,但是对于文件静态内容缓存,使用Varnish或Squid相比之下更有优势,其中Varnish可以直接响应HAProxy请求,当Varnish没有数据时,会去赵Nginx,Nginx会从后端检索数据,然后返回给Varnish,Varnish会将检索到的数据缓存下来,然后在响应给HAProxy,最后构建http响应报文返回给客户端。当然,Nginx本身也存在本地缓存功能,所以可以开启Nginx本地的缓存功能,所以如果Varnish向Nginx发来请求时,Nginx会先查询Nginx本地自己的缓存,如果命中将直接返回给Varnish,否者会向后端服务器检索数据。

1.15 CDN技术

对于中型的web站点,上面架构还是足以应付业务的需要,但是如果对于类似淘宝,京东等这一类大型的网购站点还不不够,而且还需要注意,对于一些网购站点,访问高峰时间段,甚至出现抢购这类活动,业务流量将成数倍的增长,所以现在的架构是无法满足需要,考虑到这些大型的web站点,我们需要借助于CDN机制,CDN(Content Delivery Network)内容分发网络,简单理解是各地搭建缓存服务器,将这些缓存服务器分布到用户访问相对密集的区域或网络中,利用全局负载均衡技术(GSLB),将用户访问的距离指向最近的缓存服务器中,然后由缓存服务器直接响应用户请求,而且各地缓存服务器还能之间相互进行查找,直到CDN的缓存服务器上都没有记录,那么就会向web站点主服务器去查询资源,我们知道热点的关系,其实用户访问的将近20%数据(估测)都是经常被访问的数据,所以使用CDN技术能大大的降低主服务器的查询请求,而且加快用户的访问速度已经用户体验,在选择CDN方面,我们应该选择至少2个以上的CDN服务提供商,目的也是为了提供线路的可用性。


1.16 监控系统、自动化运维、备份等工具

虽然我们为每个节点都部署高可用,但是随着业务的不断增长,传统型的服务器运维工作已经无法适应业务需求。为了提高业务的稳定性、运维人员工作效率等,我们还需要在部署监控系统、自动化运维工作、备份等工具
① 监控系统

在各节点中部署监控客户端,监控各节点的性能指标、服务状态、硬件状态,实时的将监控数据发送到监控服务器端,若出现数据异常或者节点故障,监控服务器会立即通知运维人员,这样就能在业务未中断的条件下预先知道业务中存在威胁,从而立即响应处理故障,保证业务正常稳定的运行。
常用的监控系统开源解决方案:Nagios、Zabbix

②    自动化运维工具

随着业务不断增长,所需的服务器节点设备不断增多,运维人员不可能在一步步重新部署操作系统。而且当业务需要发布更新,我们需要将所有的更新脚本文件分发至各对应节点,并同步执行更新,而这些操作简单却繁琐,仅仅重复相同操作。类似这种情况,我们需要部署自动化运维工具,将这些操作通过自动化运维工具部署完成,从而增加运维人员的工作效率。
常见的自动化运维工具开源解决方案:Ansible、Puppet、Cobbler

③    备份工具

数据对于企业而言是十分重要,虽然现在存储技术可以使用RAID技术来保障数据的安全性,由于可能不可控因素,或者是系统出现操作失误或系统故障导致数据丢失,将有可能导致不可预估的损失。而这就是备份的重要性,所以保证数据的安全性,也防范于未然。
常见的备份工具开源解决方案:Bacula


1.17 总结

本文主要介绍了从一个基本的Web站点部署所需组件,到根据业务需要一步步不断的扩展完善整个Web站点的架构,这篇文章在学习中总结汇总,由于本人能力有限,其中有些地方写的不足还有待完善,如果您有好的建议,欢迎您的指教。谢谢。



原创作者看过来:马哥Linux原创作品征集

如果你有好的原创文章
如果你想增加自己的影响力
如果你想造福更多的小伙伴
那就给马哥Linux运维公众号投稿吧!

你的运维经验、运维感悟、运维心得、运维策略、运维技能、运维遇到的坑、学习心得等等,都可以给我们投稿!

一经采用,除了特别的奖励外,还能增加自己的知名度哦~快来投稿吧!

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多