Jmeter的性能測試

在眾多類型的軟件測試中,性能測試以軟件響應速度為測試目標,尤其是在較短時間內大量并發用戶的訪問時,軟件是否具有良好的抗壓能力。本章以JMeter為性能測試工具,LifeRay為被測應用,介紹如何完成常用的壓力測試和性能測試:Web測試和數據庫測試。

Apache JMeter是個純Java的應用程序,提供了可擴展自定義腳本功能用于對靜態的和動態的資源(靜態文件、Servlet、Java對象、數據庫和FTP服務器等)進行性能測試。它可以針對服務器、網絡或對象模擬大量并發負載來進行強度測試,并分析不同壓力負載下的系統整體性能,包括性能的圖形分析。

與其說JMeter是一個測試工具,不如說是一個測試框架。因為JMeter支持范圍非常廣:

1) 通過取樣器,支持許多協議,如HTTP/ TCP/FTP/JDBC/SOAP/LDAP/JMS/MAIL;

針對不同的協議或不同的應用,配置相應的JMeter元件,所以在JMeter使用過程中,要熟悉各種元件的配置,而不僅僅局限于http請求。

2)? 跨平臺,即在所有支持JVM的平臺上都可以運行JMeter;

3) 支持多語言,所有支持BSF(Bean Scripting Framework)的腳本語言可使用。

目前各種常見的應用(如Servlets、Perl scripts、Java Objects、Databases, FTP Servers)等都可以采用JMeter來完成性能測試。JMeter的一大好處就是它內部已經實現了線程機制(線程組),用戶不用為并發負載的過程編寫代碼,只須做簡單配置即可。同時,JMeter也提供了豐富的邏輯控制器,控制線程的運行;其次,JMeter對測試結果能產生相應的統計報表,簡單、直觀,對一般性能測試應該足夠

JMeter現在作為Web程序的性能測試工具,已經得到廣泛應用。測試完成后,JMeter會形成一個performance報表,里面詳細地記載了各個URL請求的數量、平均響應時間、最小/大響應時間、錯誤率等。

JMeter除了做性能測試,也能做功能測試,特別在API層次(SOAP和REST)。這里把JMeter和Selenium做個比較,以便對JMeter有進一步的了解。

1. JMeter測試的優勢

1) 不依賴于界面。通過API調用或參數傳遞,可以添加測試用例并執行測試;

2) 測試腳本不須要編程,熟悉業務流程和http請求,就可以根據頁面中input對象來編寫測試用例;

3) 可以跳過頁面限制,向后臺程序添加非法數據,這樣可以測試后臺程序的健壯性,利用這個功能還能進行安全性測試;

4) 利用badboy錄制測試過程,可以快速地生成測試腳本;

5) JMeter斷言可以驗證程序中是否有需要得到的值;

6) 使用參數化及提供的函數功能,可以快速完成測試數據的添加和修改等。

2. JMeter測試的缺點

使用JMeter無法驗證JS程序,也無法驗證頁面UI,所以須要和Selenium配合來完成Web2.0應用的測試。

安裝

