目录
一 合理设置网络超时时间
二 核心和非核心业务分离
三 合理配置tomcat线程数
四 代码中尽量不要出现重试
五 非必要依赖进行弱化处理
六 数据库事务精简
七 SQL性能优化要点
八 上线过程尽量做到平滑
九 限流、熔断、降级、排队处理异常流量
十 完善日志和监控功能
本文主要讲解,在高可用和高性能建设方面一些经验和总结。
1.1 什么叫网络调用超时时间呢?
如应用服务器之间、应用服务器与 redis 服务器之间、应用服务器与 mq 服务器之间的网络请求,这些网络请求一般有三个超时时间:
1.2 为什么需要设置超时时间?
由于系统的连接池或者线程池的资源是有限的,假设没有设置超时时间,由于下游服务慢或者下游服务异常,将会出现大量的线程在傻傻的等待下游服务返回,
一些正常的请求将等待或者被拒绝,服务响应变慢,吞吐率下降,QPS 变低,用户体验变差。这种情况是可以通过设置超时时间来避免的。
1.3 如何合理的设置超时时间?
简单的原则就是:socketTimeout, connectTimeout,connectRequestTimeout 3个超时时间,不要超过300ms,在系统能接受的情况下尽量短。
可以根据系统的99线来设置超时时间。所谓的99线,就是满足百分之九十九的网络请求所需要的最低耗时。简单点说,假设我们这块的有一个接口一天请求了1万次,
计算能保证9900次请求所需要的最低耗时就叫99线。具体计算可以参考这篇文章(https://blog.csdn.net/brucewong0516/article/details/80205422)。
redis 正常读写在2-3ms,超时时间需要设置更短,尽量不要超过 50ms。mq 的超时也是同样。
每一个公司都有核心业务和非核心业务,针对核心业务可以梳理出来核心链路,所谓的核心链路应该是公司最值钱的业务,在链路上核心业务只能调用核心业务,
非核心业务只能调用非核心业务。如果公司可以的话,实现核心业务双机房、甚至多机房部署。
合理配置线程数,比如 CPU 型密集型的可以配置少些,IO 密集型的可以配置多些。 具体可以参考这篇文章 (https://blog.csdn.net/jack1liu/article/details/100511226)。
如果没有什么特殊原因,请不要在代码中重试,重试尽量是业务重试,由上游业务人员进行重试操作。
为什么不要在代码中重试呢?
如果在代码中重试,这块很容易出现流量放大,平时1倍的量,如果重试5次,流量将是平时的5倍。很容易将服务打挂。
什么叫弱依赖化?
所谓的弱依赖化,就是对主流程影响较小的流程进行弱依赖。
如 mq/redis 在发生 timeout exception 时,如果不影响主要功能,需要 catch 异常,不要抛到上层。举例来说:
String value = redis.get(“key”);
if(value == null) {
value = dao.getOneColumn(“”);
}
}
如果没有catch弱依赖redis,在 redis 故障时,直接向上层抛出异常,无法从数据库读出数据。
mq 的容错除了catch 以外,需要考虑在 mq 不可用时,丢失的消息如何处理?比如改发 mq 为记录日志,后期再处理。
事务内的操作应当尽可能少,减少事务执行时间,绝对不能有 RPC 调用。
7.1 怎么定义慢SQL?
理论上用户侧 SQL 的执行应该在10ms内,超过50ms已经可以归为慢 SQL。
7.2 SQL查询数量限制多少合适?
比如 limit 限制不允许超过100或者200,in 的 id 限制也在100或者200。
7.3 如何查看新增的 SQL 没有问题呢?
使用 explain 可以查看 SQL 的执行计划。
给相关的查询字段添加索引,加快查询速度。
比如数据库迁移,方案设计和上线流程过程中一定要考虑到两个核心点:最大程度控制影响面、快速恢复。
如何最大程度控制影响面?
如何将功能快速恢复?
笔者就遇到过,因为异常流量导致服务暂不可用的问题,详情可以看(https://blog.csdn.net/jack1liu/article/details/112135898)。
当然了,针对服务中的异常流量也可以使用熔断、降级和排队技术。只要能解决问题,都是ok的。
我们应该打印合理且必要的日志数据。
10.1 什么叫合理且必要的日志呢?
能给我们排查业务问题、排查系统问题的日志都是合理且必要的。
10.2 为什么需要完善监控功能?
如果没有监控,我们会感觉我们的额服务其实在裸奔,假设出现了问题,监控能更快、更有效的帮助我们发现、复现、解决问题。