在设计高并发的应用程序时,遵循以下原则可以更好的实现目的。
无状态应用无状态方便水平扩展。实际的情况通常是,应用是无状态的,但是配置文件是有状态的,例如不同机房的应用读取不同的数据源。需要配置文件或配置中心来分配。
搭配K8S,水平扩展更方便。
拆分在系统设计时,要考虑到系统是否做拆分。如果资源有限,并且用户并没有那么多,可以做一个大而全的系统。
而高并发的应用,通常是要做拆分的。
拆分可以依据多个维度:
系统维度 :如订单、库存、商品系统等功能维度 :如,对登录系统再拆分,划分为 :验证码登录、微信登录、密码登录等功能。读写维度 :针对读写再做分离,读服务可以使用缓存、写服务使用分库分表。 服务化
首先判断单点服务是否可以满足,
如果不能满足,集群可以吗?使用Nginx做负载均衡是否可以解决?
服务越来越多,是否要使用服务自动注册与发现?
某些服务访问量太大,导致整个系统不可用,要不要上服务降级和限流?哪些是主要服务?
消息队列消息队列的作用有三个 :削峰、解耦、异步。
某一个事件消息,多个系统需要使用到。如,注册了一个新的用户,优惠券系统需要送劵、积分系统送积分,会员系统可能要推荐用户开会员,并且以后还会有某些系统新增对这个事件的处理。这种如果用系统调用太复杂了,而且不解耦,每接入一个新系统,就可能需要修改代码。这种情况,使用MQ是最好的。
消息队列的另一个作用是削峰,比如某个应用的处理速度是每秒三千条,而上游系统突然来了大流量,产生速度是每秒一万条,使用MQ,可以保证下游应用不被大流量压垮。
在消息队列技术选型上,也要充分考虑。如:消息是否可丢,MQ高可用怎么做,如何确保幂等性、活跃度、排查难度。
数据异构用户查询订单列表,需要聚合多个表,可能速度就很慢,体验很差。
此时需要依据用户的ID做分库分表。
但某些场景是无需做异构的,比如商品的信息,可以考虑使用异步加载的方式。
缓存缓存是对抗大流量的最佳银d,并且可以划分多种缓存,分别存储不同的信息,以解决不同的场景。
浏览器端缓存
设置请求的过期时间,如响应头的Expires和Cache-Control。这种适合实时性不高的数据,如商品页框架、广告词、评价等。
301是永久转移,浏览器是会缓存的。
302是不会缓存的,搜索引擎也会保存原地址,这样就可能被网址劫持。
301并不总是比302好,比如在实现短链服务时,需要对短链的访问进行统计,就必须要用到302。
客户端缓存
APP可以提前在后台把即将要用到的东西先从服务端拉取,等到要使用的时候先检查本地有无。
CDN缓存
可以将静态资源推送到CDN上。
用户访问时,去最近的CDN节点拉取。
CDN资源的URL不能有随机数,如果每次URL都不同,那每次都会穿透到服务端去访问资源。
接入层缓存
使用Nginx做一层缓存。
在使用Nginx做缓存,可以考虑使用以下机制实现 :
URL重写,去除随机数一致性哈希 :对参数做哈希,确保相同数据落到同一台机器proxy_cache :使用内存级、ssd代理来缓存内容。proxy_cache_lock:lock机制,将回源合并,要设置lock的超时时间。
应用层缓存
应用在水平扩展启动新应用时、或者重启应用,本地缓存就会失效。而水平扩展时,可能流量就很大,这时候没有本地缓存就很慢。
可以考虑在本机搭建一个Redis,应用读本地的Redis,Redis集群之间主从同步。
分布式缓存
如果存放在Redis的数据量很大,那么单机Redis就不能用来。
要使用分布式缓存了。分片规则可以采用一致性哈希。
异步与并发
某些资源实时性没那么高,可以考虑使用异步加载,如用户评价、商品打分这种。
获取多个资源时,采用并发的方式获取,可以大大的加快访问速度。
高可用原则高并发与高可用是相辅相成的。
服务降级降级开关
高可用服务,很重要一个设计是降级开关。当监控发现流量达到阈值时,告知各系统打开降级。
可降级的多级读服务
可以指定服务调用降级为只读本地缓存、只读分布式缓存、只读默认数据。
业务降级
高并发流量时,将服务调用修改为异步调用,这样方便下游系统做优先级判断,优先确保高优先级的服务。保证最终一致性。
限流限流的目的是,防止流量超出系统的峰值。
有些大流量是正常的用户,这种是要临时的水平扩容。
有些流量是恶意的,如爬虫,这种恶意流量需要加以限制。需要针对的设置一些防爬机制,如:
爬虫只访问到cache穿透到后端的应用可以考虑使用Nginx的limit模块恶意访问的IP,使用nginx deny进行限制。【作用不大,IP代理并不贵,可能误封】给恶意访问假数据 可回滚
灰度发布。版本化机制,当程序出错时,回滚到上一个版本。
流量调度大型应用,切流量是很重要的,并且划分为多个层面。
DNS :切换机房的入口HttpDNS:APP绕过运营商实现更精准的流量调度LVS/HaProxy :切换故障的NginxNginx :切换故障的应用层 业务设计的原则 幂等性
会有一些重复性的调用,被调用方需要对接口进行幂等性校验。
比如,防止重复支付。
可以考虑使用防重Key。
并且如果重复调用了,需要及时监测并弥补。如,同一个订单用户使用不同的支付渠道支付了,检测到时,需要及时退款。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)