從官方網站(http://jakarta.apache.org/jmeter)下載并解壓之后即可使用。最新版(即2.3.2),需要JDK 1.4及其以上版本,不再支持JDK 1.3。下載解壓的JMeter有以下幾個目錄:bin、docs、extras、lib和printable_docs等。

1. bin目錄

對于Windows用戶來說,運行JMeter.bat就可以看見JMeter的Swing GUI客戶端。可以根據自己機器的特定配置來調整JMeter.bat中JVM調優設置,如下所示:

? ? set HEAP=-Xms256m -Xmx256m

? ? set NEW=-XX:NewSize=128m -XX:MaxNewSize=128m

? ? set SURVIVOR=-XX:SurvivorRatio=8 -XX:TargetSurvivorRatio=50%

? ? set TENURING=-XX:MaxTenuringThreshold=2

? ? set EVACUATION=-XX:MaxLiveObjectEvacuationRatio=20%

? ? set RMIGC=-Dsun.rmi.dgc.client.gcInterval=600000

? ? -Dsun.rmi.dgc.server.gcInterval=600000

? ? set PERM=-XX:PermSize=64m -XX:MaxPermSize=64m

? ? set DEBUG=-verbose:gc -XX:+PrintTenuringDistribution

根據使用經驗,Java堆值最多是物理內存的一半。如果機器的物理內存為512MB,那么選用默認值即可;如果機器的物理內存低于512MB,最好將命令行中參數調小,否則JMeter運行會很慢,甚至在JMeter.log文件里能夠看到“內存溢出”錯誤。順便提一下,如果JMeter出現異常,第一步就是檢查JMeter.log的日志信息。 bin目錄下文件JMeter.properties中有一個參數log_level.JMeter。當須要查錯時,我們可以把它設成DEBUG(默認是INFO)來獲得更詳細的日志信息。

2. Docs和printable_docs目錄

Docs目錄下面的文件是JMeter的Java Docs,而printable_docs的usermanual子目錄下的內容是JMeter的用戶手冊文檔,相關文檔還算詳細,一般需要的內容都能查到,但都是英文的。

3. extras目錄

Extras目錄下的文件是為了對構建工具Ant提供支持。可使用ant實現測試自動化的部分工作,如批量腳本的自動執行,產生HTML格式的報表。

4. lib目錄

lib目錄下還有兩個目錄:一個是ext,此目錄存放JMeter的核心jar包;另一個是junit目錄,此目錄存放JUnit測試腳本。用戶的擴展所依賴的包則要直接放在lib下(不是lib/ext下)。

Badbody進行腳本錄制

JMeter提供了一個利用本地Proxy Server(代理服務器)來錄制生成測試腳本的功能,這個功能不夠直觀(要用到代理服務器),而且JMeter的代理目前不支持HTTPS的錄制。由于HTTPS協議是加密的,該代理無法解密通信內容和請求參數。

Badboy是一款不錯的Web自動化測試輔助工具,它提供了將Web測試腳本直接導出生成JMeter腳本的功能。無論是用于非商業用途或商業用途,如果安裝Badboy的機器數量不超過5臺,是不須要為它支付任何費用的。

通過Badboy的官方網站(http://www.badboy.com.au/)下載Badboy的最新版本,其安裝過程同一般的Windows應用程序沒有什么區別。安裝完成后,可以執行桌面或Windows開始菜單中的快捷方式。如果找不到,可以直接運行安裝目錄下的Badboy.exe文件。

啟動Badboy,在地址欄中輸入待錄制的Web應用網站的URL。這里以LifeRay為例,即輸入LifeRay訪問地址 http://localhost:8080,回車開始錄制,如圖所示。

開始錄制后,可以直接在Badboy內嵌的瀏覽器(主界面的右側)中對被測應用進行操作,所有的操作都會被記錄在主界面左側的編輯窗口中。在這個簡單實驗中,我們在LifeRay中登錄然后退出。不過,我們將看到,錄制下來的腳本并不像Selenium是一個個的動作(鼠標點擊click命令或鍵盤輸入type命令),而是一個個URL。這個例子中,總共3個頂層(Top Level)HTTP請求和4個子請求被錄下。Badboy提供了兩種不同的錄制模式:請求模式(預設模式)和導航模式(類似Selenium的動作錄制),但是,只有請求模式下錄制的腳本能導出到JMeter做負載和壓力測試,因為請求模式下錄制的腳本是獨立于頁面布局和外觀的。絕大多數負載和壓力測試引擎運行時不顯示任何用戶界面,因此像JMeter這種壓力測試工具無法執行導航模式腳本。

錄制完成后,點擊工具欄中的“stop recording”按鈕,完成腳本的錄制,可以看到所有錄制下來的請求。然后,選擇“File→Export to JMeter”菜單,填寫文件名LifeRayLogin.jmx,將錄制好的腳本導出為JMeter腳本格式。

啟動JMeter并打開剛剛生成的測試腳本。在執行前,需要增加一個監聽器——“查看結果樹”,可以選擇左邊窗口中的“step1”,按右鍵,選擇“添加→監聽器→查看結果樹”。

然后,選擇“運行→啟動”,開始執行腳本。然后,在左邊導航欄內選擇“查看結果樹”,會看到執行的結果,如圖所示。

還可以再增加一個監聽器“用表格查看結果”,然后重新執行測試(按CRTL+R啟動),再選擇“用表格查看結果”,結果如圖所示。

用表格查看結果的顯示界面

請求1+2是訪問主頁的響應時間 6+5= 11 ms;

請求3+4+5是登陸的響應時間 17+17+409=443 ms;

請求6+7是退出的響應時間 13+8=21 ms。

自帶錄制組件—Http代理服務器

如何配置JMeter自帶的腳本錄制功能?在JMeter控制臺的“工作臺”(WorkBench)元件上單擊右鍵,然后選擇添加“HTTP代理服務器”,如下圖所示。這里要為記錄操作進行配置而不是運行測試計劃,所以是在工作臺(WorkBench)上而不是在測試計劃(Test? Plan)上單擊右鍵。 HTTP代理服務器的實現原理就是通過配置瀏覽器的代理服務器而使所有的訪問請求通過JMeter發送,因而JMeter能把訪問過程錄制下來。

HTTP代理服務器的顯示界面

1. “HTTP代理服務器”的配置

代理服務器的端口,默認為8080,可自行修改,但不要與其他應用端口沖突,因為LifeRay使用8080端口,所以代理服務器的端口被改為8000端口。

目標控制器是代理用于存儲生成的數據的控制器,即錄制的腳本存放的位置。默認情況下, JMeter會在當前測試計劃中找一個記錄用的控制器用于存儲,也可選擇測試計劃中的線程組或在下拉菜單中選擇任意控制器來存儲。通常,選默認值就可以。

分組(Grouping)的概念是將一批請求匯總分組,可以把url請求理解為組。在測試計劃中為生成的元件分組,有多個選項:

1) “不對樣本分組”:所有請求全部被羅列;

2) “在組間添加分隔”:加入一個虛擬的、以分割線命名的動作,運行時與“不對樣本分組”沒有區別,無實際意義;

