2011-11-02 25 views
1

我怎麼能寫一階腳本來做到以下幾點,給定的輸入:如何寫的東西,比如Apache板凳斯卡拉(多線程的方式來打網頁)

url 
total requests 
total connections (threads) 

所以它會request來自給定url的x個網頁,使用x個號碼threads

它應該查看請求的響應以確保它正常(而不是失敗的請求)。

我猜這在Scala中比在Java中更容易,因爲我聽說在Scala中編寫多線程應用程序要容易得多。

所以:

>scalac -url localhost:8080/ -requests 1000 -connections 10 

是否會讓1000個請求,但同時10個線程擊中它。

+2

你聽錯了:在Scala中寫* *併發應用程序要容易得多。主要原因是您不寫_multi-threaded_應用程序。相反,您使用其他併發抽象,這些併發抽象恰好通過線程實現,但您看不到線程。這在這裏很重要,因爲你想保證N個併發線程,這是從你的控制中取走的第一件事情之一。 –

回答

2

我已經寫了一個scala應用程序來做這件事,儘管它是圍繞壓力測試我正在開發的API。使用參與者執行併發請求非常容易。一般的想法是你想創建一個當給出消息時執行單個請求的actor。然後,您創建該actor的多個實例,並使用負載均衡器向其分發請求。

這裏是一個非常簡單的實現,給你一個想法(使用Akka演員):

case class MakeRequest(url: String) 
class RequestActor extends Actor { 

    //force the actor to run in it's own thread 
    self.dispatcher = akka.dispatch.Dispatchers.newThreadBasedDispatcher(self) 

    def receive = { 
    case MakeRequest(url) => //perform the request 
    } 
} 

val totalRequests = 1000 
val url = "http://..." 
val totalConections = 4 

//create one actor per connection and wrap them in a load balancer 
val actors = (0 to totalConnections).map{i => actorOf[RequestActor].start} 
val requestBalancer = loadBalancerActor(new CyclicIterator(actors)) 

//start sending requests 
for (i <- 0 to totalRequests) { 
    requestBalancer ! MakeRequest(url) 
} 

//send a poison pill to stop the actors after they've finished all the requests 
requestBalancer ! Broadcast(PoisonPill) 

//wait for the actors to finish 
while (actors.foldLeft(false){ (b, a) => b || !a.isShutdown}) { 
    Thread.sleep(300) 
} 

//stop the load balancer 
requestBalancer ! PoisonPill 

正如你所看到的,我送MakeRequest消息負載平衡器,橫跨演員分發它們。每個演員都有一個消息隊列,因此一個演員會一次發出一個請求,但是演員一起會同時發出請求。

這個例子沒有提供一種計算響應的方法,並且你冒着溢出演員隊列的風險,但這些很容易解決。我用這個大概的想法來進行廣泛的壓力測試和基準測試,取得了巨大的成功。

+0

那麼你會得到200OK的請求還是失敗?並將其存儲在哪裏?併發收集? – codecompleting

+0

我處理它的方式是創建一個單一的「收藏家」演員,接收來自請求演員的響應。當我創建請求演員時,我給他們一個參考收藏家,所以當他們發出請求時,他們可以將響應發送給它。然後收集器可以自由計算成功和失敗,並將結果輸出到控制檯。 –

0

下面是在Scala中一個簡單的,簡單的方式2.9+,作爲丹尼爾建議,忽略線程:

val url: String 
val totalRequests: Int 
def makeRequest(url: String): Boolean 

val requests = (1 to totalRequests).par.map(i => makeRequest(url)) 
val successes = requests.count(r => r) 
val failures = requests.count(r => !r)