Java开发高性能网站需要关注的事

 

转自:http://www.javabloger.com/java-development-concern-those-things/

 

近期各家IT媒体举办的业内技术大会让很多网站都在披露自己的技术内幕与同行们分享,大到facebook,百度,小到刚起步的网站。facebook,百度之类的大型网站采用的技术和超凡的处理能力的确给人耳目一新的感觉,但并不是每个网站都是像facebook,百度 有上亿的用户访问流量,有海量的数据需要存储,需要使用到mapreduce/并行计算,HBase/列存储这些技术不可。技术手段始终是运营的支撑,对于当前的运营环境适用就好,没有必要非要赶个时髦,一定要和某项流行的技术产生点关系才善罢甘休。

在最近的技术大会中我们更多的目光都聚焦在这些大型网站,其实中小型门户网站的技术体系也是值得去探讨和关注。全天下的攻城师们并不是都在为这些大型门户网站服务,更多的攻城师们正在默默无闻的为一些刚刚起步的中小型网站服务,而且占据了攻城师队伍中的60%以上的人群。在关注大型门户网站的时候,中小型门户网站的技术发展和实战经验更值得去分享。

无论大型门户网站还是中小型垂直类型网站都会对稳定性、性能和可伸缩性有所追求。大型网站的技术经验分享值得我们去学习和借用,但落实到更具体的实践上并不是对所有网站可以适用,其他语言开发的网站我还不敢多说,但Java开发的系统,我还是能您给插上几句话:

JVM
JEE容器中运行的JVM参数配置参数的正确使用直接关系到整个系统的性能和处理能力,JVM的调优主要是对内存管理方面的调优,优化的方向分为以下4点:
1.HeapSize             堆的大小,也可以说Java虚拟机使用内存的策略,这点是非常关键的。
2.GarbageCollector  通过配置相关的参数进行Java中的垃圾收集器的4个算法(策略)进行使用。
3.StackSize             栈是JVM的内存指令区,每个线程都有他自己的Stack,Stack的大小限制着线程的数量。
4.DeBug/Log           在JVM中还可以设置对JVM运行时的日志和JVM挂掉后的日志输出,这点非常的关键,根据各类JVM的日志输出才能配置合适的参数。
网上随处可见JVM的配置技巧,但是我还是推荐阅读Sun官方的2篇文章,可以对配置参数的其所依然有一个了解
1.Java HotSpot VM Options
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
2.Troubleshooting Guide for Java SE 6 with HotSpot VMhttp://www.oracle.com/technetwork/java/javase/index-137495.html
另外,我相信不是每个人攻城师都是天天对着这些JVM参数的,如果你忘记了那些关键的参数你可以输入Java -X(大写X)进行提示。

JDBC
针对MySQL的JDBC的参数在之前的文章中也有介绍过,在单台机器或者集群的环境下合理的使用JDBC中的配置参数对操作数据库也有很大的影响。
一些所谓高性能的 Java ORM开源框架也就是打开了很多JDBC中的默认参数:
1.例如:autoReconnect、prepStmtCacheSize、cachePrepStmts、useNewIO、blobSendChunkSize 等,
2.例如集群环境下:roundRobinLoadBalance、failOverReadOnly、autoReconnectForPools、secondsBeforeRetryMaster。
具体内容可以参阅MySQL的JDBC官方使用手册:
http://dev.mysql.com/doc/refman/5.1/zh/connectors.html#cj-jdbc-reference

数据库连接池(DataSource)
应用程序与数据库连接频繁的交互会给系统带来瓶颈和大量的开销会影响到系统的性能,JDBC连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而再不是重新建立一个连接,因此应用程序不需要频繁的与数据库开关连接,并且可以释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。
在此我认为有一点需要说明:
连接池的使用也是需要关闭,因为在数据库连接池启动的时候就预先和数据库获得了相应的连接,之后不再需要应用程序直接的和数据库打交道,因为应用程序使用数据库连接池是一个“借”的概念,应用程序从数据库连接池中获得资源是“借出”,还需要还回去,就好比有20个水桶放在这里,需要拿水的人都可以使用这些木桶从水池里面拿水,如果20个人都拿完水,不将水桶还回原地,那么后面来的人再需要拿水,只能在旁边等待有人将木桶还回去,之前的人用完后需要放回去,不然后面的人就会一直等待,造成资源堵塞,同理,应用程序获取数据库连接的时候Connection连接对象的时候是从“池”中分配一个数据库连接出去,在使用完毕后,归还这个数据库连接,这样才能保持数据库的连接“有借有还”准则。
参考资料:
http://dev.mysql.com/doc/refman/5.1/zh/connectors.html#cj-connection-pooling

