如何编写高质量的Java代码
作者:互联网
Java代码安全规范
本文目的
向Nasa的《NASA的10条代码编写原则》学习,目的有二:一是约束Java代码的使用、规避较高危的代码,二是code review更易识别。有很多优秀的JAVA规范、如《阿里巴巴JAVA开发手册》等都介绍了编码的一些原则、编程风格等,本文不再赘述;这里更多介绍生产环境易出故障的javacode。
提高生产环境系统的稳定性、可用性并非代码一项,需要有一套结构化的体系、从系统运营角度去通盘考虑;代码是系统基石之一。
故障分析
代码危险程度很难量化分析,从生产环境的故障着手分析。笔者统计了新美大近两年半对交易额有较大损失影响的线上S1故障(日交易额影响比大于5%),发现WEB服务影响最大的是DB、其次CACHE,还有些重复打款、zk重连、专线故障、前端轮询、内存不足、LOG问题等,比较共性的是:资源层级越底层、对交易额的损失越大。因此代码危险程度可以从代码对资源影响程度去衡量。
资源分析
Nasa的编写原则面向航空场景的C语言,与互联网WEB场景相比、1)服务远程通讯更少2)偏硬件打交道得多,对低能耗和安全的要求比较高,既非cpu密集型、也非io密集型 3)代码工程浩大。因此Nasa主要集中在mem及代码工程上。NASA规范总结有3条:限制内存动态分配、限制指针层级、优化C编译器做集成和静态检查。
互联网WEB场景,普通service属于cpu密集型,cpu及network资源容易出现瓶颈;而像mysql、redis等存储系统对碰盘i/o、cpu、network的要求都很高。JAVA耻笑自动档内存的C、JVM在解放程序猿对内存管理的同时,也因将内存管理交给了JVM、比C更容易出现不明所以的故障,当你越不了解它、也就越难真正驾驭它。本文主要针对JAVA互联网WEB、规范单机的三处资源:内存、CPU、网络。
本文分类的原则、是从java单机的视角去看待资源(cpu、mem、i/o、network),例如mysql的吐吞率大的sql归在Network资源方面。
安全条目
QPS
- JOB、MQ、RPC(写入场景及读QPS较高场景)需要限制请求QPS及响应队列,以便保护Write及Read资源。
- 论询导致后台QPS过大,QPS可能超出人预期的几倍、甚至上百倍;建议有专门的长链集群。
- 活动Push、大促、秒杀类活动导致后台QPS过大,后端服务容量常被打满、甚至压垮下游核心服务;建议有专门的活动运营机制隔离此类应用场景。
CPU
- Future、RPC、Redis、Http Connection、MySQL Connection等远程调用必需明确设置Network Timeout Time,防止造成线程积压、增加cpu负载。
- 大对象、 大集合的序列化耗时明显。几个思路:集合拆分与并行处理、byte代替明文存储、选择合适的序列化协议和框架。
Memory
- 禁止使用无界的List与Map集合、必须限制MaxSize,防止堆泄漏、FGC。
- Local Cache、Buffer(MQ、Log、Thrift)、Thread Local等必需明确限制MaxSzie,防止引发FullGC及OOM。(本质是无界集合、突出local cache&buffer的使用场景)
- 禁止使用自定义线程池、提供统一线程池解决方案(监控、分布式限流、动态调整线程池大小、回收thread local),防止应用线程池失去监管、带来潜在危害(在方法区动态创建thread pool属于常见错误之一)
- 在线程池的场景下使用Thread Local在回收前需要一个兜底清除的节制,防止线程复用Thread Local反复使用的风险
- 禁止JOB一次性全量操作、必须取一批、处理一批,防止引发潜在的堆溢出问题
- 慎用DirectBuffer、注意内存泄漏风险(Netty i/o线程及业务线程)XX:MaxDirectMemorySize=1g
- 慎用大对象,防止出现FGC、System Load过高、热点TPS过大
磁盘I/O
- 禁止线上应用出现swap,防止产生I/O中断、秒级GC等风险,JVM明确swap size。出现swap建议深入排查原因看是否需要更换物理机
Network
- 批量SQL必须Limit限制最大记录条数,防止产生Big Sql、影响MySQL连接数及吞吐率
- 大表操作场景。禁止大表Join、select count分页方式,慎用order by与where查询场景,避免产生慢SQL、拖累MySQL性能。分页可用id偏移的方式代替"limit n,m"。
- 不准Redis对象超过4KB,防止热点KeyValue TPS过高、引发性能问题
- 建议提供统一封装的HttpClient解决方案,防止连接池反复创建、未关闭连接、未设置超时时间、无访问链路监控等风险。
· 服务器TCP连接出现大量的TIME_WAIT、CLOSE_WAIT,占用大量fd、导致服务器不可用。优化思路大体是调整保活机制、快速回收,线上故障通过重启机器解决此类问题。
代码工程
- 不准单类超过1000行代码,防止功能模块耦合、带来不可预知的代码修改危害。
Web安全
OWASP TOP 10-2017(全球WEB安全10大安全问题排行榜):
- A1-Injection
- A2-Broken Authentication and Session Management
- A3-Cross-Site Scripting (XSS)
- A4-Broken Access Control
- A5-Security Misconfiguration
- A6-Sensitive Data Exposure
- A7-Insufficient Attack Protection
- A8-Cross-Site Request Forgery (CSRF)
- A9-Using Components with Known Vulnerabilities
- A10-Underprotected APIs
更多细节请详细访问:https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project
附录
Redis网卡打满参照表
当热点key的QPS超过一定阈值会出现网卡打满的情况。现在redis集群是万兆网卡(10000Mbps),对照表如下:
传输对象平均大小 |
打满万兆网卡的qps |
打满千兆网卡的qps |
备注 |
1KB |
128w/s |
12.8w/s |
|
2KB |
64w/s |
6.4w/s |
|
4KB |
32w/s |
4.2w/s |
|
8KB |
16w/s |
1.6w/s |
|
16KB |
8w/s |
8k/s |
|
32KB |
4w/s |
4k/s |
|
64KB |
2w/s |
2k/s |
|
128KB |
1w/s |
1k/s |
|
256KB |
5k/s |
500/s |
|
512KB |
2.5k/s |
250/s |
|
将cache的大小限制在8k以下会比较安全一些。
参考
https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project
https://blog.octo.com/en/the-evolution-of-bottlenecks-in-the-big-data-ecosystem/
https://github.com/eishay/jvm-serializers/wiki
http://www.cnblogs.com/sunxucool/p/3449068.html
国家级软件工程 发布了91 篇原创文章 · 获赞 7 · 访问量 12万+ 私信 关注标签:场景,Java,代码,高质量,网卡,线程,编写,QPS,打满 来源: https://blog.csdn.net/Ture010Love/article/details/77618623