关于 Java Web 项目性能提升的一些思路

本贴最后更新于 2699 天前,其中的信息可能已经时移世易
  • 使用 Nginx 作为前端接入

    用 Nginx 进行动静分离。这个不用多讲,新浪、网易、淘宝、腾讯等巨头的使用已经说明了一切。
    
  • 保持最简单的架构

    遵守 KISS 原则(Keep it simple and stupid)。尽量不要考虑项目外的重用。过多的考虑项目外的重用,必然会增加项目的复杂度。避免过度集成,让每个模块只做自己的事,这对于日后的维护和模块复用都有好处。
    
  • 精心设计缓存处理、毫不吝啬代码(对象、列表、片段)

    对于门户网站的首页来说,往往可能会有近百个 SQL。用户并发上去以后,光首页就足以让服务器 down 掉。缓存不但有利于降低负载,而且还能提高响应速度。
    
  • 调整使用聚集索引

    对于每个表来讲,聚集索引只有一个,利用好了,查询速度会有意想不到的提升效果。
    以 MySql 为例,InnoDB选取聚集索引参照列的顺序是
            1\. 如果声声明了主键(primary key),则这个列会被做为聚集索引;
            2\. 如果没有声明主键,则会用一个唯一且不为空的索引列做为主键,成为此表的聚集索引;
            3\. 上面二个条件都不满足,InnoDB会自己产生一个虚拟的聚集索引。
    
  1. CREATE TABLE timeline_raw (
  2. rawId bigint(20) NOT NULL AUTO_INCREMENT,
  3. uid bigint(20) DEFAULT NULL,
  4. did bigint(20) DEFAULT NULL,
  5. channelId char(1) NOT NULL DEFAULT '1' COMMENT '1:qvga; 2:720p',
  6. fileId bigint(20) DEFAULT NULL,
  7. sectionId bigint(20) DEFAULT NULL,
  8. headerFilePath varchar(120) DEFAULT NULL,
  9. startTime bigint(20) DEFAULT NULL,
  10. endTime bigint(20) DEFAULT NULL,
  11. updateTime datetime DEFAULT NULL,
  12. createTime datetime DEFAULT NULL,
  13. PRIMARY KEY (rawId),
  14. KEY index_uid_did_startTime (uid,did,startTime) USING BTREE,
  15. KEY index_uid_did_endTime (uid,did,endTime) USING BTREE,
  16. KEY index_time (startTime) USING BTREE,
  17. KEY index_uid_did_fileId (uid,did,sectionId) USING BTREE,
  18. KEY index_sectionId (sectionId)
  19. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

这个表有四个索引:主键 rawId、sectionId、uid,did、startTime。
项目的 iBatis2 中有这样一条查询语句:

  1. <selectid="getRawFileList" parameterClass="java.util.HashMap" resultClass="com.defonds.mysql.raw.entity.TimelineRaw">

  2.  SELECT * FROM timeline_raw_  
    
  3.  WHERE uid=#uid#   
    
  4.  AND did=#did#   
    
  5.  AND channelId=#channelId#  
    
  6.  < isNotNull  property="sectionId"> AND sectionId = #sectionId# < isNotNull>  
    
  7.  AND   
    
  8.  (  
    
  9.          (startTime BETWEEN #startTime# and #endTime#)   
    
  10.              OR   
    
  11.          (endTime BETWEEN #startTime# and #endTime#)  
    
  12.                                      OR  
    
  13.       (  
    
  14.       startTime<=#startTime#  
    
  15.        ]]>   
    
  16.       AND   
    
  17.       endTime>=#endTime# 
    
  18.       ]]>   
    
  19.       )  
    
  20.  )  
    
  21.  ORDER BY startTime;   
    
  22. select>

    根据实际业务向 timeline_raw 表注入一千万条数据,进行模拟测试,发现 getRawFileList 的执行平均时间为 160 ms 以上。这是不能接受的。
    考虑到实际业务中对于主键 rawId 查询条件甚少,我们把 rawId 主键索引取消掉,改为唯一约束,却把 sectionId+startTime+endTime 作为主键(业务上能够保证其唯一性,根据 InnoDB 索引规则,这个索引将成为我们新表的聚集索引)。然后把 sectionId、startTime 两个索引也取消掉,仅保留 uid,did 索引。
    这样子,我们新表的索引实际上只有两个了:一个聚集索引(sectionId+startTime+endTime)一个非聚集索引(uid,did)。
    再次进行模拟测试,同样的数据、数据量,同样的查询结果集,getRawFileList 执行平均时间已经降到了 11 ms。结果是令人振奋的,不是么?

  • 使用 /dev/shm 来存储缓存的磁盘文件

    在网站运维中,利用好了这一点,往往有意想不到的收获。以 tomcat 为例,可以通过修改 catalina.sh 中的 CATALINA_TMPDIR 值的路径来将缓存设置为 /dev/shm。
    以 OSC 为例,他们就是纯 Java 写的,部署在 tomcat 下。在长时间的在线运行之后,管理员发现网站响应速度奇慢,服务器负载正常,又找不出是哪里的问题。后来 df 一下,发现 tomcat 临时目录下的文件足足有 8G 之多,原来是 CPU 等待磁盘操作造成响应速度加长。于是他们将临时目录映射到 /dev/shm,网站响应速度从此奇快。
    
  • 分析系统中每一个 SQL 的执行效率

    以 MySql 为例,对于每个 SQL 最好都 explain 一下。对于有明显效率问题的,通过 sql 优化、调索引等方法进行改进。
    
  • 健康慢查询日志,检查所有执行超过 100 毫秒的 SQL

    对于上线了的项目,健康慢查询日志,检查所有执行超过 100 毫秒的 SQL,看看有没有优化余地。对于没有上线的项目,可以进行场景模拟对嫌疑 SQL,或者对频繁使用的 SQL 进行性能测试,统计它们执行时间,得出平均值,画出曲线分析图,对于单表千万数据,执行时间超过 50ms 的 SQL 要重点关注。参考《[sql 性能测试例子](http://blog.csdn.net/defonds/article/details/16832081)》。
    
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3169 引用 • 8208 回帖
  • Web
    115 引用 • 432 回帖 • 8 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • eddy

    学习了

  • hanson08

    很受用!!!

推荐标签 标签

  • 面试

    面试造航母,上班拧螺丝。多面试,少加班。

    324 引用 • 1395 回帖
  • ZeroNet

    ZeroNet 是一个基于比特币加密技术和 BT 网络技术的去中心化的、开放开源的网络和交流系统。

    1 引用 • 21 回帖 • 609 关注
  • WebComponents

    Web Components 是 W3C 定义的标准,它给了前端开发者扩展浏览器标签的能力,可以方便地定制可复用组件,更好的进行模块化开发,解放了前端开发者的生产力。

    1 引用 • 4 关注
  • 安装

    你若安好,便是晴天。

    131 引用 • 1184 回帖
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    536 引用 • 672 回帖
  • 负能量

    上帝为你关上了一扇门,然后就去睡觉了....努力不一定能成功,但不努力一定很轻松 (° ー °〃)

    88 引用 • 1234 回帖 • 442 关注
  • IBM

    IBM(国际商业机器公司)或万国商业机器公司,简称 IBM(International Business Machines Corporation),总公司在纽约州阿蒙克市。1911 年托马斯·沃森创立于美国,是全球最大的信息技术和业务解决方案公司,拥有全球雇员 30 多万人,业务遍及 160 多个国家和地区。

    16 引用 • 53 回帖 • 131 关注
  • Latke

    Latke 是一款以 JSON 为主的 Java Web 框架。

    70 引用 • 533 回帖 • 735 关注
  • SEO

    发布对别人有帮助的原创内容是最好的 SEO 方式。

    35 引用 • 200 回帖 • 30 关注
  • 分享

    有什么新发现就分享给大家吧!

    245 引用 • 1776 回帖
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    106 引用 • 152 回帖
  • 创造

    你创造的作品可能会帮助到很多人,如果是开源项目的话就更赞了!

    175 引用 • 994 回帖
  • frp

    frp 是一个可用于内网穿透的高性能的反向代理应用,支持 TCP、UDP、 HTTP 和 HTTPS 协议。

    16 引用 • 7 回帖 • 1 关注
  • FreeMarker

    FreeMarker 是一款好用且功能强大的 Java 模版引擎。

    23 引用 • 20 回帖 • 429 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3169 引用 • 8208 回帖
  • Logseq

    Logseq 是一个隐私优先、开源的知识库工具。

    Logseq is a joyful, open-source outliner that works on top of local plain-text Markdown and Org-mode files. Use it to write, organize and share your thoughts, keep your to-do list, and build your own digital garden.

    5 引用 • 62 回帖
  • VirtualBox

    VirtualBox 是一款开源虚拟机软件,最早由德国 Innotek 公司开发,由 Sun Microsystems 公司出品的软件,使用 Qt 编写,在 Sun 被 Oracle 收购后正式更名成 Oracle VM VirtualBox。

    10 引用 • 2 回帖 • 7 关注
  • NetBeans

    NetBeans 是一个始于 1997 年的 Xelfi 计划,本身是捷克布拉格查理大学的数学及物理学院的学生计划。此计划延伸而成立了一家公司进而发展这个商用版本的 NetBeans IDE,直到 1999 年 Sun 买下此公司。Sun 于次年(2000 年)六月将 NetBeans IDE 开源,直到现在 NetBeans 的社群依然持续增长。

    78 引用 • 102 回帖 • 646 关注
  • ZooKeeper

    ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 HBase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

    59 引用 • 29 回帖 • 9 关注
  • 百度

    百度(Nasdaq:BIDU)是全球最大的中文搜索引擎、最大的中文网站。2000 年 1 月由李彦宏创立于北京中关村,致力于向人们提供“简单,可依赖”的信息获取方式。“百度”二字源于中国宋朝词人辛弃疾的《青玉案·元夕》词句“众里寻他千百度”,象征着百度对中文信息检索技术的执著追求。

    63 引用 • 785 回帖 • 237 关注
  • Netty

    Netty 是一个基于 NIO 的客户端-服务器编程框架,使用 Netty 可以让你快速、简单地开发出一个可维护、高性能的网络应用,例如实现了某种协议的客户、服务端应用。

    49 引用 • 33 回帖 • 20 关注
  • HBase

    HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统”。就像 Bigtable 利用了 Google 文件系统所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。

    17 引用 • 6 回帖 • 60 关注
  • 创业

    你比 99% 的人都优秀么?

    83 引用 • 1398 回帖
  • 持续集成

    持续集成(Continuous Integration)是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。

    14 引用 • 7 回帖 • 4 关注
  • Markdown

    Markdown 是一种轻量级标记语言,用户可使用纯文本编辑器来排版文档,最终通过 Markdown 引擎将文档转换为所需格式(比如 HTML、PDF 等)。

    165 引用 • 1474 回帖
  • 正则表达式

    正则表达式(Regular Expression)使用单个字符串来描述、匹配一系列遵循某个句法规则的字符串。

    31 引用 • 94 回帖 • 2 关注
  • 又拍云

    又拍云是国内领先的 CDN 服务提供商,国家工信部认证通过的“可信云”,乌云众测平台认证的“安全云”,为移动时代的创业者提供新一代的 CDN 加速服务。

    21 引用 • 37 回帖 • 523 关注