数据存取
数据库服务器的优化和数据的存取,什么类型的数据放在什么地方更好是值得去思考的问题,将来的存储很可能是混用的,Cache,NOSQL,DFS,DataBase 在一个系统中都会有,生活的餐具和平日里穿衣服需要摆放在家里,但是不会用同一种类型的家具存放,貌似没有那个人家把餐具和衣服放在同一个柜子里面的。这就像是系统中不同类型的数据一样,对不同类型的数据需要使用合适的存储环境。文件和图片的存储,首先按照访问的热度分类,或者按照文件的大小。强关系类型并且需要事务支持的采用传统的数据库,弱关系型不需要事务支持的可以考虑NOSQL,海量文件存储可以考虑一下支持网络存储的DFS,至于缓存要看你单个数据存储的大小和读写的比例。
还有一点值得注意就是数据读写分离,无论在DataBase还是NOSQL的环境中大部分都是读大于写,因此在设计时还需考虑 不仅仅需要让数据的读分散在多台机器上,还需要考虑多台机器之间的数据一致性,MySQL的一主多从,在加上MySQL-Proxy或者借用JDBC中的一些参数(roundRobinLoadBalance、failOverReadOnly、autoReconnectForPools、secondsBeforeRetryMaster)对后续应用程序开发,可以将读和写分离,将大量读的压力分散在多台机器上,并且还保证了数据的一致性。

缓存
在宏观上看缓存一般分为2种:本地缓存和分布式缓存
1.本地缓存,对于Java的本地缓存而言就是讲数据放入静态(static)的数据结合中,然后需要用的时候就从静态数据结合中拿出来,对于高并发的环境建议使用 ConcurrentHashMap或者CopyOnWriteArrayList作为本地缓存。缓存的使用更具体点说就是对系统内存的使用,使用多少内存的资源需要有一个适当比例,如果超过适当的使用存储访问,将会适得其反,导致整个系统的运行效率低下。
2. 分布式缓存,一般用于分布式的环境,将每台机器上的缓存进行集中化的存储,并且不仅仅用于缓存的使用范畴,还可以作为分布式系统数据同步/传输的一种手段,一般被使用最多的就是Memcached和Redis。
数据存储在不同的介质上读/写得到的效率是不同的,在系统中如何善用缓存,让你的数据更靠近cpu,下面有一张图你需要永远牢记在心里,来自Google的技术大牛Jeff Dean(Ref)的杰作,如图所示:
cache-speed
并发/多线程
在高并发环境下建议开发者使用JDK中自带的并发包(java.util.concurrent),在JDK1.5以后使用java.util.concurrent下的工具类可以简化多线程开发,在java.util.concurrent的工具中主要分为以下几个主要部分:
1.线程池,线程池的接口(Executor、ExecutorService)与实现类(ThreadPoolExecutor、 ScheduledThreadPoolExecutor),利用jdk自带的线程池框架可以管理任务的排队和安排,并允许受控制的关闭。因为运行一个线程需要消耗系统CPU资源,而创建、结束一个线程也对系统CPU资源有开销,使用线程池不仅仅可以有效的管理多线程的使用,还是可以提高线程的运行效率。
2.本地队列,提供了高效的、可伸缩的、线程安全的非阻塞 FIFO 队列。java.util.concurrent 中的五个实现都支持扩展的 BlockingQueue 接口,该接口定义了 put 和 take 的阻塞版本:LinkedBlockingQueue、ArrayBlockingQueue、SynchronousQueue、PriorityBlockingQueue 和 DelayQueue。这些不同的类覆盖了生产者-使用者、消息传递、并行任务执行和相关并发设计的大多数常见使用的上下文。
3.同步器,四个类可协助实现常见的专用同步语句。Semaphore 是一个经典的并发工具。CountDownLatch 是一个极其简单但又极其常用的实用工具,用于在保持给定数目的信号、事件或条件前阻塞执行。CyclicBarrier 是一个可重置的多路同步点,在某些并行编程风格中很有用。Exchanger 允许两个线程在 collection 点交换对象,它在多流水线设计中是有用的。
4.并发包 Collection,此包还提供了设计用于多线程上下文中的 Collection 实现:ConcurrentHashMap、ConcurrentSkipListMap、ConcurrentSkipListSet、CopyOnWriteArrayList 和 CopyOnWriteArraySet。当期望许多线程访问一个给定 collection 时,ConcurrentHashMap 通常优于同步的 HashMap,ConcurrentSkipListMap 通常优于同步的 TreeMap。当期望的读数和遍历远远大于列表的更新数时,CopyOnWriteArrayList 优于同步的 ArrayList。

