我的物联网项目(七)前期线上事故

一 MQTT连接数报警

项目上线一个月左右,投放出去的摇摇车数量大概在200量左右,平均每天在线数(听说有些商家精打细算,有小孩需要坐车了才插电,平时都不插电,还有些干脆一直仍在角落懒的管)也就维持在100左右,当时在阿里云购买的MQTT配置是连接数上限2000(MQTT是按连接数购买的),像目前的摇摇车投放数用当时的配置绰绰有余了,连续一个月以来,都是正常化(现在想来,当初的推广策略不成熟,每天投放的摇摇车数量也是要么一天3,4台,要么连续好几天才推广3,4台),所以问题并没有暴露出来,不过出来混迟早要还的。

有天下午快下班的时候,突然MQTT不断报警,手机上5秒一次收到报警短信,提示MQTT连接数已经超标(用阿里云的产品感觉这块的预警功提示的还是蛮及时),因为当初也有一些摇摇车在做测试,频繁的使用到MQTT,所以当时也没太在意,叫测试人员先停一下在做测试(这个里面很尴尬,摇摇车扫码启动用到的测试环境和线上环境是同一个MQTT,这个后面再详情描述原因)以为过一会连接数会释放下去,但是手机收到报警短信越来越猛,当时第一时间想到的整体事故点应该在MQTT业务应用层这一端(手机扫码是通过http请求到MQTT应用层,MQTT应用层再扔消息到阿里云MQTT服务器),当初是2台MQTT应用层在做负载均衡集群,我登录2台服务器,分别用top命令查看两台服务器一台CPU在80%左右,另外一台CPU在60%左右,顿时觉得很诧异,这么点摇摇车数据请求不至于导致应用服务器承受不了,当时第一时间想到的是看看TCP的目前的连接数,结果一查吓了跳(使用命令:netstat -natp|awk ‘{print $7}‘ |sort|uniq -c|sort -rn),两台服务器的当前连接数都接近快1W多,还在持续上升(因为当时投放出去的摇摇车还在不断有人在使用消费),这个时候基本定位问题:手机扫码发送http请求到MQTT应用层,MQTT应用层每次仍消息到阿里云MQTT服务器,都需要建立连接。所以问题很有可能是没有释放连接,由于当初的代码逻辑比较简单,所以直接找到写这个代码的开发人员,一起喵了眼代码,果然如此,修改代码后,重新发包一切正常,手机报警短信立马停了。

	public void sendMsgMqtt(String productId, String deviceId, String scontent, String topic){
		String subTopic = getSubTopic(productId, deviceId, topic);
		String clientId = getClientId();
		MemoryPersistence persistence = new MemoryPersistence();
		try {
			 final MqttClient sampleClient = new MqttClient(GlobalConstant.BROKER, clientId, persistence);
             final MqttConnectOptions connOpts = getConnOpts(clientId);
             log.info("Coin Connecting to broker: " + GlobalConstant.BROKER);
             sampleClient.setCallback(new MqttCallback() {
             public void connectionLost(Throwable throwable) {
                 log.info("mqtt connection lost");
                 throwable.printStackTrace();
                 while(!sampleClient.isConnected()){
                     try {
                         sampleClient.connect(connOpts);
                     } catch (MqttException e) {
                         e.printStackTrace();
                     }
                     try {
                         Thread.sleep(1000);
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
                 }
             }
             public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
                 log.info("coin messageArrived:" + topic + "------" + new String(mqttMessage.getPayload()));
             }
             public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
                 log.info("coin deliveryComplete:" + iMqttDeliveryToken.getMessageId());
             }
          });
             sampleClient.connect(connOpts);
             try{
            	 scontent = scontent.replace("[", "").replace("]", "");
            	 final MqttMessage message = new MqttMessage(scontent.getBytes());
                 message.setQos(1);
                 log.info("pushed at "+new Date()+" "+ scontent);
                 sampleClient.publish(subTopic, message);
                 log.info("-------send end---------");
             }catch(Exception ex){
            	 ex.printStackTrace();
             }finally{
               	 sampleClient.disconnect();
                 log.info("-------client disConnect()---------");
             }
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}

二 数据库CPU100%

必须要先说下,创业项目初期,当初的业务都是很不清晰的,基本属于那种摸着石头过河,走一步算一步,再回头想想甚至看看市场的反应,然后再修改,所以这个阶段更多的是检验模式,优化业务,当然资金也有限,而且要求开发迭代要求迅速,所以数据库当初没有做集群,就是一台,玩单机,也正是因为玩单机,所以一些在集群环境下没有这么快爆发出来的问题很容易在单机里面爆发出来。

