性能优化是个枯燥, 却又有趣的过程
性能优化我大致分为几个方面
代码优化
线程优化, 异步
JVM 优化
数据库优化
缓存优化
架构优化
下面来展开谈谈感悟, 也可以参考美团技术团队常见性能优化
代码优化
代码是跟我们接触最多的东西, 代码优化主要有
代码结构优化, 可以方便日后扩展和代码标准化
是否可以进行抽象避免冗余代码
是否可以利用设计模式
代码是否遵循阿里巴巴 Java 开发手册
这里可以采用阿里巴巴 Java 开发规范插件 https://github.com/alibaba/p3c
代码是否有多重循环, 无效的查询等
多重循环可以根据数据量采用 HashMap 进行查询, 属于利用空间换取时间
无效的查询等可以进行删除
这里推荐 Findbugs http://findbugs.sourceforge.net/
线程优化
线程优化是一个复杂的过程, 多线程如何运用, 如何避免死锁, 饥饿, 活锁等问题
线程使用的地方
在查询中可以运用到多线程, 把串行化操作变化为并行化操作
I/O 阻塞的操作, 最经典的莫过于 BIO
计算量大的操作, 使用多线程可以更好的运用 CPU 的运算能力
线程池
需要了解线程池的状态, 线程池的参数, 以及内部原理, 并选择合适的线程池
这里推荐一篇文章 Java 线程池实现原理及其在美团业务中的实践 再次感谢美团技术团队
线程池分为
- newCachedThreadPool
- newFixedThreadPool
- newSingleThreadExecutor
- newScheduleThreadPool
- forkjoinPool
注意: 这里不建议使用 Executors 来创建线程池, 方式 OOM 等问题, 参考阿里巴巴开发规范, 建议使用 new ThreadPoolExecutor()
异步
异步建议采用 MQ, 使用范围例如 insert,update 操作, 可以丢到 MQ, 这里要注意 MQ 消息丢失问题, 同时 MQ 也可以实现延迟队列, 例如 30 分钟关闭订单, 采用 Job 的方式并不是一个好的解决方案, 可以采用 MQ 延时队列实现, 这里推荐 rocketmq(阿里巴巴牛逼)
并发容器的选择
concurrenthashmap 和 synchronizedmap 性能差距很大, 建议选择合适的并发容器
JVM 优化
JVM 优化这里本人也不是特别的熟练, 只是讲一些自己所知道的
无日志不优化
在没有日志的情况下, 该怎么优化, 如何优化, 哪些方面需要优化, 这里都是未知的, 所以需要日志才能进行优化
工具
优化要有趁手的工具, 好在 JDK 本身就为我们提供了不少, 在 JDK 的 bin 目录下有一堆自带的工具, 这里介绍几个我熟悉且用过的
jps: 查看当前机器上的 java 程序
jcmd: 跟 jps 差不多但是能看到启动命令
jstat: 查看 JVM 信息, 例如 GC 信息
jinfo: 查看 JVM 参数
jmap:JVM 在内存中的情况, 可以导出 Dump
jstack: 栈信息, 可以用来查看死锁等
jconsole: 一个可视化工具
jvisualvm: 也是一个可视化工具比 jconsole 功能强一些, 但是都有局限性, 在服务器上无法使用
eclipse memory analyer: 分析 dump 文件
参数优化
使用上面的工具对服务器进行监控, 可以根据信息适当的调整堆大小, GC 收集器等. 建议开启 - XX:+HeapDumpOnOutOfMemoryError
数据库优化
数据库是优化中重要的一环, 具体优化方法如下
SQL 优化: 是否可以去掉不必要的查询, 使用 explain 对 sql 进行分析, 避免回表等
分库分表: 一台数据库可能存在性能瓶颈, 可以采用分库分表的方式, 拆分主要采用冷热数据分离, 日期分割, HASH 取模等.
读写分离: 对数据的修改可以操作主库, 对数据的查询可以操作从库, 进行读写分离
分库分表以及读写分离后可能会出现分布式事务, 读写分离操作的复杂性等问题这里需要引入中间件例如: MyCat http://www.mycat.io/ sharding jdbc
缓存优化
缓存是个优化的好办法但是也有弊端
缓存分类
JVM 缓存: concurrenthashmap,guava 缓存
Redis 等 NoSQL 数据库
缓存拆分
可以在代码中对接口进行拆分, 可以缓存的和不可以缓存的写成多个方法, 对可以缓存的进行缓存
缓存带来的弊端
缓存并不是越多越好, 缓存给系统带来了复杂性, 例如: 何时添加缓存, 何时删除缓存, 缓存雪崩, 缓存击穿, 缓存穿透, 缓存预热, Redis 集群如何实现, Redis 哨兵, Redis 脑裂等问题
架构优化
架构优化其实就程序员来说能做的并不是很多
限流: GateWay 进行限流, 限流方法有滑动窗口, 漏桶, 令牌桶算法, 这里建议采用合适的方法进行限流防止应用崩溃
熔断: 可以采用 hystrix 防止服务雪崩
CDN 优化: 对静态资源采用 CDN 可以提交响应速率
DNS 优化: 这个暂时不熟可以交给运维处理
服务扩容: 可以采用 K8S 和 Docker 的技术对服务进行动态扩容, 这里也是运维实现
测试
优化了这么多, 体现当然是压力测试, 这里因为不熟悉性能指标, 单机 TPS 部分接口可以达到 800+ RT 在 300ms 以内, 希望大家提供一个单机性能标准, 以上采用的是 LoadRuner 测试的结果
洋洋洒洒写了这么多, 主要的还是平时的积累以及思考, 也希望您对内容进行补充.
来源: https://www.cnblogs.com/ingxx/p/12776224.html