队列
关于队列可以分为:本地的队列 和 分布式队列 2类
本地队列:一般常见的用于非及时性的数据批量写入,可以将获取的数据缓存在一个数组中等达到一定数量的时候在进行批量的一次写入,可以使用BlockingQueue或者List/Map来实现。
相关资料:Sun Java API.
分布式队列:一般作为消息中间件,构建分布式环境下子系统与子系统之间通信的桥梁,JEE环境中使用最多的就是Apache的AvtiveMQ和Sun公司的OpenMQ。
轻量级的MQ中间件之前也向大家介绍过一些例如:Kestrel和Redis(Ref http://www.javabloger.com/article/mq-kestrel-redis-for-java.html),最近又听说LinkedIn的搜索技术团队推出了一个MQ产品-kaukaf(Ref http://sna-projects.com/kafka ),对此保持关注。
相关资料:
1.ActiveMQ http://activemq.apache.org/getting-started.html
2.OpenMQ  http://mq.java.net/about.html
3.Kafka       http://sna-projects.com/kafka      
4.JMS文章  http://www.javabloger.com/article/category/jms

NIO
NIO是在JDK1.4后的版本中出现的,在Java 1.4之前,Jdk提供的都是面向流的I/O系统,例如读/写文件则是一次一个字节地处理数据,一个输入流产生一个字节的数据,一个输出流消费一个字节的数据, 面向流的I/O速度非常慢,并且一个数据包要么整个数据报已经收到,要么还没有。Java NIO非堵塞技术实际是采取Reactor模式,有内容进来会自动通知,不必死等、死循环,大大的提升了系统性能。在现实场景中NIO技术多数运用两个方面,1是文件的读写操作,2是网络上数据流的操作。在NIO中有几个核心对象需要掌握:1选择器(Selector)、2通道(Channel)、3缓冲区(Buffer)。
我的废话:
1.在Java NIO的技术范畴中内存映射文件是一种高效的做法,可以用于缓存中存储的冷/热数据分离,将缓存中的一部分冷数据进行这样的处理,这种做法上比常规的基于流或者基于通道的I/O快的多,通过使文件中的数据出现为内存数组的内容来完成的,将文件中实际读取或者写入的部分才会映射到内存中,并不是将整个文件读到内存中。
2.在Mysql的jdbc驱动中也可以使用NIO技术对数据库进行操作来提升系统的性能。

长连接/Servlet3.0
这里说的长连接就是长轮询,以前浏览器(客户端)需要关注服务器端发生的数据变化需要不断的访问服务器,这样客户端的数量一多必然会给服务器端造成很大的压力,例如:论坛中的站内消息。现在Servlet3.0规范中提供了一个新的特性:异步IO通信;该特性会保持一个长连接。利用Servlet3异步请求的这项技术可以大大的缓解服务器端的压力。
Servlet3.0的原理就是将request的请求开启一个线程挂起,中间设置等待超时的时间,如果后台事件触发request请求,得到的结果返回给客户端的request请求,如果在设置等待超时的时间内没有任何事件发生也将请求返回给客户端,客户端将再次发起request请求,客户端与服务器端的交互可以与此往复。
就好比,你先过来跟我说如果有人找你,我就立马通知你你来见他,原先你需要不断的问我有没有要找你,而不管有没有人找你,你都需要不断的问我有没有人找你,这样的话不论问的人还是被问的人都会累死。

日志
Log4J是通常被人们使用的工具,系统在刚刚上线的时候日志一般都设置在INFO的级,真正上线后一般设置在ERROR级,但无论在任何时候,日志的输入内容都是需要关注的,开发人员一般可以依靠输出的日志查找出现的问题或者依靠输出的日志对系统的性能进行优化,日志也是系统运行状态的报告和排错的依据。
简单来说日志按照定义的不同策略和等级输出到不同的环境,那样便于我们分析和管理。相反你没有策略的输出,那么机器一多,时间一长,会有一大推乱糟糟的日志,会让你排错的时候无从下手,所以日志的输出策略是使用日志的关键点。
参考资料:http://logging.apache.org/log4j/1.2/manual.html

打包/部署
在代码设计的时候最好能将不同类型的功能模块在IDE环境中粗粒度的分为不同的工程,便于打成不同jar包部署在不同的环境中。有这样的一个应用场景:需要每天定时远程从SP那边获得当天100条新闻和部分城市的天气预报,虽然每天的数据量不多,但是前端访问的并发量很大,显然需要在系统架构上做到读写分离。
如果把web工程和定时抓取的功能模块完全集中在一个工程里打包,将导致需要扩展的时候每台机器上既有web应用也有定时器,因为功能模块没有分开,每台机器上都有定时器工作将会造成数据库里面的数据重复。
如果开发的时候就将web和定时器分为2个工程,打包的时候就可以分开部署,10台web对应一台定期器,分解了前端请求的压力,数据的写入也不会重复。
这样做的另一个好处就是可以共用,在上述的场景中web和定时器都需要对数据库进行读取,那么web和定时器的工程里都有操作数据库的代码,在代码的逻辑上还是感觉乱乱的。如果再抽出一个DAL层的jar,web和定时器的应用模块开发者只需要引用DAL层的jar,开发相关的业务逻辑,面向接口编程,无需考虑具体的数据库操作,具体的对数据库操作由其他开发者完成,可以在开发任务分工上很明确,并且互不干涉。

框架
所谓流行的SSH(Struts/Spring/Hiberanet)轻量级框架,对于很多中小型项目而言一点都不轻量级,开发者不仅需要维护代码,还需要维护繁琐的xml配置文件,而且说不定某个配置文件写的不对就让整个都工程无法运行。无配置文件可以取代SSH(struts/Spring/Hiberanet)框架的产品真的太多了,我之前就向大家介绍过一些个产品(Ref)。
这个我并不是一味的反对使用SSH(Struts/Spring/Hiberanet)框架,在我眼里SSH框架真的作用是做到了规范开发,而并不使用了SSH(Struts/Spring/Hiberanet)框架能提高多少性能。
SSH框架只是对于非常大的项目人数上百人的团队,还需要、继续增加团队规模的公司而言,是需要选择一些市面上大家都认可,并且熟悉的技术,SSH(Struts/Spring/Hiberanet)框架比较成熟所以是首先产品。
但是对于一些小团队中间有个把技术高人的团队而言完全可以选择更加简洁的框架,真正的做到提速你的开发效率,早日抛弃SSH框架选择更简洁的技术在小团队开发中是一种比较明知的选择。

转载于:https://www.cnblogs.com/HigginCui/p/6610384.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372587.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

并发–顺序线程和原始线程

我不久前参与了一个项目,该项目的报告流程如下: 用户会要求举报 报告要求将被翻译成较小的部分 每个零件的报告将基于零件/节的类型由报告生成器生成 组成报告的各个部分将重新组合成最终报告,并返回给用户 我的目标是展示如何从错误的实…

linux夏令时配置文件,Linux夏令时是怎么调整的?

以法国巴黎为例:root121 zoneinfo]# ln -s /usr/share/zoneinfo/Europe/Paris /etc/localtime[root121 zoneinfo]# date2015年 10月 13日 星期二 03:45:09 CEST[root121 zoneinfo]# date -RTue, 13 Oct 2015 03:45:31 0200[root121 zoneinfo]# zdump -v /etc/localt…

