目录
背景描述
某项目现场,发现每天晚上服务会挂,不是OOM就是服务假死,拒绝连接请求。
1、OOM,直接看日志服务挂掉了
2、服务假死,看服务日志,日志还在正常打印,但是所有请求都被拒绝
项目背景: 以前在别的项目现场,数据中台,使用API服务对外提供接口之前,都是对数据进行加工处理之后,API只需要查询简单sql,不涉及复杂业务,而且接口有每次请求最多返回1w条的限制。
这个项目,在以前API服务做了定制。1、项目甲方,不会数据治理,不会对数据加工,API提供的服务是多个表多次联合查询的接口。2、项目甲方,把API服务接口当做数据同步工具,让我们去掉每次只返回1W条数据的限制。
问题以及解决
1、OOM问题
原因:查询日志,发现用户每页设置返回100w条数据,通过这个接口查询出的数据内存大小有12G,API服务总共就8G内存,直接OOM
解决:拿着有效证据,找甲方沟通,把每次接口请求最多1w条,加上。
2、假死
原因:单接口,用户自定义的查询sql,sql很慢,分钟级别。每个数据源,后端数据库线程池核心连接数只有10个,高并发情况,导致10个核心线程还没返回请求,后面的请求已经达到,导致服务假死
解决:1、接口返回时间,做15秒限制,超时直接报错
2、单接口并发做限制,每秒只接受5个请求
3、其实最核心的解决方案,是推动甲方使用数据中台的离线、实时、集成工具,对数据进行加工,再发布API,否则上面的都不能完全解决问题。
3、为什么是每天晚上挂?
原因:需要找甲方沟通,看看他们使用场景。他们把API当做数据同步工具
解决方案:需要找甲方沟通,推动他们使用中台其他工具。如果不使用,问题解决不了。
甲方还没同意,所以问题未解决。。。。
4、接口慢sql很多而且频繁调用怎么办?
用户写的自定义sql封装的接口,关联查询十几张大表,一个sql查询时间都是10秒以上。遇到这种情况怎么办?
方法:1、每个完整的sql,MD5生成唯一的码sqlId,弄一个表统计5秒以上的sql,如果下次sqlId出现,控制它的并发量,上一个结果没返回,下一个就不请求数据库,支持接口返回请等待
2、接口做限流,通过网关做限流,1秒钟只能限定多少个接口
3、接口做防重放,同一个接口参数,现在1分钟只能访问几次
问题解决
序号 | 方案 | 详情 |
1 | 接口限流 | 一个接口1秒只允许100个请求,别的请求直接拒绝 |
2 | 记录调用日志,定位慢sql | API接口详细记录调用日志信息,记录每一步的耗时,以及查询sql,便于问题排查。 |
3 | 设置接口超时时间 | 设置调用其他依赖的接口的响应时间 |
4 | 设置数据库执行最长时间 | 设置数据库查询的最长响应时间,这样可以避免把数据库连接数耗光 |
5 | 网关设置黑白名单 | 对于恶意访问,设置黑名单 |
6 | 服务调用和服务管理平台基础功能分离 | 服务调用和服务管理平台基础功能分成2个微服务,互相不干扰,发布服务跟服务调用互不影响 |
7 | 增加接口调用监控预警功能 | 监控接口的调用耗时,失败率,自动发送监控预警 |
总结
奇葩项目,说服不了甲方。那就只能保证自己服务不挂,做限流,做超时限制,做连接限制,做服务数据量限制。限制不轻易放开,API能提供高并发快速响应最终还是需要推动用户做数据治理、数据加工。