前言
永远记得:微服务不是代表系统快、微服务不代表性能就好了。相反,实施了微服务后如果你没有掌握好要领,你反而会比没实施微服务“死了更惨”。
这句话非常有意思。我们不急,看下去。
通过一个实际例子我们来看没有微服务带来的危害先。
2021年11月27号因为用户模块中访问直播间的一条API被卡死后发生的事。
实例例子
在我们的生产上,用户模块内访问微信直播间API,互联网一侧(微信直播间应该是发生了一次网络抖动)不响、超时后,直接导致了用户模块侧外联互联网API被强制打断。打断后进而一路卡在了用户模块内,这样的HTTP请求越堆越多,最终因为搜索、订单、购物车都要依赖于用户模块,由于用户模块来不及释放本身卡死的http请求而导致该模块对所有访问请求进行了“排队”等待,导致了小程序首页、搜索、分类、加车提交慢。
改进手段
我们通过结果来推导设计。
首先,对于这种外联侧请求不管是它会发生网络抖动、还是请求超时还是第三方自身出现了问题,我们必须及时把这条请求踢掉。
踢掉手段无非就是:断开。那么我们自然而然想到了HttpConnection的connectionTimeOut这个值,这个值设了有用吗?然并没用!看下去。
这就是超时的作用,它根本没有解决问题。
提出我们要解决的问题
- 严重超时,熔断请求;
- 此时相应的外联模板应该还在短时间未恢复,此时就不能再让这种请求进入模块了,因此需要在一个可配阀值内不让外部请求进入,这就叫“服务降级”;
- 当过了一段阀值设置的时间后,我再试一条(仅且仅试一次)外联请求,恢复了,那么我放行后面的请求,这就叫“服务升级”;
对于以上设计,传统的做法我可以:
- 使用connectionTimeOut+Redis计数器+分布式锁+异步线程去实现;
- 我可以使用connectionTimeOut+Zk计数器+分布式锁+异步线程去实现;
- 我还可以。。。用至少10种实现手段
有必要吗?企业级开发,我们已经有现成的、成熟的工具、框架、平台了,为什么“闭门超车”?
所以,针对上述设计,我们必须使用“微服务”框架去实现它。
在此,我们选用了spring cloud2.0+nacos+feign+hystrix去做这个实现。
- 把微信直播室相关的API包成一个微服务;
- 设这个living-room-microservice为5秒熔断;
- 熔断后在一段时间内,不会再请求这“一条路”了 – 服务降级;
- 过一段时间(默认是5分钟),再试图去请求一下直播室,如果<5秒,那么恢复此服务 – 服务升级。否则,继续熔断;
- 熔断期间,由于服务降级了,因此用户相关模块内其它业务不会再被影响;
- 为了更加安全把这个直播服务移到一个弱业务模块内,如:网关层;
微服务设计后带过来的另一个梗
这个标题我把它做成了红色高亮加粗,为什么呢?
大家看着上面一个图想一下。
如果右边这一块“微信小程序官方API”就是慢,就是永远>我们设置的“超时熔断时间”,会发生什么?
不断的被熔断!
所以很多我们的猿们,为了让“业务正常”,就去放大微服务的超时时间!这就是著名的ALI、美团、饿了吗、金蚂蚁经常问的:你放大微服务超时时间,那当初为什么不做成HTTP CONNECTION永不超时的那种20年前的模式不就完了?
所以,这边呼应了上头开篇处那句话:微服务不是代表系统快、微服务不代表性能就好了。相反,实施了微服务后如果你没有掌握好要领,你反而会比没实施微服务“死了更惨”。这后半段话。
因此我们需要在微服务设计原则上再加一句话:一旦使用了微服务设计,对你的单体模块的性能反而提出了更高的响应速度、资源使用上的要求。由于是微服务设计(熔断、服务降级、服务升级)因此本来不容易发生的“业务操作的顺畅性”,现在变成了经常被打断。这就要求对每一个走微服务的模块做到性能上的极致表现。
因此总结什么是微服务设计。
总结
- 上联:微服务不是代表系统快、微服务不代表性能就好了。相反,实施了微服务后如果你没有掌握好要领,你反而会比没实施微服务“死了更惨”;
- 下联:一旦实现了微服务,那么对每一个联通微服务的模块的单体性能提出了更高的性能要求;
- 横批:不要做猿要做真正的“程序员”;