3) “每個組放入一個新的控制器”:執行時按控制器定義輸出結果;

4) “只存儲每個組的第1個樣本”:對于一次url請求、實際很多次http請求的情況,這個選項很好用,因為我們常常并不關心后面的那些請求。

一般可以選擇“只存儲每個組的第1個樣本”,否則,將會原樣錄制URL,包括圖像和JavaScripts腳本在內的頁面。

參考JMeter原版的測試計劃:

1) 記錄HTTP信息頭:錄制request的head信息;

2) 添加斷言:錄制時,加入空的檢查點(須自行填寫內容);

3) Regex matching:錄制時,加入空的正則匹配(須自行填寫內容);

4) 包含模式(Patterns to Include)和排除模式(Patterns to Exclude):幫助過濾一些不需要的訪問請求,如過濾一些靜態文件css、js和圖片。

2. 定時器偏移量

在錄制操作的同時,JMeter會根據設置建立一些定時器,其延遲時間是完全根據真實的操作來設置的。在代理服務器元件中可以增加一個定時器子元件(配置元件),用于告知JMeter在其生成的HTTP請求中自動增加一個定時器。JMeter會自動把實際的延遲時間存儲為一個被命名為T的JMeter變量。因此,如果在代理服務器元件里使用了高斯隨機定時器,就應該在其中的固定延遲偏移(Constant Delay Offset)設置項里添上${T},用于自動引用紀錄的延遲時間。

3. 在瀏覽器中錄制

啟動HTTP代理服務器后,打開瀏覽器(IE、Firefox、Opera等)添加代理,地址填寫本機ip或host name,端口填寫剛剛所設置的代理端口(本例為8000),IE設置代理,如下圖所示。

在IE中設置代理

在瀏覽器地址中鍵入待錄制頁面的URL,然后對頁面進行操作,JMeter就會自動把所進行的操作轉換為測試腳本,可以看到錄制控制器節點下多了許多子節點,它們就是錄制生成的腳本。操作完畢后,在JMeter中單擊“停止”,停止錄制,然后把瀏覽器的代理設置改為原來的設置。我們可以發現HTTP代理服務器錄下的請求,和Badboy錄出的請求是類似的。

4. 線程組屬性設置

在執行腳本前,須要設置線程組(相當于虛擬用戶組)的屬性。線程組為JMeter的主要插件,常用來模擬并發用戶訪問,其內部實現了多線程,而每個線程均獨立運行測試計劃,用戶只要添加、配置即可使用。如果客戶機沒有足夠的能力來模擬高負載(如大于100個并發用戶),可以使用JMeter的分布式測試功能,通過一個JMeter控制臺,遠程控制多個JMeter引擎完成測試。

