ipanda

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            3 Posts :: 3 Stories :: 2 Comments :: 0 Trackbacks
          前言:
          公司開發了一個網站,估計最高在線人數是3萬,并發人數最多100人。開發的網站是否能否承受這個壓力,如何確保網站的負荷沒有問題,經過研究決定如下:
          (1) 采用負載平衡和集群技術,初步機構采用Apache+Tomcat的機群技術。
          (2) 采用壓力測試工具,測試壓力。工具是Loadrunner。
          硬件環境搭建:
          為了能夠進行壓力測試,需要搭建一個環境。剛開始時,測試在公司局域網內進行,但很快發現了一個問題,即一個腳本的壓力測試結果每次都不一樣,并且差別很大。原來是受公司網絡的影響,于是決定搭建一個完全隔離的局域網測試。搭建后的局域網配置如下:
          (1) 網絡速度:100M
          (2) 三臺服務器:
          負載服務器 :操作系統windows2003,
          Tomcat服務器:操作系統windows2000 Professional
          數據庫服務器:操作系統windows2000 Professional
          三臺機器的cpu 2.4 G, 內存 1G。
          軟件環境搭建:
          軟件的版本如下:
          Apache 版本:2.054,
          Tomcat5.0.30,
          mysql :4.1.14.
          JDK1.5
          壓力測試工具:Loadrunner7.8。


          負載平衡方案如下:
          一臺機器(操作系統2003)安裝apache,作為負載服務器,并安裝tomcat作為一個worker;一個單獨安裝tomcat,作為第二個worker;剩下的一臺單獨作為數據庫服務器。
          Apache和tomcat的負載平衡采用JK1.2.14(沒有采用2.0,主要是2.0不再維護了)。
          集群方案:
          采用Tomcat本身的集群方案。在server.xml配置。
          壓力測試問題:
          壓力測試后,發現了一些問題,現一一列出來:
          (1) 采用Tocmat集群后,速度變得很慢。因為集群后,要進行session復制,導致速度較慢。Tomcatd的復制,目前不支持application復制。復制的作用,主要用來容錯的,即一臺機器有故障后,apache可以把請求自動轉發到另外一個機器。在容錯和速度的考慮上,我們最終選擇速度,去掉了Tomcat集群。
          (2) 操作系統最大并發用戶的限制:
          為了采用網站的壓力,我們開始的時候,僅測試Tomcat的最大負載數。Tomcat服務器安裝的操作系統是windows2000 Professional。當我們用壓力測試工具,并發測試時,發現只要超過15個并發用戶,會經常出現無法連接服務器的情況。經過研究,發現是操作系統的問題:windows2000 Professional 支持的并發訪問用戶有限,默認的好像是15個。于是我們把操作系統全部采用windows2003 server版本。
          (3) 數據庫連接池的問題:
          測試數據庫連接性能時,發現數據庫連接速度很慢。每增加一些用戶,連接性能就差了很多。我們采用的數據庫連接池是DBCP,默認的初始化為50個,應該不會很慢吧。查詢數據庫的連接數,發現初始化,只初始化一個連接。并發增加一個用戶時,程序就會重新創建一個連接,導致連接很慢。原因就在這里了。如何解決呢?偶爾在JDK1.4下的Tomcat5.0.30下執行數據庫連接壓力測試,發現速度很快,程序創建數據庫連接的速度也是很快的。看來JDK1.5的JDBC驅動程序有問題。于是我們修改 JDK的版本為1.4.

          (4) C3P0和DBCP
          C3P0是Hibernate3.0默認的自帶數據庫連接池,DBCP是Apache開發的數據庫連接池。我們對這兩種連接池進行壓力測試對比,發現在并發300個用戶以下時,DBCP比C3P0平均時間快1秒左右。但在并發400個用戶時,兩者差不多。

          速度上雖然DBCP比C3P0快些,但是有BUG:當DBCP建立的數據庫連接,因為某種原因斷掉后,DBCP將不會再重新創建新的連接,導致必須重新啟動Tomcat才能解決問題。DBCP的BUG使我們決定采用C3P0作為數據庫連接池。
          調整后的方案:
          操作系統Windows2003 server版本
          JDK1.4
          Tomcat 5.0.30
          數據庫連接池C3P0
          僅采用負載平衡,不采用集群。
          軟件的配置:
          Apache配置:主要配置httpd.conf和新增加的文件workers.properties
          Httpd.conf:
          #一個連接的最大請求數量
          MaxKeepAliveRequests 10000
          #NT環境,只能配置這個參數來提供性能
          <IfModule mpm_winnt.c>
          #每個進程的線程數,最大1920。NT只啟動父子兩個進程,不能設置啟動多個進程
          ThreadsPerChild 1900
          每個子進程能夠處理的最大請求數
          MaxRequestsPerChild 10000
          </IfModule>

          # 加載mod_jk
          #
          LoadModule jk_module modules/mod_jk.so
          #
          # 配置mod_jk
          #
          JkWorkersFile conf/workers.properties
          JkLogFile logs/mod_jk.log
          JkLogLevel info
          #請求分發,對jsp文件,.do等動態請求交由tomcat處理
          DocumentRoot "C:/Apache/htdocs"
          JkMount /*.jsp loadbalancer
          JkMount /*.do loadbalancer
          JkMount /servlet/* loadbalancer
          #關掉主機Lookup,如果為on,很影響性能,可以有10多秒鐘的延遲。
          HostnameLookups Off
          #緩存配置
          LoadModule cache_module modules/mod_cache.so
          LoadModule disk_cache_module modules/mod_disk_cache.so
          LoadModule mem_cache_module modules/mod_mem_cache.so

          <IfModule mod_cache.c>
          CacheForceCompletion 100
          CacheDefaultExpire 3600
          CacheMaxExpire 86400
          CacheLastModifiedFactor 0.1

          <IfModule mod_disk_cache.c>
          CacheEnable disk /
          CacheRoot c:/cacheroot
          CacheSize 327680
          CacheDirLength 4
          CacheDirLevels 5
          CacheGcInterval 4
          </IfModule>
          <IfModule mod_mem_cache.c>
          CacheEnable mem /
          MCacheSize 8192
          MCacheMaxObjectCount 10000
          MCacheMinObjectSize 1
          MCacheMaxObjectSize 51200
          </IfModule>
          </IfModule>
          worker. Properties文件
          #
          # workers.properties ,可以參考
          http://jakarta.apache.org/tomcat/connectors-doc/config/workers.html
          # In Unix, we use forward slashes:
          ps=

          # list the workers by name

          worker.list=tomcat1, tomcat2, loadbalancer

          # ------------------------
          # First tomcat server
          # ------------------------
          worker.tomcat1.port=8009
          worker.tomcat1.host=localhost
          worker.tomcat1.type=ajp13

          # Specify the size of the open connection cache.
          #worker.tomcat1.cachesize

          #
          # Specifies the load balance factor when used with
          # a load balancing worker.
          # Note:
          # ----> lbfactor must be > 0
          # ----> Low lbfactor means less work done by the worker.
          worker.tomcat1.lbfactor=900

          # ------------------------
          # Second tomcat server
          # ------------------------
          worker.tomcat1.port=8009
          worker.tomcat1.host=202.88.8.101
          worker.tomcat1.type=ajp13

          # Specify the size of the open connection cache.
          #worker.tomcat1.cachesize

          #
          # Specifies the load balance factor when used with
          # a load balancing worker.
          # Note:
          # ----> lbfactor must be > 0
          # ----> Low lbfactor means less work done by the worker.
          worker.tomcat1.lbfactor=2000

          # ------------------------
          # Load Balancer worker
          # ------------------------

          #
          # The loadbalancer (type lb) worker performs weighted round-robin
          # load balancing with sticky sessions.
          # Note:
          # ----> If a worker dies, the load balancer will check its state
          # once in a while. Until then all work is redirected to peer
          # worker.
          worker.loadbalancer.type=lb
          worker.loadbalancer.balanced_workers=tomcat1,tomcat2

          #
          # END workers.properties
          #

          Tomcat1配置:
          <!--配置server.xml
          去掉8080端口,即注釋掉如下代碼:-->
          <Connector
          port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
          enableLookups="false" redirectPort="8443" acceptCount="100"
          debug="0" connectionTimeout="20000"
          disableUploadTimeout="true" />

          <!--配置8009端口如下:-->
          <Connector port="8009"
          maxThreads="500" minSpareThreads="400" maxSpareThreads="450"
          enableLookups="false" redirectPort="8443" debug="0"
          protocol="AJP/1.3" />
          <!--配置引擎-->
          <Engine name="Catalina" defaultHost="localhost" debug="0" jvmRoute="tomcat1">

          啟動內存配置,開發configure tomcat程序即可配置:
          Initial memory pool: 200 M
          Maxinum memory pool:300M
          Tomcat2配置:
          配置和tomcat1差不多,需要改動的地方如下:
          <!--配置引擎-->
          <Engine name="Catalina" defaultHost="localhost" debug="0" jvmRoute="tomcat2">

          啟動內存配置,開發configure tomcat程序即可配置:
          Initial memory pool: 512 M
          Maxinum memory pool:768M
          Mysql配置:
          Server類型:Dedicated MySQL Server Machine
          Database usage:Transational Database Only
          并發連接數量:Online Transaction Processing(OLTP)
          字符集:UTF8
          數據庫連接池的配置:
          我們采用的是spring 框架,配置如下:
          <property name="hibernateProperties">
          <props>
          <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
          <prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
          <prop key="hibernate.connection.url">jdbc:mysql://202.88.1.103/db</prop>
          <prop key="hibernate.connection.username">sa</prop>
          <prop key="hibernate.connection.password"></prop>

          <prop key="hibernate.show_sql">false</prop>
          <prop key="hibernate.use_sql_comments">false</prop>

          <prop key="hibernate.cglib.use_reflection_optimizer">true</prop>
          <prop key="hibernate.max_fetch_depth">2</prop>

          <prop key="hibernate.c3p0.max_size">200</prop>
          <prop key="hibernate.c3p0.min_size">5</prop>
          <prop key="hibernate.c3p0.timeout">12000</prop>
          <prop key="hibernate.c3p0.max_statements">50</prop>
          <prop key="hibernate.c3p0.acquire_increment">1</prop>
          </props>
          </property>
          其他的沒有額外配置。
          LoadRunner 常見問題:
          (1)sofeware caused connction:這種情況,一般是腳本有問題,或者loadrunner有問題。解決方法:重新啟動機器,或者重新錄制腳本,估計是loadrunner的bug。
          (2)cannot connect to server:無法連接到服務器。這種情況是服務器的配置有問題,服務器無法承受過多的并發連接了。需要優化服務器的配置,
          如操作系統采用windows 2003 server,
          優化tomcat配置:maxThreads="500" minSpareThreads="400" maxSpareThreads="450"。但是tomcat 最多支持500個并發訪問
          優化apache配置:
          ThreadsPerChild 1900
          MaxRequestsPerChild 10000
          其他的錯誤如:
          Action.c(10): Error -27791: Server has shut down the connection prematurely
          HTTP Status-Code=503 (Service Temporarily Unavailable)
          一般都是由于服務器配置不夠好引起的,按照問題(2)處理,如果仍舊不行,需要優化硬件和調整程序了。
          Apache問題:
          (1) File does not exist: C:/Apache/htdocs/favicon.ico:
          這個問題是apache,htdocs目錄沒有favicon.ico文件引起的,該文件是網站的圖標,僅在firefox,myIE等瀏覽器出現。
          (2) 圖片無法顯示:
          配置apache后,卻無法顯示圖片。
          解決方法:把程序的圖片,按照程序結構copy到apache的htdocs目錄下。
          (3) 無法處理請求:
          當我們輸入 ***.do 命令后,apache確返回錯誤信息,而連接tomcat卻沒有問題。原因是沒有把.do命令轉發給tomcat處理。解決方法如下:
          在apache配置文件中配置如下內容:
          DocumentRoot "C:/Apache/htdocs"
          JkMount /*.jsp loadbalancer
          JkMount /*.do loadbalancer


          總結:
          網站的壓力測試,涉及的知識面挺廣的,不僅要熟悉壓力測試工具,還要知道如何配置和優化應用服務器和數據庫,并且需要知道如何優化網絡、操作系統、硬件系統。
          測試中不僅要善于發現問題,要知道如何解決。最重要的一點,要有良好的測試方法。剛開始測試時,可以從最簡單的測試腳本入手,不需要太復雜的腳本,這樣便于發現問題。如我們剛開始時,就從一個簡單的下載登陸界面的腳本入手,測試一個tomcat的壓力負載。一個簡單的獲取登陸的腳本,幫助我們優化了tomcat的配置;后來再測試數據庫連接,也是一個簡單的數據庫連接腳本,幫助我們優化了數據庫連接池;然后利用這些簡單的腳本,測試apache的負載平衡,優化了apache配置。最后運行復雜的腳本,模擬多種角色的用戶在不同時間下的處理,以測試網站壓力負載。

          posted on 2006-05-15 15:21 傻傻貓的博客 閱讀(227) 評論(0)  編輯  收藏 所屬分類: java方面

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 长沙县| 临沭县| 葵青区| 克什克腾旗| 稻城县| 荔波县| 桑日县| 临潭县| 胶州市| 高雄县| 丁青县| 安新县| 恩平市| 大连市| 康保县| 乃东县| 珲春市| 三门县| 黑水县| 安吉县| 长泰县| 齐齐哈尔市| 夹江县| 灵寿县| 庄河市| 方城县| 安义县| 九寨沟县| 汽车| 公安县| 兴仁县| 神木县| 南岸区| 墨玉县| 张家界市| 娱乐| 兴文县| 永修县| 朝阳市| 元江| 无为县|