在给定输入的情况下,如何编写scala脚本来执行以下操作:
url
total requests
total connections (threads)
因此request
x来自给定url
的x个网页,使用x个threads
。
它应该查看请求的响应,以确保它是正常的(不是失败的请求)。
我猜这在Scala中比在Java中更容易,因为我听说在Scala中编写多线程应用程序要容易得多。
所以:
>scalac -url localhost:8080/ -requests 1000 -connections 10
会产生1000个请求,但同时用10个线程命中它。
答案 0 :(得分:2)
我已经编写了一个scala应用程序来做这件事,虽然它是围绕压力测试我正在开发的API构建的。使用actor执行并发请求非常容易。一般的想法是你想创建一个actor,当给出一个消息时,执行一个请求。然后,您创建actor的多个实例,并使用负载均衡器将请求分发给它们。
这是一个非常简单的实现,可以给你一个想法(使用Akka actor):
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
消息,负载均衡器将它们分配给各个角色。每个actor都有一个消息队列,所以一个actor会一次发出一个请求,但是actor会同时发出请求。
此示例没有提供计数响应的方法,并且您冒着溢出actor的队列的风险,但这些很容易修复。我已经用这个一般的想法进行了广泛的压力测试和基准测试,取得了巨大的成功。
答案 1 :(得分:0)
这是Scala 2.9+中一种简单,天真的方式,正如Daniel建议的那样,忽略了线程:
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)