單擊線程組,在右邊的窗口中設置線程數為20,Ramp-Up Period(in seconds)為1,循環次數選項取消選中永遠,在右邊的框中輸入10,如下圖所示。Ramp-Up Period可理解為負載的啟動周期。例如,上述設置的20個虛擬用戶連接,用了1秒來實現,即每個連接建立用時為50ms。

5. 運行及記錄結果設置

要查看運行的結果還須要加入監聽器。選中線程組,單擊鼠標右鍵選擇“監聽器 ”,再從其列表中選擇所需要的監聽器。

JMeter的腳本開發

介紹JMeter進行性能測試腳本開發,包括使用多線程、斷言、變量和函數等。

1) Access Log Sampler

每天有多少訪問量?如何找到Top10 URL、各個URL并發數分配?這些可以通過產品線上服務器的訪問日志分析得來, JMeter的Access Log Sampler用來實現這些功能的。

要獲得用戶訪問日志就要把webserver配置成擴展日志模式(extended log format)。

因為有些數據是加密的,可以用的錄制腳本登錄,再用Access Log Sampler完成余下的測試。

如何建立Access Log Sampler?先選擇“線程組”,然后按右鍵,選擇菜單“添加→Sampler→Access Log Sampler”,然后按照下圖所示進行設置。

2) 監視器結果

性能測試中服務器的資源監控非常重要,這里先介紹JMeter的“監視器結果(Monitor Result)”,來檢查Tomcat資源的使用情況(內存,線程等)。JMeter的“監視器結果”利用Tomcat本身的特性,說白了就是直接訪問Tomcat服務器的/manager/status,獲得相應的服務器狀態數據并進行呈現。

“監視器結果”是Tomcat 5+設計的,如果應用服務器(AppServer)不是Tomcat 5+,使用“監視器結果”將得不到結果。但是,任何servlet container都可以移植Tomcat 5的status servelet并使用此monitor。LifeRay用到的是Tomcat 6.x,但自帶的Tomcat沒有Manager App,可從Apache網站(http://tomcat.apache.org/)下載一個Tomcat,把其中的Manager App復制到 ${liferayHome}\webapps\manager目錄下,在${liferayHome}\conf\tomcat-users.xml文件中添加以下內容: <role rolename="manager"/>

<role rolename="admin"/>

<user username="admin" password="admin" roles="admin,manager"/>

重啟Tomcat。接下來,可以在JMeter中添加“監視器結果”來監視服務器狀態,步驟如下:

1) 增加一個HTTP Request的Sampler;

2) 選中該新增的HTTP Request,修改其屬性。修改路徑為manager/status,必要時給出服務器的IP地址和Port的值;增加一個參數,該參數的名稱為大寫的XML,值為小寫的true,并選中下方的“用作監視器”,如下圖所示;

設置“HTTP Request”的操作界面

3) 增加一個“監視器結果”的節點;

4) 增加“HTTP授權管理器”和認證信息,因為訪問Tomcat的應用服務器的 /manager/status要給出用戶名和口令,因此,在JMeter中增加一個HTTP授權管理器。選擇“線程組”,然后按右鍵,選擇菜單“添加→配置元件→HTTP授權管理器”,增加一條記錄,包括BaseURL、用戶名和密碼等信息。

在上面這個測試計劃中包含了兩個線程組,一個用來給服務器加壓,另一個用來監控服務器的資源。最后,給服務器加壓的腳本增加“響應斷言”去驗證登錄是否成功。

增加“響應斷言”的操作界面
復雜的分布式大規模壓力測試

當要模擬數以千計的并發用戶時,使用單臺機器模擬所有的并發用戶就有些力不從心,甚至還會引起Java內存溢出的錯誤。JMeter允許用戶從多臺機器啟動JMeter測試,通過使用多臺機器來分擔負載所產生的壓力,并借此來獲取更大的并發用戶數。

