导图按照由浅入深的方式进行讲解,架构从来不是设计出来的,而是演进而来的
从一个几百人的抽奖系统到几万人,再到百万人,不断增加新的东西。
最后总结归纳一套设计思想,也是万能模板,这样面试官问任何高并发系统,只需从这几个方向去考虑就可以了。
当一台服务器的单位时间内的访问量越大时,服务器压力就越大,大到超过自身承受能力时,服务器就会崩溃。为了避免服务器崩溃,让用户有更好的体验,我们通过负载均衡的方式来分担服务器压力。
负载均衡就是建立很多很多服务器,组成一个服务器集群,当用户访问网站时,先访问一个中间服务器,好比管家,由他在服务器集群中选择一个压力较小的服务器,然后将该访问请求引入该服务器。
限流主要的作用是保护服务节点或者集群后面的数据节点,防止瞬时流量过大使服务和数据崩溃(如前端缓存大量实效),造成不可用。还可用于平滑请求。
限流的意义就在于我们无法预测未知流量,比如刚提到的抽奖可能遇到的:
虽然在负载均衡那个层面,已经把比如50万流量中的48万都拦截掉了,但是可能还是会有2万流量进入抽奖服务
此时抽奖服务自然是可以多机器来部署的,比如假设一台Tomcat可以抗500请求,那么2万并发就是40台机器。
但是有个问题,你的数据库MySQL能抗住2万的并发请求吗?
如果你基于MySQL来实现核心的抽奖业务逻辑,40个Tomcat部署的抽奖服务频繁对MySQL进行增删改查,这一个MySQL实例也是很难抗住的。 所以此时还得把MySQL给替换成Redis,通常这种场景下,建议是基于Redis来实现核心的业务逻辑,并同步抽奖状态。
一些热点数据,可以通过定时任务去查询,并写入redis缓存中。
对于线上环境,工作线程数量是一个至关重要的参数,需要根据自己的情况调节。
众所周知,对于进入Tomcat的每个请求,其实都会交给一个独立的工作线程来进行处理,那么Tomcat有多少线程,就决定了并发请求处理的能力。
但是给一个经验值的话,Tomcat的线程数量不宜过多。因为线程过多,普通服务器的CPU是扛不住的,反而会导致机器CPU负载过高,最终崩溃。
同时,Tomcat的线程数量也不宜太少,因为如果就100个线程,那么会导致无法充分利用Tomcat的线程资源和机器的CPU资源。
所以一般来说,Tomcat线程数量在200~500之间都是可以的,但是具体多少需要自己压测一下,不断的调节参数,看具体的CPU负载以及线程执行请求的一个效率。
在CPU负载尚可,以及请求执行性能正常的情况下,尽可能提高一些线程数量。 但是如果到一个临界值,发现机器负载过高,而且线程处理请求的速度开始下降,说明这台机扛不住这么多线程并发执行处理请求了,此时就不能继续上调线程数量了。
由上至下,还剩中奖通知部分没有优化。
接着问题又来了,假设抽奖服务在2万请求中有1万请求抽中了奖品,那么势必会造成抽奖服务对礼品服务调用1万次。礼品服务假设也是优化后的Tomcat,可以抗500并发,难道礼品服务也要去部署20台机器吗?
其实这是没必要的,因为抽奖之后完全可以让礼品服务在后台慢慢的把中奖的礼品给发放出去,不需要一下子就立马对1万个请求完成礼品的发放逻辑。
所以这里可以在抽奖服务和礼品服务之间,引入消息中间件,进行限流削峰。也就是说,抽奖服务把中奖信息发送到MQ,然后礼品服务假设就部署两个Tomcat,慢慢的从MQ中消费中奖消息,然后慢慢完成1完礼品的发放就可以了。