从运维角度看代码的高并发
前言
简单讲解一下架构和目前面临的问题,废话不多说看下图。
这里只画了一小部分架构图,但足已说明问题。
现有的架构是完全可以满足公司的业务模式,但是前两天因为一个活动(邀请用户注册进行投票,注册的时候会给用户发送短信)
我们的网站出现无法打开的情况,经过排查后发现是短信服务出现了异常。
问题分析
短信是一个独立的基础服务,查看短信日志发现redis
连接池不够了,已经为短信分配了1000
个连接,此时对外服务连接短信服务进入排队队列中,大量的请求连接等待造成对外服务也无法响应。
在开发环境对短信服务进行压力测试进行问题复现,这时候和开发一起review
代码,每一个请求进来进行发送短信都会开启一个线程,线程里有大量的操作redis
比如分布式锁d,短信的一些规则等,这里有一个问题就是,一个线程中使用了多个redis
连接,虽然每次都会使用之后都会进行释放,但是在多线程中会造成抢占而导致连接池不够的情况。这里找到一个问题
继续review
代码,限流器在限流使用的是排队的方法,这里就会造成系统无法处理时大量的无效连接让上游系统进入一直等待结果的状态。
解决问题方法
需要解决问题
- 连接池不够
- 与上游系统解耦
修改代码中每个线程只使用一个连接,并且线程池不能大于redis
连接池,线程池不够就进入限流规则。
其实短信业务的实时性要求并不是那么高,而且也允许进行重试,既然这样那就使用粗暴的方法直接修改限流器为拒绝,返回信息让用户重试,这样就和上游进行解耦了。其实还可以使用消息队列这是更好的解决方法。这里考虑到了改造成本,维护成本,消息队列成本还有业务模式暂时没有选择消息队列。
到此为止问题解决了,并且保证了短信服务的稳定性。其实问题解决方法很简单。