某些Web和應用程序服務器可連續處理同一個IP地址的多個請求,以及并行處理不同IP地址的請求,因此,對于一些關鍵測試場合(請求來自不同的機器或將測試負載分布到幾個客戶端),可以使用該選項來執行操作。在具有1.4G~3GHz的CPU、1GB內存的JMeter客戶端上,可以處理線程100~300,但web services是例外。XML處理是CPU運算密集的,會迅速消耗所有的CPU。作為一般規則,以XML技術為中心的應用系統,其性能將是普通web應用的25%~10%。另外,如果所有的負載從一臺機器產生,網卡和交換機端口都可能產生瓶頸,所以一個JMeter客戶端線程數不要超過100。下圖描述了一個多測試機的情景:一臺控制機器(Controller)控制3臺負載產生(機)器。對于下圖的架構,各種平臺上互相調用也是沒有問題的,Windows的JMeter Controller控制Linux的遠程機,或者Linux的JMeter Controller控制Windows的遠程機,而且一般要求負載產生機器與Controller機器上JDK、JMeter的版本一致。

JMeter多測試機的情景

1. 啟動負載產生器的服務

在所有產生負載的機器上啟動JMETER_HOME/bin/jmeter-server.bat (windows) 或JMETER_HOME/bin/jmeter-server (linux) 腳本。

2. 配置Controller機器

把所有負載產生器的IP地址加入到Controller機器上JMeter的配置文件中。編輯Controller機器上的JMeter屬性文件/bin/jmeter.properties,找到“remote_hosts”段,然后增加負載產生器的IP地址,使用逗號分隔。

3. 啟動控制端

在Controller端啟動JMeter,然后在“運行(Run)”菜單下會多出幾個子菜單“Remote Start”、“ Remote Start All”和“Remote Stop”、“Remote Stop All”等。這些子菜單下又會列出所有在屬性文件中增加的IP地址,如下圖所示,可啟動某臺特定的負載產生器(執行腳本)。當然,也可以啟動全部負載產生器,即選擇“Remote Start All”。

啟動遠程負載產生器

4. 手動啟動遠程服務

有些情況下JMeter負載產生器上的腳本可能運行不起來,必須依靠手動的方法來啟動JMeter遠程服務。

1) 首先要運行RMI(Remote Method Invocation,遠程方法調用)注冊程序(名為rmiregistry),因為JMeter使用RMI作為機器間的通信方法。rmiregistry組件在JDK的bin目錄下,須要讀取某些JMeter的類文件,所以在運行它之前,確認在ClassPath環境變量里包含了以下jar包:

JMETER_HOME /lib/ext/ApacheJMeter_core.jar;

JMETER_HOME /lib/jorphan.jar ;

JMETER_HOME /lib/logkit-1.2.jar。

2) 啟動RMI注冊程序(它使用1099端口),然后鍵入“jmeter -s”來啟動JMeter服務。

3) JMeter服務啟動之后,其他步驟和前面一致。

5. 常見問題

1) 在Controller端上啟動遠程機器,沒有成功,系統給出錯誤提示:“Bad call to remote host”。這時,須要檢查被控制機器上的JMeter-server是否啟動。

2) 在Windows中重啟rmiregistry服務很簡單,即首先關閉運行rmiregistry的窗口,然后重新運行rmiregistry;而在Linux下,則應使用ps aux|grep rimregistry查詢該進程的pid,然后使用kill -9 pid殺死該進程,重新啟動。

數據庫性能測試

在大多數企業項目中,數據庫服務器是不可缺少的,其壓力測試是為了找出數據庫對象是否可以有效地承受來自多個用戶的并發訪問。被測試的對象主要有索引、觸發器、存儲過程和鎖等。

利用JMeter,可以測試所用數據庫是否滿足某些指標(例如能夠處理一定數量的并發用戶)。JMeter可以針對各種數據庫產品模擬出繁重的負載,這可以通過JMeter的多線程框架來實現。

以使用LifeRay自帶的默認數據庫HSQL為例來建立一個數據庫測試計劃。為了方便對LifeRay的HSQL進行JDBC測試,要把HSQL的JDBC驅動程序復制到 <jmeter安裝目錄>\lib目錄下。對于LifeRay,在默認安裝情況下,HSQL的JDBC驅動程序的位置為<liferay安裝目錄>\lib\ext\hsql.jar。

通過下面的命令來啟動LifeRay的名叫lportal的數據庫,所有的數據都在<liferay安裝目錄>\lib\lportal.script里。hsqldb保存的就是所有操作的sql語句,如下所示。

