PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/finagle-stress/src/main/scala/com/twitter/finagle/stress/EndToEndStress.scala

http://github.com/twitter/finagle
Scala | 97 lines | 83 code | 14 blank | 0 comment | 1 complexity | b15a34a00a9c0bee543b67af4f596dd4 MD5 | raw file
Possible License(s): Apache-2.0
  1. package com.twitter.finagle.stress
  2. import com.twitter.conversions.time._
  3. import com.twitter.finagle.Service
  4. import com.twitter.finagle.builder.{ClientBuilder, ServerBuilder}
  5. import com.twitter.finagle.http.Http
  6. import com.twitter.finagle.stats.OstrichStatsReceiver
  7. import com.twitter.finagle.util.DefaultTimer
  8. import com.twitter.ostrich.stats
  9. import com.twitter.util.{Future, Return, Throw, Stopwatch}
  10. import java.net.{SocketAddress, InetSocketAddress}
  11. import java.util.concurrent.CountDownLatch
  12. import org.jboss.netty.buffer.ChannelBuffers
  13. import org.jboss.netty.handler.codec.http.{
  14. DefaultHttpRequest, HttpVersion, HttpResponseStatus, HttpMethod, HttpHeaders, HttpRequest
  15. , HttpResponse, DefaultHttpResponse}
  16. object EndToEndStress {
  17. private[this] object HttpService
  18. extends Service[HttpRequest, HttpResponse]
  19. {
  20. def apply(request: HttpRequest) = Future {
  21. val response = new DefaultHttpResponse(
  22. request.getProtocolVersion, HttpResponseStatus.OK)
  23. response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, 1)
  24. response.setContent(ChannelBuffers.wrappedBuffer(".".getBytes))
  25. response
  26. }
  27. }
  28. @volatile private[this] var running = true
  29. def dispatchLoop(service: Service[HttpRequest, HttpResponse], latch: CountDownLatch) {
  30. if (!running) {
  31. latch.countDown()
  32. return
  33. }
  34. val request = new DefaultHttpRequest(
  35. HttpVersion.HTTP_1_1, HttpMethod.GET, "/")
  36. val elapsed = Stopwatch.start()
  37. service(request) ensure {
  38. dispatchLoop(service, latch)
  39. } respond {
  40. case Return(_) =>
  41. stats.Stats.addMetric("request_msec", elapsed().inMilliseconds.toInt)
  42. case Throw(_) =>
  43. stats.Stats.incr("failure")
  44. }
  45. }
  46. private[this] def buildServer() = ServerBuilder()
  47. .name("stressServer")
  48. .bindTo(new InetSocketAddress(0))
  49. .codec(Http())
  50. .reportTo(new OstrichStatsReceiver)
  51. .maxConcurrentRequests(5)
  52. .build(HttpService)
  53. private[this] def buildClient(concurrency: Int, addr: SocketAddress) = ClientBuilder()
  54. .name("stressClient")
  55. .reportTo(new OstrichStatsReceiver)
  56. .hosts(Seq(addr))
  57. .codec(Http())
  58. .hostConnectionLimit(concurrency)
  59. .build()
  60. def main(args: Array[String]) {
  61. println("Starting EndToEndStress")
  62. val concurrency = 10
  63. val latch = new CountDownLatch(concurrency)
  64. val elapsed = Stopwatch.start()
  65. val server = buildServer()
  66. val client = buildClient(concurrency, server.localAddress)
  67. DefaultTimer.twitter.schedule(10.seconds) {
  68. println("@@ %ds".format(elapsed().inSeconds))
  69. Stats.prettyPrintStats()
  70. }
  71. 0 until concurrency foreach { _ => dispatchLoop(client, latch) }
  72. Runtime.getRuntime().addShutdownHook(new Thread {
  73. override def run() {
  74. val start = System.currentTimeMillis()
  75. running = false
  76. latch.await()
  77. client.close()
  78. server.close()
  79. println("Shutdown took %dms".format(System.currentTimeMillis()-start))
  80. }
  81. })
  82. }
  83. }