Kali Linux渗透基础知识整理(二)漏洞扫描

Kali Linux渗透基础知识整理系列文章回顾 漏洞扫描 网络流量NmapHping3NessuswhatwebDirBusterjoomscanWPScan网络流量 网络流量就是网络上传输的数据量。 TCP协议 TCP是因特网中的传输层协议,使用三次握手协议建立连接。当主动方发出SYN连接请求后,等待…

嵌入式软件设计第09实验报告

学号:140201133 姓名:李宇昕 组别:第3组 实验地点:D19 一、实验目的: 1.熟悉WWW技术中的SSI(Server Side Include)技术。 2.学会使用SSI技术编写代码把当前开发板内…

TeamCity工件:HTTP,Ant,Gradle和Maven

您可以通过几种方式检索TeamCity工件? 我说有很多选择 ! 如果您使用的是Java构建工具,那么可以使用简单的HTTP请求,Ant Ivy,Gradle和Maven下载和使用TeamCity构建配置生成的二进制文件。 怎么样? 继续阅读…

AutoCAD如何方便截图放到Word文档,改成白底黑字

将模型视图切换到布局2即可 比如下图所示的效果 先回到模型视图把所有线条颜色都改成白色,然后添加适当的标注(比如要受力分析,则在CAD中绘制箭头也很方便的),文字说明。然后切换到布局2就OK 可以截图了。 转载于:http…

