用Java寫壓測(cè)程序(基于Socket)

1.概述

最近,公司服務(wù)器需要做一個(gè)壓力測(cè)試,公司的服務(wù)器,是基于Socket的連接,然后去進(jìn)行數(shù)據(jù)的傳輸。

2.然而,壓測(cè)程序的書寫卻讓我吃力。(以下是我走過的方案)


  • 1 . 最開始,我是直接用傳統(tǒng)的Socket作為連接,然后,一個(gè)程序創(chuàng)建N個(gè)Socket,因?yàn)槠胀ǖ腟ocket是一個(gè)阻塞式的Socket,所以呢,每個(gè)Socket必須對(duì)應(yīng)著一條線程!這樣,從一開始的10線程并發(fā)(慢慢壓上去)到后面的1000線程并發(fā),邏輯上,測(cè)試程序很直觀,一個(gè)線程發(fā)送了請(qǐng)求包,就阻塞等待回包,然后繼續(xù),到最后的1000個(gè),2000個(gè),結(jié)果發(fā)現(xiàn)超出JVM的限制了。所以,這條路,走不通了。

  • 2 . 然后,我就到處找資料,看到網(wǎng)上有一些專業(yè)的壓測(cè)程序:例如,JMeter,LoadRunner等等。然后我就開始研究了。LoadRunner非常專業(yè),但是專業(yè),就很難短時(shí)間入手了,所以我選擇了比較容易入門的JMeter。
    這里介紹一下我入門推介的文章(后期我會(huì)親手寫一下遇到的坑):
    JMeter學(xué)習(xí)(十六)JMeter函數(shù)學(xué)習(xí)
    JMeter學(xué)習(xí)(十七)JMeter測(cè)試Java
    JMeter學(xué)習(xí)(十八)JMeter測(cè)試Java(二)
    這一系列文章能很好的帶你入門!
    在這個(gè)方案上,我掙扎了一天!到了晚上,終于出來的壓測(cè)程序!但是,結(jié)果卻不如人意?。ㄟ@里我想罵人)不過是我自己沒先弄清楚。我以為這個(gè)壓測(cè)軟件是通過別的方法,大概是線程復(fù)用啥的,結(jié)果跑起來,發(fā)現(xiàn)還是跟方案一一樣!跑到了2K個(gè)并發(fā)后,就報(bào)JVM達(dá)到線程數(shù)上限了。(欲哭無淚)大概經(jīng)過了:懷疑自己-懷疑人生-自暴自棄-重新站起來,我繼續(xù)站了起來,不哭繼續(xù)擼!

  • 3 . 繼續(xù)上網(wǎng)扒資料。普通的Socket因?yàn)槭亲枞?dāng)前線程的,所以壓測(cè)量一上去,其弊端就出來了,所以,不能是線程阻塞的!于是我就找到了不阻塞的Socket,使用異步回調(diào)的Socket,嗯,很棒!在這里我粗略介紹一下這個(gè)異步的Socket,其位于:java.nio.channels.AsynchronousSocketChannelNIO包:
    AsynchronousSocketChannel異步Socket,其連接,發(fā)送,接收,都是異步的,其異步回調(diào)的接口如下:(代碼來了,大家不要怕)
public interface CompletionHandler<V,A> 
{
        void completed(V result, A attachment);    
        void failed(Throwable exc, A attachment);
}
  • 這不是一個(gè)函數(shù)式接口,而且也沒有提供者接口的閉包,嗯,有點(diǎn)桑心。
    從函數(shù)的名稱看,completed就是完成時(shí)的回調(diào),failed就是失敗的回調(diào)。
    成功的回調(diào),有V result,這個(gè)東西,在AsynchronousSocketChannel的讀取函數(shù),規(guī)定了V必須是Integer,這個(gè)就是告訴你讀到了多少個(gè)字符。
    而,其他沒規(guī)定,然后呢,A這個(gè)泛型我們就可以自定義啦,一般來說,是傳入AsynchronousSocketChannel的對(duì)象,到如果,你需要給Socket加上一些自定義的屬性,你可以去DIY一個(gè)SocketBean類去包裝。嗯,好像說的有點(diǎn)多了,就先這樣,后期這個(gè)方案我也會(huì)寫篇文章紀(jì)念一下。

  • 又過了快一天(腦子笨+網(wǎng)上資料有點(diǎn)少),我又弄出了一個(gè)異步Socket的壓測(cè),然后,我想到一個(gè)問題,它這個(gè)回調(diào)回是在哪里回調(diào)呢?在原線程嗎?還是在新開線程?如果是新開線程中回調(diào),就又GG了。。。結(jié)果,很悲劇...我竟然忽略這個(gè)問題,TMD在新線程中回調(diào)...如果,我壓測(cè)量又上了2000,那,2K個(gè)發(fā)包,2K個(gè)回包,且在新開線程中?。?!好了,瓶頸又回到了方案一二的瓶頸....


  • 4 .哎,這次真的心累了。不過我這次慢慢地從JAVA AIP文檔查起來,結(jié)果發(fā)現(xiàn)有個(gè)很棒的東西:
    Java NIO系列教程(六) Selector
    這個(gè)NIO中的Selector,引用一下別人的話:

Selector(選擇器)是Java NIO中能夠檢測(cè)一到多個(gè)NIO通道,并能夠知曉通道是否為諸如讀寫事件做好準(zhǔn)備的組件。這樣,一個(gè)單獨(dú)的線程可以管理多個(gè)channel,從而管理多個(gè)網(wǎng)絡(luò)連接。
我...我...欣喜若狂,這就是我要找的Socket。

  • 這種Socket位于:java.nio.channels.SocketChannel,看來NIO包很重要有木有!這個(gè)網(wǎng)上也是很少資料,坑也是一個(gè)一個(gè)的,弄得我不要不要的?。ê竺鏁?huì)出文章說明)
  • 通過Selector,去管理N個(gè)Socket,注意,這個(gè)Selector是跑在一條阻塞的線程上,而其就只需要一條線程!就能管理N個(gè)連接。
  • 通過這個(gè)東西,進(jìn)過1半天的努力,我終于弄粗了一個(gè)壓測(cè)4.0版本,然后隨便改改一個(gè)參數(shù),就上千上萬了嘻嘻。

3 .總結(jié)

這幾天的經(jīng)歷很棒,從一次一次的期望到失望,到一次一次懷疑人生,我都熬過來了,其實(shí)也沒什么了不起的大事情。加油!寫這篇文章,主要是紀(jì)念一下這幾天,和預(yù)告一下我要寫一下幾篇技術(shù)文章(其實(shí)很水),因?yàn)檫@方面網(wǎng)上很少資料!

  • 希望有人期待。(我自己就很期待)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容