先前将7层的反代程序nginx,此类的应用程序还有haproxy
nginx,既能实现4层反向代理,也能实现7层反代,而且反代完以后,利用相应upstream模块还能完成负载均衡的功效
现在主要针对应用层反代,用nginx实现反代时用的proxy模块,proxy模块中有一个指令叫proxy_cache_path,
proxy_cache_path,指定路径,(几级路径,有多少个子目录,1,2,2,存的缓存有两部分,
一部分在内存里,是键,到磁盘里的hash运算表,一部分在磁盘上,磁盘上的数据是缓存里一一对应的内容)
对于缓存来讲的确可以减少整个服务过程中的环节,从而实现加速的功能
当一个客户端来访问你的web服务的时候,如果没有缓存,第一次到达反向代理服务器,反代服务器再次经过网络到达被代理服务器,这台主机要获取用户需要的内容,还需要看看是否是静态还是动态的,如果是静态内容,还需要经过磁盘IO,获取到
用户所请求的内容上,打包响应给代理主机,所以大体上会多出一个网络IO的过程,磁盘IO不可避免,这个网络IO可能消耗不少时间的,如果是获取动态内容,中间可能还需要一个执行过程,即便是不做反代,这个服务器要获取内容也需要执行,这一步是少不了的,对于后端服务器来讲,要做负载均衡,这种网络IO也是不可避免的,,执行过程要消耗一段时间也是无法避免的
有了缓存以后,这些过程可以被某种程度上省略的,如果是动态内容这个执行过程也是可以被省略的。所以是可以大大节约时间的
如果用户就是一个获取的请求方法,或者没有进行修改的话,用原来内容就可以,用这种缓存方式的确能提高用户对性能的感知
**之所以缓存能生效,主要取决于,程序的运行具有局部性特征
长期运行具有时间局部性:一个数据被访问之后,可能很快会被再次访问(这种逻辑,才使缓存有价值可依据)
**
空间局部性:一般一个数据被访问时,其周边的数据也有可能随后被访问到
就可以用到预加载的方式,把一个数据访问的时候,周边的数据也缓存到内存中,随后就可以进行访问了
为何要使用缓存,如果中间环节过多的时候,势必每个环节都会降低性能,影响用户感知,所以把那些用户所需要的内容送到用户最近的地方,带来的性能提升是很明显的
这里使用的缓存不仅是我们反向代理服务器上所使用的缓存(缓存服务器缓存,public cache),事实上每个浏览器都有缓存(用户私有缓存private cache)
缓存有多级,离用户越近越好
正是站点本身的局部性热区,所以才让缓存的局部性加强了
对于mysql来讲,要缓存是缓存的select语句的查询结果,这是数据流,而站点的缓存(更多的是图片,css文件,页面数据)
mysql和一些数据类的缓存 一般叫data ceche
而对于web站点来讲,缓存一般叫 page cache
缓存逻辑都是一样的
因为有热区的概念,所以一般缓存是不会缓存整个数据集的,大部分遵循2,8法则,百分之20数据,承载百分之80的访问,余下百分之80承载百分之20 的访问量,所以百分之20的数据缓存到系统中就好了,通常只是缓存热区数据
哪些数据是热区的,这个是无法判断的,所以缓存上线以后是不会立即生效的,不会立即到最佳工作模式的,需要大体上过一段时间以后,热区数据可以大多数缓存下来,缓存热身过程 warm up
但是这个过程太长,所以有些就用复制的先生流量对于缓存进行压测,压测不断交换数据,留下来的就是热区数据,这个热身过程,需要人工来实现的
对于某些应用程序的编译结果也可以进行缓存
比如php 有 opcode,一般两个之间速度跟不上的时候,都用缓存解决问题,缓存几乎无处不在
缓存数据应该是小于原数数据空间的
缓存打满了,需要清理,有个著名的算法就是LRU。最近最少使用
既然是缓存,那么这个数据也应该不会一直长期有效
原始数据可能也是会发生改变的,这时候原来的缓存就应该失效,不然缓存响应用户得到的不是最新数据
(对于mysql数据来讲,缓存是要及时更新)
但对于web站点,新的用css,我的方式来展示商品,只不过是换一种方式来展示商品,这个时候及时更新缓存,倒也不是很必要,可以允许慢一点‘
过期以后,有缓存清理逻辑来清理’
未命中缓存的原因有很多,
1.第一次访问,之前没有历史 (人工热身)
2.缓存存下来了,但是缓存时间很短,在下次访问以前,被过期清理掉了(增加缓存时长来解决问题,如果原始数据变化频率过大,通常缓存起到的加速效率是很低的)
3.缓存空间太小,大量缓存项,基于LRU算法被清理掉了,(就需要增加缓存空间)
所以一般给读多写少的情况加以缓存,如果缓存命中率过低的话,反而引入的是一个麻烦(先查缓存,缓存没命中,再去后面找,没少步骤,反而多了个步骤
如果缓存代价价值低于节约的时间,那么这个缓存就需要撤了)
命中率应该在0-1之间,多高为好,多高为差,并没有衡量标准
页面命中率(总共800个页面,缓存下来40个,这40个页面命中率非常高,百分之90,碰巧这些页面体积都很小,没命中的也经常被请求,但是体积都很大,这种状态下,带来的节约也是有限的)
基于页面大小来衡量,基于页面数量来衡量
几乎所有缓存都类似
缓存是有多级结构的,就跟反代一样,每一级反代都会开启缓存的
因此在服务器就要指明这是可以公共缓存的数据,还是只能私有缓存的数据
对于私有信息,带认证授权的,cookie,
除去这些一般都是公共数据,但是未必带有cookie的都是私有,登录以后,查看商品,商品的那些描述信息,就不是私有数据
对于缓存管理员,就要理解哪些是私有哪些是公有
对于web服务来讲,所有缓存都是一个代理
代理缓存(用户请求,缓存没有,缓存服务器要向服务器询问帮你把数据拿到,然后再发送给客户端)
还有一种缓存叫旁挂式(用户访问缓存,如果命中直接返回 ,没命中,客户端需要自己去找原始服务器,找到以后,要客户端自己决定,是否缓存进来,像这种缓存服务器,缓存数据自己不决定而是由客户端决定的)(web服务,http协议的所有缓存都是一个代理,可以是代理没有缓存,但是只要是缓存都是代理)
旁挂式对客户端的要求变高了(一般好 的产品都是让用户变成傻瓜了,客户端就会因为你难用而放弃,memacached,就是这样的缓存,纯粹的缓存服务器,不是代理)
vanish的缓存能力是nginx比不上的,但是并发量较弱,所以构建站点时,会把varnish和nginx联合起来使用
为什么不用squid(varnish和squid的关系就像是nginx和httpd的关系,一个是上一时代的产品,一个是当前时代的产品,充分利用了当前网络并发编程模型中的优势,比如EPOLL)
应该这么去组织我们web站点
用户请求首先到nginx反代,避免单点,所以用到keepalived做双主模型
向后端进行反代的时候不在直接是web服务器了而是多了个层次,缓存服务器
缓存项分割到多台服务器上,每一个缓存服务器只承载一部分缓存项
为了提高缓存命中率(url, 根据url来调度缓存),利用一致性哈希算法来提高缓存命中率,免得缓存服务器数量发生变动时导致全局失效
缓存服务器对静态内容可以缓存,对动态内容就需要三思,(哪些内容缓存,哪些内容不缓存)
加入动态内容都不缓存,那么定义nginx服务的location的时候静态内容(图片,css)都代理到缓存服务器上
或者可以直接定义哪些不能缓存的更为简单
对于动态内容来讲可以直接去找原始的主机,index.php
那就认为每个用户第一次访问请求都需要由原数服务器所承载,如果主页生成速度很慢的话,会导致用户体验很差的
所以就需要动态的内容静态化,index.html
一般网站都是动静分离,
css,js,都是放在动态的主页服务器上,而图片一般都放在图片服务器上,所以一把网站上的图片都是有单独域名的
大概十几台的架构,就可以承载差不多千万级的pv了
现在web2,。0,有些零碎数据放在关系型数据库里,效率是很低的,就需要用到非关系型数据库(比如redis,mongodb)
消息队列系统kafka,twitter内部,每天所承载的消息是万亿级别的采用kafka
小的服务采用合适自己的解决方案,不用去刻意弄个kafka之类的
现在这个架构看上去完美了,但是如果哪一个节点出现了问题该怎么办
所以运维的时候,第一步要确定我们的系统要做标准化,
明文系统版本要一致,程序版本要一直,路径组织要一致,做好能一致化,
做好这步就是做好监控,对你整个系统当中的每一个组件都需要做好监控并发现故障以后随之报警,通知人来修复
监控系统只能发现问题,还需要去解决问题
解决问题需要(坏的系统换了新的,那就需要装系统,装程序,提供电源,启动服务,再让它加入调度器里,继续服务)
ip地址可以变,但是主机名可以不变,所以内部就需要一个DNS服务器
这时候就需要个配置服务器,把你整个环境中的所有主机,每一台主机要装什么程序,提供什么配置文件,启动哪些服务等等都在这个服务器里面定义好,它能够周期性的和你的监控系统一样的,监控你的每一台主机是不是处于我们所期望的目标。(某个服务是否启动,某个配置文件是否一致)就能够强制你的每一个节点,把软件装上,把配置文件copy过去,把服务启动起来
监控要是发现故障就去通知配置系统,配置系统再去配置修复监控,
如果不想人工换服务器还有个简单办法,云化,所有服务器能用虚拟机的就用虚拟机,虚拟机故障了没关系,出现问题直接删除,只要数据不在本地,直接创建新实例,继续来
有了云以后,装系统部署系统的时候还是很麻烦,就像装订程序一样,有很多依赖关系,但是如果部署的是python程序的时候,这个依赖关系不是那么容易解决的(各种模块,各种库,各种第三方pam,都需要安装,这个依赖关系解决起来非常复杂,如果不访问互联网,很可能有些安装包是安装不了的,对于装系统的用户来讲,这是很大的挑战,如果出现问题,只能 一个应用程序和它依赖的包打包成一个镜像文件,直接基于此镜像文件启动,容器),所以系统运行以后,再也不是单个单个运行,而是一个程序一个容器,自带所有依赖关系都可以解决
dooker的实现对于人工的要求是越来越少
云依赖于底层的网络构建能力,所以一般建议小公司用公有云
这样还缺一步,如何把自己的网站推到用户家门口,CDN,各个地方的解析域名,得到的服务器是离的最近的缓存服务器地址
如果CDN没有名字,才会CDN发起请求链接到你的站点上来,这意味着站点可能有百分之8090的压力受CDN承载
如果CDN挂了,你的机房服务器挂了,你就需要异地做机房,做好冗余
基于doocker来构建整个系统,叫做容器化,确实能很大程度上降低我们运维工作的复杂程度
我们做整个站点,就需要做运维分析,整个网站还有搜索引擎系统(ELK)
没准有数据集数据量很大,需要做到实时展示的,还需要一些大数据 流处理系统(strom)
varnish的官方站点
要HTTP1.1版本中,有两种缓存协议,过期缓存逻辑,2.条件是请求,缓存内容过期了也不会立即去后端服务器要数据,先问问后端服务器有没有进行修改,没有修改继续用,缓存又更新一个生命周期)
能大大减少后端服务器的压力
2019/06/05 M web站点架构演变及缓存系统优化
最新推荐文章于 2023-08-07 15:09:55 发布