我正在尝试创建一个可以一次处理100万个请求的简单微服务。但我在客户端遇到连接重置错误。如果我犯了任何错误,请纠正我。
服务器代码 1. 听众:
object Collection {
case class calculate(values:Double)
}
object EngineController{
import Collection._
def main(args: Array[String]): Unit = {
try {
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
implicit val executionContext = system.dispatcher
val requestHandler = system.actorOf(RoundRobinPool(3).props(RequestHandler.props), "round-robin-pool")
val route: Route = {
implicit val timeout = Timeout(100.seconds)
path("aggregate") {
log.info("REQUEST RECEIVED")
post {
entity(as[String]) { values =>
onSuccess(requestHandler ? calculate(values)) {
case result: Double =>
log.info("Response Sent -" + result)
complete(s"${result}")
}
}
}
}
}
val routeBinding :Future[ServerBinding] = Http().bindAndHandle(route, "localhost", 8080)
log.info("Connection Established! Waiting for Request")
routeBinding.failed.foreach { ex =>
log.error(ex, "Failed to bind to {}:{}!", host, port)
}
StdIn.readLine()
routeBinding.flatMap(_.unbind())
system.terminate()
}
catch {
case ex: Exception =>
log.error(ex, ex)
}
}
}
RequestHandler:此actor返回数字的最大值。
object RequestHandler extends App {
def props: Props = {
Props(classOf[RequestHandler])
}
class RequestHandler extends Actor {
var doubleArray: Array[Double] = Array.empty
val system1 = ActorSystem("system2")
var routees: List[ActorRef] = _
override def preStart() = {
routees = List.fill(5)(
context.actorOf(AggregateCalculator.props)
)
}
val aggregateActor = system1.actorOf(AggregateCalculator.props.withRouter(RandomPool(100)), "ag")
//CONVERT STRING TO ARRAY
def stringToArray(values: String): Array[Double] = {
return values.split(",").map(x => x.toDouble)
}
override def receive: Receive = {
case calculate(values) =>
doubleArray = stringToArray(values)
sender() ! doubleArray.max
}
}
}
客户代码:
package Test
import scalaj.http.{Http, HttpResponse}
import org.apache.log4j.Logger
//libraryDependencies += "org.scalaj" % "scalaj-http_2.11" % "2.3.0"
object RequestSender1 {
val log = Logger.getLogger(getClass.getName)
def main(args: Array[String]): Unit = {
try {
val str = "22.78, -1.23, 50, 60, 3, 32, 11, 54, 72, 78, 99, 70, 19, 47, 90, 81, 50, 69, 69, 72, 83, 14.7, 8, 41, 65, 73, 48, 63, 47, 17, 55, 39, 50, 87, 76, 8, 67, 51, 55, 94, 75, 14, 91, 35, 87, 36, 42, 74, 70, 81, 18, 14, 50, 22, 16, 55, 71, 17, 39, 44, 58, 61, 16, 4, 74, 61, 37, 31, 62, 36, 53, 30, 82, 72, 89, 96, 28, 36, 77, 89, 30, 2, 31, 79, 50, 34, 81, 39, 91, 85, 94, 25, 68, 98, 46, 42,14,14"
var result: HttpResponse[String] = null
var counter = 0
for (i <- 1 to 300) {
for (i <- 1 to 13000) {
val thread = new Thread {
override def run {
while (counter < 1000024) {
try {
counter += 1
result = scalaj.http.Http("http://localhost:8080/aggregate").postData(str).timeout(1200000, 120000000) //192.168.0.157:8089
.header("Content-Type", "text/plain").asString
println("Thread Count----" + java.lang.Thread.activeCount())
j += 1
println(result.body + " " + j)
} catch {
case ex:Exception =>
log.error(ex)
}
}
}
}
thread.start
// slow the loop down a bit
}
println("Sent request with --" + i)
Thread.sleep(1)
// slow the loop down a bit
}
}
catch {
case ex:Exception =>
println("Exception"+">>>>>>>>>>")
}
} }
错误1 :
09:58:07 ERROR [Thread-12803] - Test.RequestSender1$.run 32 - java.net.BindException: Address already in use: connect
错误2 :
Thread-12418" java.net.SocketException: Connection reset
对不良对齐
答案 0 :(得分:0)
我认为这与Scala或HTTP无关。这是TCP协议的限制。
不幸的是,您无法从一台计算机创建100万个出站TCP连接。 TCP连接由客户端和服务器的两对(IP地址,端口)指定。服务器可能具有到达同一端口的所有连接,并通过客户端信息区分它们。但是对于任何典型的TCP / IP实现,每个出站连接都会分配给它自己唯一的TCP端口(即使您推出了一些自定义实现,您仍然无法从同一客户端连接到同一服务器/端口的两个传出连接/ port因为它们无法区分)。 TCP port实际上只是一个16位数字。这意味着总共只有大约65,000个端口,这显然远远少于你想要的100万个。因此,要建立100万个连接,您需要同时运行测试的许多计算机(或至少是虚拟机)。