晚上大概7点左右(晚点7点到9点是摇摇车的使用高峰,白天一般订单数据较少,到了晚上数据成倍的增涨),收到反馈,说平台系统打开很慢很慢,而且手机也不断收到MQTT短信预警,说堆积了大量未消费的订单,第一时间的反应迅速登录云数据库管理平台看到数据库CPU这项指标严重标红,并显示使用率达到100%。当初数据库用的是通用型4核8G的,订单表数据将近40W,打开数据库性能管理界面查看(如果没有这种管理界面,也可以通过命令show processlist来查看正在执行的SQL和explain来分析执行计划查看慢SQL),发现积累了大量的慢SQL,有些SQL的平均执行时间超过将近1分钟,很明显做了数据库的全局扫描,再加上这段时间的高峰时期,慢SQL堆积,导致CPU资源顺序消耗完。

当时也正是业务的使用的高峰期,再加上客户投诉和上面很多人在盯着这个事情,所以我这边要在短时间内恢复数据库的正常,当初有几种选择可以迅速恢复,将数据库切换到备数据库(数据库是高可用的)或者kill掉一些慢SQL(通过show processlist查看state为Sending data的列,然后kill id),这些都有可能会影响到现在正在使用的业务,万不得已的情况的不会第一时间去做。我看了下排在前面的几条慢SQL,其中有些是第一时间可以迅速处理的,比如优化索引,我抱着试试的方法,将之前有些索引重新优化了下(后面会详细描述),过了几分钟,CPU的使用率慢慢的降了下来(没有优化索引之前大概3秒执行一个记录,优化索引后1秒可以执行上千个记录),业务正常了,给我后面做数据库的优化有了大把时间思考,所以这次事件给我最大的感触就是切勿头脑发热,需要冷静最小化处理问题。

这次SQL优化也总结了些经验并做了相关优化如下:

1.添加索引和优化索引,特别小心索引隐式转换

一个表里面如果只是设置了主键,然后其它索引一律不建不管,简单业务如只涉及到按照主键查询的业务是没问题,但是设计到其它字段的查询,在数据量稍大又加上业务高峰期,这种导致表全局查询的SQL肯定会积累大量慢SQL,最终导致CPU持续上升,如果有条件的话,测试最好做一些大数据量的压力测试是可以测试出来的,另外,建立了索引,也要注意到索引失效这种情况。如:select *from order where phone=13772556391; 平时写代码粗心大意,不仔细检查再加上压力测试没测试到位,在高并发数据量稍微大点的业务场景里面搞不好就出问题。数据库表phone字段用的字符串类型,但是这个SQL里面没有加上引号,所以像这种情况下,索引是无效的。

2.分页查询优化

select * from orderwhere oid=100 limit 100000,5000,这种普通limit M,N的翻页写法,在越往后翻页的过程中速度越慢,原因mysql会读取表中的前M+N条数据,M越大,性能就越差。像这种SQL如果只是平时查询看看记录,感觉不到异常,就算稍微慢点,也忍了,但是在我刚才说的业务场景里面,也会导致慢SQL查询积累。优化写法:select t1.* from order t1,(select id from order oid=100 limit 100000,5000) t2 where t1.id=t2.id,这种效率会高很好

3.分表

虽然做了上面的优化,执行效率比之前高了很多台阶,但是单表达的压力依然存在。订单表当时没有做分表,尽管目前的条件没有用分片集群,但是为解决燃眉之需也需要做物理分表(随着投放出去的摇摇车越来越多,当时每天订单大约1万到2万)。

SQL优化是一个长期的过程,最好是结合具体业务场景来做优化效率会更好一些,后面我会继续罗列在这个项目实战中出现的一些关于SQL的坑和做的相关优化。

时间: 2024-11-07 20:02:25

我的物联网项目(七)前期线上事故的相关文章

腾讯物联网操作系统TencentOS tiny线上移植大赛,王者机器人、QQ公仔、定制开发板等礼品等

一.产品介绍 TencentOS tiny是腾讯面向物联网领域开发的实时操作系统,具有低功耗,低资源占用,模块化,安全可靠等特点,可有效提升物联网终端产品开发效率.TencentOS tiny 提供精简的 RTOS 内核,内核组件可裁剪可配置,可快速移植到多种主流 MCU (如STM32全系列)及模组芯片上.而且,基于RTOS内核提供了丰富的物联网组件,内部集成主流物联网协议栈(如 CoAP/MQTT/TLS/DTLS/LoRaWAN/NB-IoT 等),可助力物联网终端设备及业务快速接入腾讯云

JVM系列(七) - JVM线上监控工具

前言 通过上一篇的 JVM 垃圾回收知识,我们了解了 JVM 具体的 垃圾回收算法 和几种 垃圾回收器.理论是指导实践的工具,有了理论指导,定位问题的时候,知识和经验是关键基础,数据可以为我们提供依据. 在线上我们经常会遇见如下几个问题: 内存泄露: 某个进程突然 CPU 飙升: 线程死锁: 响应变慢. 如果遇到了以上这种问题,在 线下环境 可以有各种 可视化的本地工具 支持查看.但是一旦到 线上环境,就没有这么多的 本地调试工具 支持,我们该如何基于 监控工具 来进行定位问题? 我们一般会基于

