您的位置: 江门资讯网 > 娱乐

Java EE 常见性能问题解决手册5

发布时间:2019-09-13 20:00:12

设置一个饱和的池,然后逐步减少连接池大小,一直到CPU占用率为75%到85%之间,同时用户负载正常。如果等待队列大小实在无法控制,考虑下面2中建议:  1.把你的程序放入代码模拟器运行,调整程序代码   2.增加额外的硬件  如果你的用户负载超过了环境能承受的范围,你应该考虑修正代码减少和CPU的冲突或者增加CPU。

JDBC连接池

很多JAVA EE 程序连接到一个后台数据源,大多数是通过JDBC(JAVA DATABASE CONNECTIVITY)将程序和后台连接起来。由于创建数据库连接的代价很高,程序服务器让在同一个程序服务器实例下的所有程序共享特定数量的一些连接。如果一个请求需要连接到数据库,但是数据库的连接池无法为这个请求创建一个新连接,这个时候请求就会停下来等待连接池完成自己的操作再给她分配一个连接。反过来,如果数据库连接池太大程序服务器就会浪费资源,并且程序有可能强迫数据库承受过量的负荷。我们调试的目的就是尽量减少请求的等待时间和饱和的资源之间之间的冲突,让一个请求在数据库外等待要比强迫数据库好的多。

一个程序服务器如果设置连接的数量不合理就会有下面这些特征:

1.程序运行速度缓慢   2.CPU使用率低   3.数据库连接池使用率非常高   4.线程等待数据库的连接   5.线程使用率很高   6.请求队列中有待处理的请求(潜在的)   7.数据库CPU使用率很低(因为没有足够的请求能够让他繁忙起来)  JDBC prepared statements

和JDBC相关的另一个重要的设置就是:为JDBC使用的statement 所预设的缓存的大小。当你的程序在数据库中运行SQL statement 的时候三下面3个步骤进行:

1.准备   2.执行   3.返回数值  在准备阶段,数据库驱动器让数据库完成队列中的执行计划。执行的时候,数据库执行语句并返回指向结果的引用。在返回的时候,程序重新描述这些结果并描述出这些被请求的信息。

数据库驱动会这样优化程序:首先,你需要去准备一个statement ,这个statement 它会让数据库做好执行和缓存结果的准备。在此同时,数据库驱动会从缓存中装载已经准备好的statement ,而不用直接连接到数据库。

如果prepared statement 设置太小,数据库驱动器会被迫去查询没有装载进缓存区的statement ,这就会增加额外的连接到数据库的时间。prepared statement 缓存区设置不恰当最主要的症状就是花费大量的时间去连接相同的statement。这段被浪费的时间本来是为了让它去装载后面的调用的。

事情变的稍微复杂了点,缓存prepared statement 是每个statement的基础,就是说在一个statement连接之前都应当缓存起来。这个增加的复杂性就产生了一个冲突:如果你有100个prepared statement需要去缓存,但你的连接池中有50个数据库连接,这个时候你就需要有存放5000条预备语句的内存。

通过跟踪性能,确定出你程序所执行的不重复的statement 的数量,并从这些statement 中找出哪些条是频繁执行的。

Entity bean(实体BEAN)和stateful session bean的缓冲

无状态(stateless)对象可以被放入到池中共享,但象Entity beans和 stateful session bean这样的有状态的对象就需要被缓存,因为这些bean的每个实例都是不相同的。当你需要一个有状态对象时,你需要明确创建这个对象的特定实例,普通的实例是不能满足的。类似的,你考虑一个超市类似的情况,你需要个售货员但他叫什么并不重要,任何售货员都可以满足你。也就是,售货员被放入池中共享,因为你只需要是售货员就可以,而不是一个叫做史缔夫的这个售货员。当你离开超市的时候,你需要带上你的孩子,不是其他人的孩子,而是你自己的。这个时候,孩子就需要被缓存。

Figure 10. The application requests an object from the cache that is in the cache, so a reference to that object is returned without making a network trip to the database

当你的缓存区太小的时候,缓存的性能就会明显的受到影响。特别是,当一个请求去一个已经满了的缓存区域去请求一个对象的时候,下面的步骤就会执行,这些步骤会在图11中显示:

1. 程序请求一个对象   2. 缓存检测这个对象是否已经存在于缓存中   3. 缓存决定把一个对象开除出缓存(一般采用的算法是遗弃最近使用次数最少的对象)   4. 把这个对象扔出缓存(称为passivated)   5. 把从数据库中装载这个新对象并放入到缓存(称为activated)   6. 把指向这个对象的引用返回给程序

Figure 11. Because the requested object is not in the cache, an object must be selected for removal from the cache and removed from it.

如果多数的请求都需要执行这些步骤的话,那你采用缓存技术就不是好的选择了!如果这些处理步骤频繁发生的话,你就需要重新推敲下你的缓存了。回忆一下:从缓存中去除一个对象称为passivation,从持久存储区取出一个对象放入缓存称为activation。能在缓存中找到的请求(缓存中有此请求的对象)的百分率称为hit ratio,相反找不到的请求的百分率称为miss ratio。

缓存刚被初始化的时候,hit ratio是0,它的activation数量非常高,因此在初始化后你需要去观察缓存的性能。初始化以后,你应该跟踪passivation的数量并把它和与向缓存请求对象的请求的总量相比较,因为passivations只会发生在缓存被初始化以后。但一般来说,我们更需要关心缓存的miss ratio。如果miss ratio超过25%,那么缓存可能是太小了。因此,如果missratio的数量超过75%,那么不是你的缓存设置的太小就是你不需要缓存这个技术。

一旦你觉得你的缓存太小,就去尝试着增大大小,并测试增加的性能。如果miss ration下降到20%以下,那你的缓存的大小就非常棒了,如果没有什么效果,那么你就需要和这个程序的技术员联系,看是这个对象是不是需要缓存或者是否应该修正程序中这个对象的代码。

Staless session bean和message-driven bean池

Stateless session bean 和message-driven bean 在商业应用方面很重要,不要期望它们会保持自己特有的状态信息。当你的程序需要使用这些BEAN的商业功能的时候,它就从一个池中取出一个BEAN实例,用这个实例来调用一个个方法,用完后再将BEAN的实例再放回到池中。如果你的程序过了一会又需要这个一摸一样的BEAN,就从池中再得到一个实例,但不能保证你得到的就是上一个实例。池能够让程序共享资源,但是会让你的程序付出潜在的等待时间。如果你无法从池中得到想要的BEAN,请求就会等待,一直到这个BEAN被放入到池中。很多程序服务器都会把这些池调整的很好,但是我碰到过因为在环境中把他们设置的太小而引发的不少麻烦。Stateless bean池的大小应该和可执行线程池的大小一般大,因为一个线程同时只能使用一个对象,再多了就造成浪费的。因此,一些程序服务器把池的大小和线程的数量设置成同样的数量。为了保险起见,你应该亲自把它设置成这个数。

威门热淋清颗粒有用吗
幼儿咳嗽怎么办
小儿发热怎么办
儿童止咳化痰药排名
猜你会喜欢的
猜你会喜欢的