? ? D:\liferay\bin>java -cp ..\lib\ext\hsql.jar org.hsqldb.Server -database.0

? ? lportal -dbname.0 lportal

[Server@e0e1c6]: [Thread[main,5,main]]: checkRunning(false) entered

[Server@e0e1c6]: [Thread[main,5,main]]: checkRunning(false) exited

[Server@e0e1c6]: Startup sequence initiated from main() method

[Server@e0e1c6]: Loaded properties from [D:\liferay\bin\server.properties]

[Server@e0e1c6]: Initiating startup sequence...

[Server@e0e1c6]: Server socket opened successfully in 31 ms.

[Server@e0e1c6]: Database [index=0, id=0, db=file:lportal, alias=lportal]

opened sucessfully in 594 ms.

[Server@e0e1c6]: Startup sequence completed in 625 ms.

[Server@e0e1c6]: 2009-04-13 20:32:32.563 HSQLDB server 1.8.0 is online

[Server@e0e1c6]: To close normally, connect and execute SHUTDOWN SQL

[Server@e0e1c6]: From command line, use [Ctrl]+[C] to abort abruptly

數據庫啟動后,我們可以按照下面的步驟用JMeter來完成一個基于LifeRay項目的數據庫測試計劃。

1) 新建一個Thread Group。

2) 新增JDBC Connection Configuration(連接配置)。

3) 點擊新增的JDBC Connection? Configuration,須要修改的參數如下。

JDBC連接配置界面

Variable Name:填入“HSQL”。

Database URL:jdbc: hsqldb:hsql://{host_IP_or_machine_name}:{HSQL監聽器監聽的端口}:{HSQL實例名} ——注意,“{ }” 大括號只用于說明,在配置JMeter時,請將大括號 “{ }”去掉。

JDBC Driver class:org.hsqldb.jdbcDriver。

Username:訪問HSQL實例的用戶名。

Password:對應的密碼。

上面這些數據庫參數從LifeRay中得到:

? ? <liferay安裝目錄>\conf\Catalina\localhost\ROOT.xml

? ? ? <Resource

? ? ? ? ? name="jdbc/LiferayPool"

? ? ? ? ? auth="Container"

? ? ? ? ? type="javax.sql.DataSource"

? ? driverClassName="org.hsqldb.jdbcDriver"

? ? ? ? ? url="jdbc:hsqldb:lportal"

? ? ? ? ? username="sa"

? ? ? ? ? password=""

? ? ? ? ? maxActive="20"

? ? ? />

4) 新增一個JDBC Request,需要修改參數如下。

Variable Name:和上面的JDBC Connection Configuration填寫同樣的內容。這里表示JDBC Connection Configuration建立一個名為Oracle的連接池,之后其他的JDBC Request都共用這個連接池;

Query:select * from table_name 。建議另行使用數據查詢工具,輸入一條SQL查詢語句,保證可以看到執行結果,然后再將SQL語句拷貝到這里。例如,在<liferay安裝目錄>\lib\lportal.script 里有表名。

5) 新增一個View Results Tree。

6) 點擊Run,查看結果。可以在Response data tab看到響應的返回結果。

如果所測試的數據庫是Oracle,請注意以下事項。

1) 執行時提示:No Suitable Driver。在電腦上搜索classes12.jar,然后復制到JMeter的Lib目錄下。如果找不到classes12.jar,就找classes12.zip文件,然后把擴展名改為jar。這里順便說一句,其實classes12.jar并不是最快的Oracle JDBCdriver,如果將classes12.jar和Oranxo.jar(http://www.inetsoftware.de/products/jdbc-driver/oracle/oranxo)比較,Oranxo.jar要快得多。

2) 執行時提示:ORA-00911: invalid? character。確保在JDBC Request里面的Query中輸入的SQL語句是正確的。

JMeter用戶手冊中關于配置通過JDBC對數據庫性能進行測試的部分如下:

http://jakarta.apache.org/jmeter/usermanual/build-db-test-plan.html


本文來自朱少民老師的《輕輕松松自動化測試》,如有侵權,請通知后刪除。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,197評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,415評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,104評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,884評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,647評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,130評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,208評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,366評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,887評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,737評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,939評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,478評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,174評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,586評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,827評論 1 283
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,608評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,914評論 2 372