最近的项目,面临情况如下:
1. 并发压力大。平时并发连接大约在3000左右,高峰期是8000人上线访问,预期未来会达到20,000人同时在线。
2. 受到网络攻击。系统是接在公网上致使网络爬虫和攻击工具都可能给系统带来未知压力,甚至突然增加的并发访问导致系统瘫痪。
3. 数据库压力大。有大量的数据库访问操作,并且SQL语句中含有COUNT(*)或者JOIN等消耗系统资源的代码。
为了满足应用需要,特别对以下环境进行了调优。系统基本配置如下:
HP-UX V11.11 2CPU 4G
HP JDK V1.5
Apusic V5.0
SQL Server 2005
系统硬件条件已经确定,系统资源调用变化最频繁的就是应用服务器,因此应用服务器所在的操作系统、Java虚拟机(Java Virtual Machine, JVM)和Apusic AS都需要调优。而应用服务器对数据库的数据库连接池大小也必定会影响数据库服务器的相关压力,因此最后再根据稳定后的应用服务器调整数据库服务器配置。
1. 先调整JVM。这个先根据JVM所在的应用服务器物理内存的大小和JDK所支持的大小决定,建议是将空闲内存的70%~80%分配给JVM使用。下面是Java启动时用的配置参数:
-server -Xms1024m -Xmx1024m -Xmn?m -XX:MaxPermSize=256m -XX:NewSize=128m -XX:MaxNewSize=128m -XX:SurvivorRatio=8 -Xincgc、
注:1. 不同JDK在不同OS下所能使用的内存大小是不同
2. Heap的大小和分配现在设置的是经验值,是否调整最终还需要分析应用来定,一般经验值已经满足需要。
3. GC的机制对系统稳定也比较重要,尽可能参考JDK提供的最新GC参数。
4. 使用server版的JVM一般都会对应用系统提升带来帮助。
2. 再调整Apusic应用服务器。因为并发压力大,也意味着系统对CPU和内存的资源消耗都会比较大,为保证应用服务器的稳定修改apusic.conf的配置如下(只保留了修改的部分):
2.1. 线程池调整
为了平衡用户访问速度与并发支持的关系,必须调整Apusic的线程池。调整前依据以下原则:
● 每CPU50用户的原则(线程池的设置可参考《Apusic AS V5.1线程池配置和调优》)。
● HTTPHandler是MuxHandler的三倍。
<SERVICE
CLASS="com.apusic.util.ThreadPoolService"
NAME="apusic:service=ThreadPool,name=MuxHandler"
>
<ATTRIBUTE NAME="MaxThreads" VALUE="100"/>
<ATTRIBUTE NAME="MaxSpareThreads" VALUE="30"/>
<ATTRIBUTE NAME="MinSpareThreads" VALUE="30"/>
</SERVICE>
<SERVICE
CLASS="com.apusic.util.ThreadPoolService"
NAME="apusic:service=ThreadPool,name=HTTPHandler"
>
<ATTRIBUTE NAME="MaxThreads" VALUE="300"/>
<ATTRIBUTE NAME="MaxSpareThreads" VALUE="100"/>
<ATTRIBUTE NAME="MinSpareThreads" VALUE="100"/>
</SERVICE>
2.2. Mux(多路复用服务)调优。多路复用是将客户端的服务申请分发给相应的服务,如:HTTP服务、JMS服务等等。因此该服务对资源占用时间较短,不需要分配太多线程,只需要关注他的接收能力和申请排队,保证申请不会丢失。
<SERVICE
CLASS="com.apusic.net.Muxer"
>
<ATTRIBUTE NAME="NumberSelectors" VALUE="2"/>
<!-- 系统CPU核数,多个CPU使用多个Selectors可以加快并发处理能力 -->
<ATTRIBUTE NAME="Port" VALUE="80"/>
<!-- 默认的服务端口 -->
<ATTRIBUTE NAME="Backlog" VALUE="50"/>
<!-- TCP/IP的队列大小,如果有大量客户端连接超时,而服务器又没有足够的CPU压力,可以调大这个值 -->
</SERVICE>
2.3. WEB服务调优。
<SERVICE
CLASS="com.apusic.web.WebService"
>
<ATTRIBUTE NAME="NumberSelectors" VALUE="2"/>
<!-- 系统CPU核数,多个CPU使用多个Selectors可以加快并发处理能力 -->
<ATTRIBUTE NAME="MaxKeepAliveConnections" VALUE="300"/>
<!-- 最大保持KeepAlive的连接数,与HTTPHandler保持一致 -->
<ATTRIBUTE NAME="MaxKeepAliveRequests" VALUE="600"/>
<!-- 最大保持KeepAlive的请求数,设HTTPHandler×2,大约一个连接支持两次请求,如果服务器硬件条件允许可以再开大些 -->
<ATTRIBUTE NAME="WaitingClientTimeout" VALUE="15"/>
<ATTRIBUTE NAME="MaxWaitingClients" VALUE="200"/>
<!-- 等待队列满了后,将客户端请求抛弃的等待时间。如果关注系统反应的及时性,就把这个值调小,还可以把请求队列MaxWaitingClients调小;如果关注系统服务的有效性则要调大。-->
<ATTRIBUTE NAME="KeepAlive" VALUE="True"/>
<!-- 默认打开KeepAlive,了解这个参数配置需要参看HTTP 1.1协议 -->
<ATTRIBUTE NAME="ServletReloadCheckInterval" VALUE="-1"/>
<!-- 设为-1,意思就是不检查,因为这个功能是为开发阶段提供热部署的 -->
<ATTRIBUTE NAME="KeepAliveTimeout" VALUE="15"/>
<!-- 服务器关闭客户端连接前等待下一次请求的时间,如果系统压力较大可以将这个值设小,以便应对更多的请求。 -->
</SERVICE>
2.3. Session服务
基本上采用默认值就可以了,如果需要配置集群才需要调整Session里面某些配置选项,具体可以参考Apusic集群配置。
2.4. 数据库连接池服务
<datasources>
<datasource name="test"
jndi-name="jdbc/test"
driver-class="net.sourceforge.jtds.jdbc.Driver"
url="Jdbc:jtds:sqlserver://192.168.0.1:1433/test"
min-spare-connections="50"
max-spare-connections="50"
max-connections="150"
initial-connections="50"
>
<property name="user" value="sa"/>
<property name="test-before-reused" value="false"/>
<property name="password" value="test"/>
<property name="stmt-cache-size" value="50"/>
<property name="pre-fetch-size" value="50"/>
</datasource>
</datasources>
min-spare-connections、max-spare-connections:在池中保留的空闲数据库连接数;
initial-connections:初始化的空闲数据库连接数;
三个值相同,保证在初始化时就有足够的数据库连接使用。
数据库连接数×2=HTTP线程池数目
注:max-connections在现实中被调小。因为数据库服务器无法处理更多响应,因此原则是先保证拥有数据库连接的线程能够有效响应。
3. 调整HP-UX操作系统。
3.1. 首先调整核心资源,使用ulimit -a查看核心参数,特别关注file和memory两部分的使用,有些时候操作系统限制了进程打开文件数和内存使用数,无法有效利用硬件资源也会限制应用服务器性能的发挥。
3.2. 因为应用系统受到攻击,致使出现大量的CLOSE_WAIT、FIN_WAIT_2这样状态的连接,消耗大量系统资源。因此使用ndd进行网络参数配置,先用:ndd /dev/tcp,然后输入?,可以得到所有网络参数情况。使用:ndd -get /dev/tcp 参数名称,可以获得原参数的值。使用:ndd -set /dev/tcp 参数名称 参数值,可以设置新参数的值。例如:获得初始值:ndd -get /dev/tcp tcp_time_wait_interval,设置新值:ndd -set /dev/tcp tcp_time_wait_interval 30000,30000是毫秒单位=30秒。不能设置为0,0似乎是无限长的意思。需要关注的参数如下:
#与TIME_WAIT相关的参数,当系统出现大量此状态的连接时可以调小这个值
tcp_time_wait_interval 30000
tcp_tw_cleanup_interval 60000
#与FIN_WAIT相关的参数
tcp_fin_wait_2_timeout 1000
#与KeepAlive相关的参数,因为应用服务器不负责KeepAlive连接的管理,因此这里由操作系统负责
tcp_keepalive_interval 120000
tcp_keepalive_detached_interval 120000
tcp_keepalives_kill 1
tcp_ip_abort_interval 600000
#与TCP连接数相关的参数
tcp_conn_request_max 4096
4. 调整SQL Server数据库的参数。这个是因为数据库压力较大,才关注到这个部分调优。
4.1. 内存调整。因为SQL Server内存管理默认无限大,结果把系统资源全部耗尽,因此将服务器内存按照70~80%原则分配给SQL Server使用。
4.2. 处理器设置。主要是选择提升SQL Server的优先级和使用Windows纤程,保证SQL Server在操作系统中的执行速度。
4.3. 连接设置。控制最大并发连接数,比数据库连接池所设的连接数稍大就可以了,防止过多连接导致系统切换线程带来的资源消耗。同时合理设置查询的超时时间,保证资源不会被某个访问占用。
4.4. 活动监视器。通过活动监视器查看系统中的活动进程,以及执行的SQL语句,并且在系统压力较大时观察是否有资源被锁。
不过这些其实都只是帮助系统更好的运行,实际上SQL Server资源消耗问题的解决仍然领先应用的调整,应用发现某些表关联有问题,重新调整后CPU压力立刻降低。
以上是整个调优的过程记录。