iOS--支付宝环境集成

1.下载支付宝SDK以及Demo https://doc.open.alipay.com/doc2/detail?treeId54&articleId103419&docType1 2.新建文件夹“AliSDK”,将压缩包内的文件拷贝到该文件夹下,完成后如下图所示: 3.将文件夹拷贝到项目中, 4.执行完…

Java EE 6测试第二部分– Arquillian和ShrinkWrap简介

在Java EE 6测试的第一部分中,我简要介绍了使用Glassfish嵌入式容器的EJB 3.1 Embeddable API,以演示如何启动该容器,如何在项目类路径中查找bean以及运行非常简单的集成测试。 这篇文章重点介绍Arquillian和ShrinkWrap以及为什么它们是用于企…

【腾讯Bugly干货分享】Android内存优化总结实践

本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/2MsEAR9pQfMr1Sfs7cPdWQ 导语 智能手机发展到今天已经有十几个年头,手机的软硬件都已经发…

令人印象深刻的第一个Apache Camel版本

为了准备下周的CamelOne会议,我花了一些时间回顾一下Apache Camel项目的历史。 因此,除其他外,我了解了Apache Camel的第一个正式1.0版本 。 Apache Camel 1.0 – 5年前 我看的越多,这个版本的事实给我留下了深刻的印象。 现在您…

为什么在2012/2013年我将在新的Enterprise Java项目中继续使用Spring *和* Java EE

自从我担任技术决策职务以来已经过去了一年多,很高兴看到我仍然与之保持着完美的和谐。 几个月前,我在KaiWhner的一个不错的博客中写了一个有关JEE与Spring的答案。 如果观点没有不同,那么讨论的附加值在哪里? 我确实同意Kai的许多…

linux ubuntu 五笔输入法,ubuntu下安装fcitx五笔输入法

安装fcitx输入法sudo add-apt-repository ppa:fcitx-team/stable #添加安装源,apt-get 添加,nightly源也可以sudo apt-get update #更新源,否则无法安装fcit…

浅谈Windows下SVN在Android Studio中的配置、基本使用及解除关联

看到网上很多关于svn环境配置和关联Android-Studio的很多博文,发现很零散,想集大家所长整理一下: 在AndroidStudio中开发版本控制中,除了Git就是SVN,和Eclipse不同Android Studio没有提供单独的插件,只能和…

四. 基于环视Camera的BEV感知算法-BEVDepth

目录 前言0. 简述1. 算法动机&开创性思路2. 主体结构3. 损失函数4. 性能对比总结下载链接参考 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》,链接。记录下个人学习笔记,仅供自己参考 本次课程我们来学习下课程第四章——基于环视Cam…

【腾讯Bugly干货分享】Android Patch 方案与持续交付

本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57a31921ac3a1fb613dd40f3 Android 不仅系统版本众多,机型众多,而且各个市场都各有各的政策和审核速度&#xff0…

App Engine中的Google Services身份验证,第1部分

这篇文章将说明如何构建一个简单的Google App Engine(GAE)Java应用程序,该应用程序可针对Google进行身份验证,并利用Google的OAuth授权访问Google的API服务(例如Google Docs)。 此外,在Google已…

山东自考c语言程序设计停考了吗,2018山东自考停考专业有哪些

自考每年都会停考一批的专业以适应社会的发展,今年山东自考的停考专业有哪些?本文由学梯网小编整理发布,仅供参考。2018年山东自考停考专业有什么根据山东省教育考试院发布的《关于山东自学考试停考国际贸易(专科)等19个专业的通知》知悉&…

公开调用私有Java方法?

我们是Java开发人员,在Java中已知4种访问修饰符:私有,受保护,公共和包。 好吧,除了私有外,最后三个可以通过继承,相同的包或实例从类外部调用。 现在,常见的问题是,可以公…

C语言字符像素,返回字符串宽度 (以像素为单位)

[c]代码库#include #include #include #include int main(void){/* request auto detection */int gdriver DETECT, gmode, errorcode;int x 0, y 0;int i;char msg[80];/* initialize graphics and local variables */initgraph(&gdriver, &gmode, "");/…

Spring动态物业管理

静态和动态属性对于运营管理以及在生产级别更改系统行为都非常重要。 特别地,动态参数减少了服务中断。 本文展示了如何使用Quartz在Spring Applications中管理动态属性。 有关使用 Spring和Quartz集成提供“ 使用Spring和Quartz的多作业计划服务”的文章。 让我们看…