共计 1398 个字符,预计需要花费 4 分钟才能阅读完成。
线上服务 CPU 飙升
前言
- 性能开发实现仅仅是我的项目周期中的第一步,一个完满的我的项目是在运行期体现的
- 明天咱们就来看看笔者之前遇到的一个问题 CPU 飙升的问题。代码层面从性能上看没有任何问题然而投入使用后却让我头大
问题形容
- 零碎上点击数据录入性能在全局监控中会受到相干音讯的告诉。此时服务器 CPU 飙升 300%
问题定位
- 首先咱们先梳理下
Websocket
的数据发送的简略原理示意图。往往定位问题得分明咱们的逻辑是什么 - 当一个客户端启动时除了和
Websocket
建设连贯之外,咱们还须要向Websocket
服务注册以后客户端须要哪些接口的实时数据 - 我在代码外部是通过一个 Map 来存储这些接口签名信息的。而后客户注册时候将这些接口和客户端绑定在一起
- 当咱们监听程序坚挺到数据变动就会对绑定到相干接口的客户端发送最新数据
业务定位
- 业务上很好定位,问题就是呈现在咱们的监听程序中。当监听到数据给
websocket
客户端发送订阅的最新变动接口时就会呈现 CPU 飙升。持续时间还很长,稍等一会就会降下来 - 这很显著是咱们推送音讯的时候呈现了问题
隔离业务看实质
- 作为一个合格的程序员呢,必须解脱业务能力有所播种。业务是咱们代码的外壳所有的问题基本上都是咱们实质的问题。咱们线上应用用户 1W 内。在这种的并发场景下应该是不会出问题的。当初出了问题必定咱们的程序逻辑有缺点
- 下面是咱们的发送音讯的代码。代码也很简略。先获取所有合乎发送条件的客户端。而后通过客户端外部提供的
sendMessage
办法进行推送。 - 然而这个时候的
message
是咱们的接口信息。在外部会基于客户端保留的办法签名进行反射调用从而获取最新数据。在推送给客户端的 - 在下面的代码中外围的是
WebsocketManager.messageParse
。这段是获取音讯而后发送。外面获取音讯是基于 resultful 格局解析的
- 这个办法外部咱们有内置了咱们的四种解析形式。这里咱们只须要关怀
RequestMappingMessageParseHandlerImpl
这个协定。
- 对于咱们外部的协定这里也不须要太在意。这是咱们本人的一个设计。依据下面的图示咱们也能看的进去外面
RequestMappingMessageParseHandlerImpl
是外围
产生起因
- 下面咱们简略的梳理了下代码的逻辑。
- 仔细分析下咱们是遍历所有客户端而后在反射调用接口数据进行返回的。实际上在音讯推送时咱们没必要在每个客户端外部调用数据。咱们齐全能够先调用数据而后在遍历客户端进行发送。
- 这也是导致 CPU 过高的问题。咱们 1W 个用户共事在线的可能有 5000+。那么咱们须要 5000 次以上的反射着必定是吃不消的。这也是为什么本文结尾说性能失常不代表业务失常。
解决方案
- 这就是质变引起量变。在多客户的状况下咱们的设计弊病就裸露进去。这里也是笔者本人给本人挖坑。既然找到问题咱们就好解决了。上面咱们对代码做了一下改变
- 我将数据缓存起来。因为在同一批次推送时原本也应该保证数据一致性。而且咱们系统对数据实时性也是能够承受肯定时间延迟的。我在这里又加上缓存这样就解决了咱们循环的问题
- 通过测试本次改变在 CPU 上大略优化了 100 倍。
总结
- 性能开发实现仅仅代表性能的试验没有问题
- 单用户和多用户齐全是两种不同的用户状态。咱们功能设计初期就应该尽量思考数据量的问题
- 惟一做的好的中央是我通过责任链模式将数据解析隔离进去。否则这样的问题定位将会更加麻烦
正文完