1)数据层
2)项目层
3)应用层
1、HTML静态化 freemaker
其实大家都知道,效率最高、消耗最小的就是纯静态化的html页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问的各个门户站点的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。除了门户和信息发布类型的网站,对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子、文章进行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop的大杂烩就是使用了这样的策略,网易社区等也是如此。同时,html静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用html静态化来实现,比如论坛中论坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以考虑将这部分内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求。
2、图片服务器分离
大家知道,对于Web服务器来说,不管 是 Apache、IIS还是其他容器,图片是最消耗资源的,于是我们有必要将图片与页面进行分离,这是基本上大型网站都会采用的策略,他们都有独立的图片服务器,甚至很多台图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力,并且可以保证系统不会因为图片问题而崩溃,在应用服务器和图片服务器 上,可以进行不同的配置优化,比如apache在配置ContentType的时候可以尽量少支持,尽可能少的LoadModule,保证更高的系统消耗和执行效率。
3、数据库集群和库表散列
大型网站都有复杂的应用,这些应用必须使用数据库,那么在面对大量访问的时候,数据库的瓶颈很快就能显现出来,这时一台数据库将很快无法满足应用,于是我们需要使用数据库集群或者库表散列。在数据库集群方面,很多数据库都有自己的解决方案,Oracle、Sybase等都有很好的方案,常用的MySQL提供的Master/Slave也是类似的方案,您使用了什么样的DB,就参考相应的解决方案来实施即可。上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制,于是我们需要从应用程序的角度来考虑改善系统架构,库表散列是常用并且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者功能进行更小的数据库散列,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu的论坛就是采用了这样的架 构,将论坛的用户、设置、帖子等信息进行数据库分离,然后对帖子、用户按照板块和ID进行散列数据库和表,最终可以在配置文件中进行简单的配置便能让系统随时增加一台低成本的数据库进来补充系统性能。
4、缓存
缓存一词搞技术的都接触过,很多地方用到缓存。网站架构和网站开发中的缓存也是非常重要。这里先讲述最基本的两种缓存。高级和分布式的缓存在后面讲述。 架构方面的缓存,对Apache比较熟悉的人都能知道Apache提供了自己的缓存模块,也可以使用外加的Squid模块进行缓存,这两种方式均可以有效的提高Apache的访问响应能力。 网站程序开发方面的缓存,Linux上提供的Memory Cache是常用的缓存接口,可以在web开发中使用,比如用Java开发的时候就可以调用MemoryCache对一些数据进行缓存和通讯共享,一些大型社区使用了这样的架构。另外,在使用web语言开发的时候,各种语言基本都有自己的缓存模块和方法,PHP有Pear的Cache模块,Java就更多了。
5、镜像
镜像是大型网站常采用的提高性能和数据安全性的方式,镜像的技术可以解决不同网络接入商和地域带来的用户访问速度差异,比如ChinaNet和EduNet之间的差异就促使了很多网站在教育网内搭建镜像站点,数据进行定时更新或者实时更新。在镜像的细节技术方面,这里不阐述太深,有很多专业的现成的解决架构和产品可选。也有廉价的通过软件实现的思路,比如Linux上的rsync等工具。
6、负载均衡
负载均衡将是大型网站解决高负荷访问和大量并发请求采用的终极解决办法。 负载均衡技术发展了多年,有很多专业的服务提供商和产品可以选择。
秒杀实现思路
秒杀技术实现核心思想是运用缓存减少数据库瞬间的访问压力!读取商品详细信息时运用缓存,当用户点击抢购时减少redis中的库存数量,当库存数为0时或活动期结束时,同步到数据库。 产生的秒杀预订单也不会立刻写到数据库中,而是先写到缓存,当用户付款成功后再写入数据库。所有买家在同一时间网上抢购的一种销售方式。通俗一点讲就是网络商家为促销等目的组织的网上限时抢购活动。由于商品价格低廉,往往一上架就被抢购一空,有时只用一秒钟。
秒杀商品通常有两种限制:库存限制、时间限制。
需求:
秒杀架构设计理念
前端方案:浏览器端
后端方案:服务端控制器层(网关层)
使用Redis缓存实现秒杀:
Redis是一个分布式缓存系统,支持多种数据结构,我们可以利用Redis轻松实现一个强大的秒杀系统。我们可以采用Redis 最简单的key-value数据结构,用一个原子类型的变量值(AtomicInteger)作为key,把用户id作为value,库存数量便是原子变量的最大值。对于每个用户的秒杀,我们使用 RPUSH key value插入秒杀请求, 当插入的秒杀请求数达到上限时,停止所有后续插入。然后我们可以在台启动多个工作线程,使用 LPOP key 读取秒杀成功者的用户id,然后再操作数据库做最终的下订单减库存操作。当然,上面Redis也可以替换成消息中间件如ActiveMQ、RabbitMQ等,也可以将缓存和消息中间件 组合起来,缓存系统负责接收记录用户请求,消息中间件负责将缓存中的请求同步到数据库。
当商品库存数量不足时,如何保证不会超卖?当库存数量不足时,必须保证库存不能被减为负数,如果不加以控制,库存被减为小于等于0的数,那么这就叫做超卖。
那么如何防止超卖的现象发生呢?
做交易或是金融系统安全性需要从哪些方面考虑?没有用什么第三方可以框架?
ip黑白名单,访问日志明细记录,防止重复提交,访问频率控制,分布式锁,数据前后端校验,自动对账任务处理,互联网金融项目一般情况下,不建议自动重试,最好结合对账系统,人工进行处理,写好人工处理的接口就好。其他就是控制好数据的一致性了,这个最重要,其次还要保证接口的幂等性,不要重复处理订单。这些是最基本的安全控制了。像这类网站用户的输入数据一般都不会太多,一般敏感词过滤,广告之类的可以忽略,如果有的话还要控制这些。安全框架选shiro 了,在系统中分配好角色就好了,控制好用户的资源访问。其他的用springmvc 就够了。
讲一下高并发下的电商项目每台服务器的集群数量:
项目中一共15台项目服务,那么为了每一台高可用一主一备,但首页项目高并发设为四台服务器,则一共32台项目服务器,再加redis集群用了3台,为了每一台高可用一主一备一共6台,fastdfs一个trackerServer一个storageServer搭建集群一共6台,solr集群7台服务器,nginx为了高可用一主一备一共2台,mysql数据库集群3台!activemq消息中间件高可用2台;
共计:58台服务器!
介绍一下高并发的电商项目:
我最近的一个项目是一个电商项目,我主要负责的是后台管理和商品详情的模块,然后也会参与到购物车和订单模块。这个项目是以SpringBoot和mybatis为框架,应为springBoot相对于SSM来说 配置方面,还有操作方面简单很多。然后是采用zookeeper加dubbo分布式架构和RPC远程调用,因为他Dubbo实现了软负载均衡,其特点是成本低,但也会有缺点,就是负载能力会受服务器本身影响,然后为了解决软负载均衡的缺点,我们使用了Nginx进行负载均衡的轮询算法,但Nginx主要在我们项目还是实现反向代理,就是可以防止外网对内网服务器的恶性攻击、缓存以减少服务器的压力和访问安全控制。基础模块就有后台管理,商品详情,订单,支付,物流情况,库存服务。然后SpringBoot整合Thymeleaf模块技术开发项目商品详情模块,easyUI开发后台管理项目。至于我负责的两个模块呢,就是后台管理和商品详情,其中呢使用了sku和spu的数据表结构进行增删改查,spu就好比我们要买一台Mate20,但是我们没有选择它是什么配置,那么关于详细的配置就是sku了,就是我要买一台Mate20,黑色,内存是128G的。商品详情和商品列表模块使用Nginx实现集群,使用Redis解决应用服务器的cpu和内存压力,减少io的读操作,减轻io的压力,使用分布式锁防止Redis缓存击穿。其中Redis的作用我是觉得挺大的,因为他可以防止过多的用户去直接访问我们的数据库,当然,Redis也会在高并发的时候宕机,在使用Redis做缓存的时候,我们使用Redis持久化功能,防止Redis宕机后数据丢失,如果Redis宕机了,用户就会大量的去访问数据库,从而我们数据库也会崩溃吧。这个时候我们就用了一个分布式锁,用户需要获得一个锁才能访问我们的数据库,当然啦,并不只是只有一个锁,而是锁的数量是有限的,当一位用户查完了数据之后,锁就会释放,给下位用户,这也就是服务降降级。没有获得锁的用户,页面就一直刷新直到自己拿到锁为止。redis提供了持久化功能——RDB和AOF。通俗的讲就是将内存中的数据写入硬盘中。在实际应用中,用户如果要查询商品的话呢,首先回到Redis缓存里面找的,如果找不到,就会到数据库里面找,然后缓存到Redis中,那么下一次或者下一个用户需要查找这个数据就不必到数据库中查找了!然后我还参与了购物车和订单模块的开发。购物车模块里面呢,我先和您讲下他的业务逻辑吧。就像你逛网页淘宝一样,在没有登录的时候,把东西放入购物车,它是不会和你的账号里的商品合并的,这个时候,商品就会以cookie的形式,放到你的浏览器里面。这个时候如果你想购买这些商品的时候,你就要登录,这个时候就会使用到单点登录这一个技术。用户跳转到订单页面的时候,我们会用拦截器去进行判断用户是否已经登录。我们是用cookie中是否有token,如果没有token的话就跳转到登录页面,然后生成token,至于token的生成呢,我们是用本地的IP,用户的id,保存在map中,还有一个常量,这个我们通常会以项目名称来命名的。至于为什么要token呢,其实是因为cookie是不太安全的,它很容易被伪造,所以我们就需要token,然后有了token之后,我们用JWT这个盐值生成最后的token。并把它保存到cookie当中。下一次支付的时候我们也还会用到这个token,用一个加密算法再去运算验证一下就可以了!然后就是合并购物车了。这个的话我所知道的就是将客户端的cookie复印一份到缓存中进行修改然后送回客户端进行覆盖,再接着就是数据库的修改了。那这个如果登陆了的就直接从数据库中取得数据跳到订单系统了。然后订单模块里面,简单来说就是从购物车中勾选的商品迁移到订单里面。但是呢订单模块其实是会联系到另外两个模块的,就是库存和支付。如果你点击了提交订单,商品就会在购物车里移除。然后我们提交订单避免他反复的提交同一个订单,就会通过交易码防止订单重复提交。我们会吧tradecode放在缓存里面,以用户id为key商品的交易为value在Redis里面保存这个交易码。到最后选好收货地址,留言之后,提交订单了,就会用自己的tradecode和在Redis里面通过用户的id去获取tradecode进行对比,如果能跳转到支付页面,那么缓存中的交易码就会删除掉。到最后就是支付功能,这一步的话我是不太清楚其中的技术点了,只知道这个模块调用了支付宝的接口和用了消息队列,异步通知。
高并发下的一些优化:
数据层面的优化:
项目层面的优化:
服务器层面的优化:
通常企业级应用系统(特别是政府部门和大企业的应用系统)一般会采用安规的软硬件设备,如IOE(IBM的小型机、Oracle数据、EMC存储设备)系列。而一般互联网公司更多地采用PC级服务器(x86),开源的数据库(MySQL)和操作系统(Linux)组建廉价且高容错(硬件故障是常态)的应用集群。
目的:保证服务器硬件故障服务依然可用,数据依然保存并能够被访问。
主要的手段?
数据和服务的①冗余备份以及②失效转移:
高可用的服务
①分级管理:核心应用和服务具有更高的优先级,比如用户及时付款比能否评价商品更重要;
②超时设置:设置服务调用的超时时间,一旦超时,通信框架抛出异常,应用程序则根据服务调度策略选择重试or请求转移到其他服务器上
③异步调用:通过消息队列等异步方式完成,避免一个服务失败导致整个应用请求失败的情况。不是所有服务都可以异步调用,对于获取用户信息这类调用,采用异步方式会延长响应时间,得不偿失。对于那些必须确认服务调用成功后才能继续进行下一步的操作的应用也不适合异步调用。
④服务降级:网站访问高峰期间,为了保证核心应用的正常运行,需要对服务降级。
降级有两种手段:
⑤幂等性设计:保证服务重复调用和调用一次产生的结果相同;
高可用的数据
保证数据高可用的主要手段有两种:一是数据备份,二是失效转移机制;
①数据备份:又分为冷备份和热备份,冷备份是定期复制,不能保证数据可用性。热备份又分为异步热备和同步热备,异步热备是指多份数据副本的写入操作异步完成,而同步方式则是指多份数据副本的写入操作同时完成。关系数据库的热备机制就是通常所说的主从同步机制,实践中通常使用读写分离的方法来访问Master和Slave数据库,也就是说写操作只访问Master库,读操作均访问Slave库。
②失效转移:若数据服务器集群中任何一台服务器宕机,那么应用程序针对这台服务器的所有读写操作都
要重新路由到其他服务器,保证数据访问不会失败。
网站运行监控
”不允许没有监控的系统上线“
(1)监控数据采集
①用户行为日志收集:服务器端的日志收集和客户端的日志收集;目前许多网站逐步开发基于实时计算框架Storm的日志统计与分析工具;
②服务器性能监控:收集服务器性能指标,如系统Load、内存占用、磁盘IO等,及时判断,防患于未然;
③运行数据报告:采集并报告,汇总后统一显示,应用程序需要在代码中处理运行数据采集的逻辑;
(2)监控管理
①系统报警:配置报警阀值和值守人员联系方式,系统发生报警时,即使工程师在千里之外,也可以被及时通知;
②失效转移:监控系统在发现故障时,主动通知应用进行失效转移;
③自动优雅降级:为了应付网站访问高峰,主动关闭部分功能,释放部分系统资源,保证核心应用服务的正
常运行;—>网站柔性架构的理想状态
其他手段:
什么是负载均衡?
当一台服务器的性能达到极限时,我们可以使用服务器集群来提高网站的整体性能。那么,在服务器集群中,需要有一台服务器充当调度者的角色,用户的所有请求都会首先由它接收,调度者再根据每台服务器的负载情况将请求分配给某一台后端服务器去处理。
(1)HTTP重定向负载均衡。
这种负载均衡方案的优点是比较简单;
缺点是浏览器需要每次请求两次服务器才能拿完成一次访问,性能较差。
(2)DNS域名解析负载均衡
优点是将负载均衡工作交给DNS,省略掉了网络管理的麻烦;
缺点就是DNS可能缓存A记录,不受网站控制。
(3)反向代理负载均衡。
优点是部署简单;
缺点是反向代理服务器是所有请求和响应的中转站,其性能可能会成为瓶颈。
(4)IP负载均衡。
优点:IP负载均衡在内核进程完成数据分发,较反向代理均衡有更好的处理性能。
缺点:负载均衡的网卡带宽成为系统的瓶颈。
(5)数据链路层负载均衡。
避免负载均衡服务器网卡带宽成为瓶颈,是目前大型网站所使用的最广的一种负载均衡手段。
(1)HTTP重定向负载均衡。
原理:当用户向服务器发起请求时,请求首先被集群调度者截获;调度者根据某种分配策略,选择一台服务器,并将选中的服务器的IP地址封装在HTTP响应消息头部的Location字段中,并将响应消息的状态码设为302,最后将这个响应消息返回给浏览器。当浏览器收到响应消息后,解析Location字段,并向该URL发起请求,然后指定的服务器处理该用户的请求,最后将结果返回给用户。
优点:比较简单
缺点:调度服务器只在客户端第一次向网站发起请求的时候起作用。当调度服务器向浏览器返回响应信息后,客户端此后的操作都基于新的URL进行的(也就是后端服务器),此后浏览器就不会与调度服务器产生关系,浏览器需要每次请求两次服务器才能拿完成一次访问,性能较差。而且调度服务器在调度时,无法知道当前用户将会对服务器造成多大的压力,只不过是把请求次数平均分配给每台服务器罢了,浏览器会与后端服务器直接交互。
(2)DNS域名解析负载均衡
原理:为了方便用户记忆,我们使用域名来访问网站。通过域名访问网站之前,首先需要将域名解析成IP地址,这个工作是由DNS域名服务器完成的。我们提交的请求不会直接发送给想要访问的网站,而是首先发给域名服务器,它会帮我们把域名解析成IP地址并返回给我们。我们收到IP之后才会向该IP发起请求。一个域名指向多个IP地址,每次进行域名解析时,DNS只要选一个IP返回给用户,就能够实现服务器集群的负载均衡。
优点:配置简单,将负载均衡工作交给DNS,省略掉了网络管理的麻烦;
缺点:集群调度权交给了DNS服务器,从而我们没办法随心所欲地控制调度者,没办法定制调度策略,没办法了解每台服务器的负载情况,只不过把所有请求平均分配给后端服务器罢了。某一台后端服务器发生故障时,即使我们立即将该服务器从域名解析中去除,但由于DNS服务器会有缓存,该IP仍然会在DNS中保留一段时间,那么就会导致一部分用户无法正常访问网站。不过动态DNS能够让我们通过程序动态修改DNS服务器中的域名解析。从而当我们的监控程序发现某台服务器挂了之后,能立即通知DNS将其删掉。
调度策略:一般DNS提供商会提供一些调度策略供我们选择,如随机分配、轮询、根据请求者的地域分配离他最近的服务器。
随机分配策略:当调度服务器收到用户请求后,可以随机决定使用哪台后端服务器,然后将该服务器的IP封装在HTTP响应消息
的Location属性中,返回给浏览器即可。
轮询策略(RR) :调度服务器需要维护一个值,用于记录上次分配的后端服务器的IP。那么当新的请求到来时,调度者将请求依
次分配给下一台服务器。
(3)反向代理负载均衡。
原理:反向代理服务器是一个位于实际服务器之前的服务器,所有向我们网站发来的请求都首先要经过反向代理服务器,服务器根据用户的请求要么直接将结果返回给用户,要么将请求交给后端服务器处理,再返回给用户。反向代理服务器就可以充当服务器集群的调度者,它可以根据当前后端服务器的负载情况,将请求转发给一台合适的服务器,并将处理结果返回给用户。
优点:
缺点:
解决办法:
(4)IP负载均衡。
优点:IP负载均衡在内核进程完成数据分发,较反向代理均衡有更好的处理性能。
缺点:负载均衡的网卡带宽成为系统的瓶颈,场景:某个服务器跑的应用非高峰期间都能达到500M以
上,晚高峰一般能够超过1G,主流服务器的网卡都是千兆的,超过1G的流量明显会导致丢包的问题,此时又不
能停止业务对网卡进行更换。
(5)数据链路层负载均衡。
对于linux系统来说,数据链路层的解决方案就是实现多个网卡绑定联合提供服务,把多张网卡捆绑做成一个逻辑网卡。避免负载均衡服务器网卡带宽成为瓶颈,是目前大型网站所使用的最广的一种负载均衡手段。linux bonding的七种模式,mod=0~6:平衡抡循环策略,主-备份策略,平衡策略,广播策略,动态链接聚合,适配器传输负载均衡,适配器适应性负载均衡