首先必须要从代码层面上提升性能,利用缓存等,如果在访问量大,确实无法处理的情况下就要考虑限流,或者防刷也是要考虑限流,然后如果服务确实不可用的话就把服务进行降级,比如当无法获取评论信息的时候,但是写的朋友圈是要正常返回的。不能因为评论服务无法提供,连朋友圈也不能看了。
缓存
可以通过注解把技术相关的,读缓存,写日志,写缓存的功能,使用注解加反射来进行操作。
伪代码:
1 | Cache cache =getCache(); |
业务上,实际只有getDatabase才有用。
伪代码:
1 | @getCache() |
通过注解反射如果有getCache的话直接使用缓存中的数据,如果有直接返回,如果有log写日志,如果有set则把获取到的数据写到cache中。
1 |
限流
限流瞬时流量
双11,秒杀,之类的属于瞬时流量很大,平时相对稳定。
限流总并发量
限流平均流量
滑动窗口
令牌桶,每秒生成n个,限制平均流量
漏桶,这个是应对瞬时流量过大的一种方法,一定的速率进行消费,MQ,削峰,解耦,异步。但是能解决的瞬时流量也是有一个最大值。
计数器,限制总的并发数,比如说每秒钟只能请求100次,是限制总并发量。通常可用redis缓存,请求增加incr来实现。
采用:Google开源工具包Guava提供了限流工具类RateLimiter,该类基于令牌桶算法来完成限流,非常易于使用。
降级
当服务调用者使用同步调用的时候,会产生大量的等待线程占用系统资源,一旦线程资源被耗尽,
服务调用者提供的服务也将处于不可用状态,于是服务雪崩效应产生了!
这时候就需要比如说:当失败了多少次之后,
1,超时机制
2,服务限流
3,服务熔断
4,服务降级
超时机制
如果我们加入超时机制,例如2s,那么超过2s就会直接返回了,那么这样就在一定程度上可以抑制消费者资源耗尽的问题
服务限流
通过线程池+队列的方式,通过信号量的方式。比如商品评论比较慢,最大能同时处理10个线程,队列待处理5个,那么如果同时20个线程到达的话,其中就有5个线程被限流了,其中10个先被执行,另外5个在队列中
服务熔断
这个熔断可以理解为我们自己家里的电闸。
当依赖的服务有大量超时时,在让新的请求去访问根本没有意义,只会无畏的消耗现有资源,比如我们设置了超时时间为1s,如果短时间内有大量请求在1s内都得不到响应,就意味着这个服务出现了异常,此时就没有必要再让其他的请求去访问这个服务了,这个时候就应该使用熔断器避免资源浪费
服务降级
有服务熔断,必然要有服务降级。
所谓降级,就是当某个服务熔断之后,服务将不再被调用,此时客户端可以自己准备一个本地的fallback(回退)回调,返回一个缺省值。 例如:(备用接口/缓存/mock数据),这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强,当然这也要看适合的业务场景