.NET Core项目----七牛云图片上传

在引用官方的qiniu.core的nuget是总是发生错误,错误如下,所以就在网上找到了一种解决方案,并稍微改进了一番, 以下是引用图: 第一步:引用nuget(是位大神写的,官方的qiniu.core用不了) 第二部:新建项目新建控制器视图.添加配置信息类和读取配置信息 配置信息类: public class QnySetting { public string qiniuyunAK { get; set; } public string qiniuyunSK { get; set; } pu

Vue.js项目实战-打造线上商城

首先上一下完成后的效果: 首页: 商品详情页: 购物车页(其实还有个订单页,只是和购物车页基本类似,所以就不截图啦): 开始项目: 由于涉及的是前后端分离,所以我们的后台数据就模拟存储于浏览器端(config/config.js里面): 当然在这之前你需要使用Vue CLI构建项目(),然后才可以进行下去,还有我们这各项目里面用了Font Awesome图标库 来使我们的项目的图标更加酷炫.读者可以使用cnpm install font-awesome --save-dev安装,具体的Font

Node.js项目线上服务器部署与发布

第1章 课程预热   1-1 为什么是全栈最后一公里   1-2 搭建线上生产环境需要做什么第2章 待部署的 5 个本地 Nodejs 项目   2-1 快速本地搭建一个纯静态简易站点   2-2 Nodejs 电影网站项目上线准备   2-3 狗狗说 React Native 开发的 App 后台项目分析   2-4 微信小程序的项目介绍   2-5 电影微信公众号的项目概况   2-6 从一个故事理解整个部署思路第3章 选购域名服务器及备案   3-1 选购域名的经验分享   3-2 主机厂

Node.js线上服务器部署与发布

第1章 课程预热对整个部署思路进行全流程介绍,通过 5 个不同类型项目,来演示从本地的仓库到最终线上稳定运行的整个项目部署发布流程,来帮助始终编程在一线的前端或者后端工程师,甚至是有 Coding 能力的产品经理,从操作流程和架构形态上,掌握从零开始的项目上线环节,掌握这关键一步,跨过去前端到后端,本地到线上,开发到生产...1-1 为什么是全栈最后一公里1-2 搭建线上生产环境需要做什么 第2章 待部署的 5 个本地 Nodejs 项目分别介绍五个技术架构和产品形态的项目背景,一个 Nodej

浅谈工业级物联网项目架构设计及实施

[说明]这是发表在<程序员>电子刊10月B架构专题文章 网页链接:http://www.csdn.net/article/2015-10-31/2826093 摘要:互联网+和物联网由于发展的侧重点不同,在做架构设计上肯定有所不同.而以中小项目为主的物联网项目,其实更看重的,一是系统稳定可靠,能保证系统长期稳定的运行.本文主要介绍工业级物联网项目的架构设计及实施. 前言 早在1999年就已经有了“物联网”这个概念,但是直到十年之后的2009年,IBM提出“智慧地球”的概念,才推动很多国家把物联

蚂蚁金服技术专家分享25个分布式缓存实践与线上案例

前言: 本文主要介绍使用分布式缓存的优秀实践和线上案例.这些案例是笔者在多家互联网公司里积累并形成的优秀实践,能够帮助大家在生产实践中避免很多不必要的生产事故. 一.缓存设计的核心要素 我们在应用中决定使用缓存时,通常需要进行详细的设计,因为设计缓存架构看似简单,实则不然,里面蕴含了很多深奥的原理,如果使用不当,则会造成很多生产事故甚至是服务雪崩之类的严重问题. 1.容量规划 缓存内容的大小缓存内容的数量淘汰策略缓存的数据结构每秒的读峰值每秒的写峰值2.性能优化 线程模型预热方法缓存分片冷热数据

手机线上决战万圣夜游戏APP开发步骤

时下广州龙其仕有一种手机线上决战万圣夜游戏APP和推币游戏是异常火热,广州龙其仕经过线上娃娃机的过渡期之后毅然选择开发直播推币机游戏,寻找一个突破口,前期市场目光敏锐的公司很早就已经把APP上架到各大应用市场,而且耗时很短,通过率也很可观. 不过经过一年的沉淀之后,随着越来越多的企业进驻这类马戏团推币游戏,上架对于他们来讲越来越难,多次提交还是被驳回,对于APP的发展出现很大的阻碍! 视频直播手机线上决战万圣夜游戏APP开发技术其实就是通过物联网技术实现智能控制线下设备技术,其本质是物联网APP