JBOSS调优
WEB程序调优1.纯JSP比JSF性能要好
2.树形数据的显示如果用JSF性能要差,不如用低层次的JAVASCRIPT
WEB SERVICE调优
1.性能不太好,尤其依赖于传输的SOAP大小,因为在XML与JAVA OBJECT的转换中消耗太多
2.加缓存在SOAP上
3.JBOSS的WEB SERVICE有三个实现,原生的、CXF和METRO,性能最好的是METRO,最差是原生的
JBOSS中的TOMCAT调优
1.CONNECTOR参数
当进入JBOSS的请求到达maxThreads,且又高于acceptCount的时候,用户就会收到Connection refused的错误信息,当HTTP请求的线程空闲了maxIdleTime时,系统就会杀掉这些线程,直到到达minSpareThreads数为止
2.如何计算程序就需的线程数
CPU数*200,如4核的设800
可以通过域名为jboss.web,name=http-127.0.0.1-8080,type=ThreadPool的MBEAN观察实际的线程数
3.处理周期长的WEB线程
WEB线程处理请求时,并不会马上结束,还会继续传递到EJB层,这样如果EJB层处理周期长,会导致WEB层请求数增长来处理新进来的请求
4.如何增大线程最大处理数
这完全依赖于CPU、RAM和SOCKET数
5.使用APACHE PORTABLE RUNTIME
增加APR包能提高性能20%,如果是WINDOWS系统则不建议
6.整合APACHE WEBSERVER与JBOSS SERVER
使用APACHE WEBSERVER作为JBOSS的前端,以达到HA的效果,又能提高20%的性能
结合方式是使用mod_jk mod_proxy_ajp mod_proxy_http
7.三种方式的比较
mod_proxy_ajp要高于其他两种
8.引入mod_cluster
9.web.xml中关于JSP的调优
development=false,避免访问前的检查
checkInterval=0,避免JSP需要重新编译
trimSpaces=true,删除JSP中的空格
genStringAsCharArray=true
JBOSS中SERVICE的调优
SESSION BEAN
1.stateless session bean在池中数量大小的配置
每建一个SESSION BEAN,就会在jboss.j2ee域下建一个MBEAN,通过查看其信息得知BEAN的处理统计时间来调整BEAN数量大小,配置文件:/deploy/ejb3-interceptors-aop.xml
2.stateful session bean
SFSB是被JBOSS缓存在容器中,因此客户端的每个请求都会立即响应,同样也是通过SLSB的方式查看并调整CACHE的数量大小
3.SFSB与 SLSB的比较
SFSB性能要差10%
4.事务
EJB与普通RMI SERVICE相比,就是有完整的事务支持,如果EJB采用CMT,则可以保证其方法是在全局的事务上下文中被执行的,但开启事务的成本太高,如果不需用到事务的方法需将事务关闭
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
5.自定义EJB容器
JBOSS是以拦截器的方式运行EJB的,如果EJB中不需要事务的支持,可将这个INTERCEPTOR注释掉
<
interceptor-ref
name
="org.jboss.aspects.
tx.TxPropagationInterceptor" />
6.比较软的方式自定义EJB容器
tx.TxPropagationInterceptor" />
将定义写在新的XML文件中,以覆盖原先的设定
<?
xml version="1.0" encoding="UTF-8"
?>
< aop xmlns ="urn:jboss:aop-beans:1.0" >
< domain name ="Non Tx Stateless Bean" extends ="Intercepted Bean"
inheritBindings ="false" >
< bind pointcut ="execution(public * *->*(..))" >
< interceptor-ref name ="org.jboss.ejb3.stateless.
StatelessInstanceInterceptor" />
< interceptor-ref name ="org.jboss.ejb3.
AllowedOperationsInterceptor" />
< stack-ref name ="EJBInterceptors" />
</ bind >
</ domain >
</ aop >
< aop xmlns ="urn:jboss:aop-beans:1.0" >
< domain name ="Non Tx Stateless Bean" extends ="Intercepted Bean"
inheritBindings ="false" >
< bind pointcut ="execution(public * *->*(..))" >
< interceptor-ref name ="org.jboss.ejb3.stateless.
StatelessInstanceInterceptor" />
< interceptor-ref name ="org.jboss.ejb3.
AllowedOperationsInterceptor" />
< stack-ref name ="EJBInterceptors" />
</ bind >
</ domain >
</ aop >
JMS
1.基本概念
JMS provider:JMS系统
Messages:客户端交流的载体
Connection factories:产生链接的工厂
Destinations:有Queues和Topics
Queues:含有一堆Messag的队列,只能发给一个客户端
Topics:可以发给多个客户端
JMS clients:生产和消费Message的东西
MDB:一个特殊的consumer
2.JMS架构
如果客户端和服务器端同一个JBOSS,则通过JCA作通讯,通过调整deploy/jca-jboss-beans.xml中的WorkManagerThreadPool的参数来调优,
如果不在一个JBOSS内,则通过远程框架进行通讯,通过调整deploy\messaging\remoting-bisocket-service.xml中的org.jboss.remoting.transport.Connector里的参数大小来调优
3.调优JBoss Messaging Connectionfactory
deploy\messaging\connection-factories-service.xml
4.调优JBoss Messaging destinations
在deploy/messaging中增加*–service.xml文件,从而增加MBEAN,来增加队列,再调整其参数
5.HornetQ
是JBOSS 6.0之后的JMS服务器,没有依赖于任何JBOSS包,可以嵌于任何程序中。
调优主要针对deploy/hornetq/hornetq-configuration.xml文件中的journal和transport参数
journal:journal-directory-存放message的地方,如果与其他文件夹共享,则会降低性能;journal-min-files:生成文件的个数,如果发现新文件建立的次数非常频繁,则考虑加大此数值来避免
6.JMS调优基本原则
减少message的大小;使用DUPS_OK_ACKNOWLEDGE;重用JMS资源,如connections, sessions, consumers, and producers;可以不持久化message的就不持久化。
持久层的调优
数据库设计调优
1.减少表所占的空间
这样IO读速度会加快,更少的内存;列的数据类型选少的;表设计要正规化(如果是报表类型的程序则非正规化的表速度要好)
2.数据库分割
如果某个表数据量太大,可将此表按某种逻辑分割成若干个小表,如按月份分成不同的表,不同月份的数据就放于不同的表中;
如果某个表中字段数太多,可将某些字段分组,不同的组建不同的表,如将BLOB类型的字段分割到新表中;
3.增加索引
对查询中用得比较锪WHERE字段做索引,索引数据是被抽出来,进行排序后单独存放的,如果不加索引,排序的动作只能在SQL被执行的时候做;
如果做了索引的字段被修改,则该字段的索引同样也要被修改,重新排序,这也会带来性能问题,因此一个表中最多只能放4-5个索引;
但如果这个表是只读的,则索引可以随意增加;
如果有组合索引,则UNIQUE的,值比较大的字段放在前面会比较好;
索引可以加在HIBERNATE的注释中
JDBC的调优
1. 使用链接池来链接数据库
数据链接的建立和关闭是一个非常昂贵的操作,能重用就重用,客户端从PreparedStatement Cache中取得对象,PreparedStatement再从链接池中取得链接,从而得以进行对数据库的操作
2.设置正确的fetch大小
如果设置了fetch大小为100,则JDBC会从数据库中取回100条记录,这样从ResultSet中读取next()是,是从内存中返回数据,超过了100再从数据库中取100以备用;
此数值一般设为当次查询总量的一半或1/4,但如果随便设高,性能反而下降;
JBOSS中设置全局大小:<connection-property name="defaultFetchSize">50</
connection-property>
3.INSERT和UPDATE使用批量操作
4.使用PreparedStatement而不使用Statement
PreparedStatement能避免SQL语句重复解释;使用PreparedStatement cache来缓存PreparedStatement对象
5.JDBC网络调优
<
connection-property
name
="tcpSndBuf"
>
65534
</
connection-property
>
< connection-property name ="tcpRcvBuf" > 65534 </ connection-property >
< connection-property name ="tcpNoDelay" > true </ connection-property >
< connection-property name ="tcpRcvBuf" > 65534 </ connection-property >
< connection-property name ="tcpNoDelay" > true </ connection-property >
JPA/HIBERNATE调优
使用JDBC的限制:
由于是使用了原生的SQL语句,但不同的数据库SQL语句也是不同的,如果换数据库的时候SQL语句改动量大;
多表关联时,需维护JAVA OBJECT与数据表的对应关系;
加缓存时,工作量也比较大。
JPA与HIBERNATE的区别:JPA是JAVA的一个标准,HIBERNATE是JPA的一个实现
1.优化对象获取
HIBERNATE的N+1总量,如果有两个表是一对多的关系,查询父表的时候,子表的数据是不会被查出来的,直到调用查询子表的方法时子表的数据才被查出来,因此而多出一个SQL语句
使用LEFT OUTER JOIN来达到只用一个SQL语句就查出父表和子表的数据
Query q
=
entityManager.createQuery(
"
from Customer c left outer join
fetch c.items order by c.id " );
fetch c.items order by c.id " );
2.以分页的方式限制一次性获取数据的数量
q.setFirstResult(page
*
100
).setMaxResults(
100
);
3.不能同时使用分页和FETCH的方式
HIBERNATE的分页,是首先取出所有的数据再在内存中分页,以避免不同数据库中分页语句的不同
4.使用BatchSize
@BatchSize(size = 50)
加载相关联的实体集合的个数,注意个数的对象是集合,不是集合里的单个元素
5.使用named queries作查询
这样会使用到PreparedStatement中的绑定参数
6.使用批量更新与插入
Session session
=
HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
for ( int index = 0 ; index < 1000 ;index ++ ) {
Person person = new Person();
book.setCountry("Usa");
book.setCity("NY");
person.setName("Inhabitant n." + index);
session.save(person);
// Flush every 50 records
if (index % 50== 0) {
session.flush();
session.clear();
}
}
session.getTransaction().commit();
session.close();
session.beginTransaction();
for ( int index = 0 ; index < 1000 ;index ++ ) {
Person person = new Person();
book.setCountry("Usa");
book.setCity("NY");
person.setName("Inhabitant n." + index);
session.save(person);
// Flush every 50 records
if (index % 50== 0) {
session.flush();
session.clear();
}
}
session.getTransaction().commit();
session.close();
7.使用HIBERNATE CACHE
一级缓存,在SESSION关闭前都可以使用;
二级缓存,HIBERNATE使用第三方CACHE框架来做缓存
<
property
name
="hibernate.cache.use_second_level_cache"
value ="true" />
< property name ="hibernate.cache.region.factory_class"
value ="org.hibernate.cache.jbc2.
JndiMultiplexedJBossCacheRegionFactory" />
< property name ="hibernate.cache.region.jbc2.cachefactory"
value ="java:CacheManager" />
< property name ="hibernate.cache.region.jbc2.cfg.entity"
value ="mvcc-entity" />
< property name ="hibernate.cache.region.jbc2.cfg.collection"
value ="mvcc-entity" />
启用缓存
value ="true" />
< property name ="hibernate.cache.region.factory_class"
value ="org.hibernate.cache.jbc2.
JndiMultiplexedJBossCacheRegionFactory" />
< property name ="hibernate.cache.region.jbc2.cachefactory"
value ="java:CacheManager" />
< property name ="hibernate.cache.region.jbc2.cfg.entity"
value ="mvcc-entity" />
< property name ="hibernate.cache.region.jbc2.cfg.collection"
value ="mvcc-entity" />
@Entity
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL, region =
" customers " )
public class Customer implements Serializable {
}
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL, region =
" customers " )
public class Customer implements Serializable {
}
查询缓存
<
property
name
="hibernate.cache.use_query_cache"
value
="true"
/>
启用查询缓存
@NamedQueries(
{
@NamedQuery(
name = "findCustomersByName",
query = "FROM Customer c WHERE c.name = :name",
hints = { @QueryHint(name = "org.hibernate.cacheable", value =
"true") }
)
{
@NamedQuery(
name = "findCustomersByName",
query = "FROM Customer c WHERE c.name = :name",
hints = { @QueryHint(name = "org.hibernate.cacheable", value =
"true") }
)
使用缓存的策略:静态数据可以考虑,但查询和更新频率很高的、查询条件非常复杂的不建议用