【问题标题】:Concept of vert.x concerning a webserver?vert.x 关于网络服务器的概念?
【发布时间】:2019-05-29 10:40:51
【问题描述】:

我不太明白 vert.x 是如何应用于网络服务器的。

我所知道的网络服务器概念是基于线程的。

  1. 您启动您的网络服务器,然后它正在运行。
  2. 然后,对于每个连接的客户端,您都会获得一个套接字,然后将其传递给它自己的线程处理程序。
  3. 线程处理程序然后处理此特定套接字的任务。

所以明确定义了哪个线程为哪个套接字工作。 但是,对于每个套接字,您都需要一个新线程,从长远来看,这对于许多套接字来说是昂贵的。

然后是 vert.x 提供的基于事件的概念。 到目前为止,我已经理解,它应该像这样工作:

  1. Vertx 实例部署 Verticles。
  2. Verticle 在后台线程中运行,但并非每个 Verticle 都有自己的线程。例如,一个 Vertx 实例中可能部署了 1000 个 Verticle,但 Vertx 实例仅处理 8 个线程(nr of cores * 2)。
  3. 然后是事件循环。我不确定它们是如何指代verticles的。我读过每个 Verticle 都有 2 个事件循环,但我真的不知道它是如何工作的。

作为网络服务器示例:

class WebServer: AbstractVerticle() {
    lateinit var server: HttpServer

    override fun start() {
        server = vertx.createHttpServer(HttpServerOptions().setPort(1234).setHost("localhost"))
        var router = Router.router(vertx);
        router.route("/test").handler { routingContext ->
            var response = routingContext.response();
            response.end("Hello from my first HttpServer")
        }
        server.requestHandler(router).listen()
    }
}

此 WebServer 可以在 Vertx 实例中多次部署。看起来,每个 WebServer 实例都有自己的线程。当我尝试连接 100 个客户端并回复一个简单的响应时,似乎每个客户端都是同步处理的。因为当我在每个服务器处理程序中执行 Thread.sleep 语句时,每秒一个客户端都会收到响应。但是,所有服务器处理程序都应该开始它们的 1 秒睡眠,然后在此时间之后几乎相同地回复所有客户端。

这是启动 100 个客户端的代码:

fun main(){
    Vertx.vertx().deployVerticle(object : AbstractVerticle(){
        override fun start() {
            for(i in 0 .. 100)
                MyWebClient(vertx)
        }
    })
}

class MyWebClient(val vertx: Vertx) {
    init {
        println("Client starting ...")
        val webClient = WebClient.create(vertx, WebClientOptions().setDefaultPort(1234).setDefaultHost("localhost"))
        webClient.get("/test").send { ar ->
            if(ar.succeeded()){
                val response: HttpResponse<Buffer> = ar.result()

                println("Received response with status code ${response.statusCode()} + ${response.body()}")
            } else {
                println("Something went wrong " + ar.cause().message)
            }
        }
    }
}

有人知道这个的解释吗?

【问题讨论】:

    标签: kotlin webserver vert.x vertx-verticle


    【解决方案1】:

    那里有一些主要问题。

    当你这样做时:

    class WebServer: AbstractVerticle() {
        lateinit var server: HttpServer
    
        override fun start() {
            server = vertx.createHttpServer(HttpServerOptions().setPort(1234).setHost("localhost"))
           ...
        }
    }
    

    然后是这样的:

    vertx.deployVerticle(WebServer::class.java.name, DeploymentOptions().setInstances(4)
    

    您将获得 4 个 Verticle,但其中只有一个会真正监听端口。因此,您不会再获得任何并发性。

    其次,当您在 Vert.x 代码中使用 Thread.sleep 时,您会阻塞事件循环线程。

    第三,您对客户的测试不正确。创建 WebClient 非常昂贵,因此通过一个接一个地创建这些,您实际上发出请求的速度非常慢。如果您真的想测试您的 Web 应用程序,请使用 https://github.com/wg/wrk

    【讨论】:

    • wrk 和 Apache 的 ab 用于测试多线程请求有什么明显区别吗?
    • wrk 有一些问题,您应该使用wrk2ab。如果您对更多详细信息感兴趣,请创建一个单独的问题。
    • 好的。我创建了一个单独的问题,请关注this link
    【解决方案2】:

    您的代码的问题是,默认情况下,Vert.x 每个顶点最多只使用一个线程(如果顶点数多于可用线程,则单个线程必须处理多个顶点)。

    因此,如果您对单个 Verticle 的单个实例执行 100 个请求,则这些请求由单个线程处理。

    要解决您的问题,您应该部署多个 Verticle 实例,即

    vertx.deployVerticle(MainVerticle::class.java.name, DeploymentOptions().setInstances(4))
    

    这样做时,几乎同时会收到 4 个响应,因为 4 个 Verticle 实例正在运行,因此使用了 4 个线程。

    在以前的 Vert.x 版本中,如果您不想设置特定数量的实例,也可以简单地为 Verticle 配置多线程。

    vertx.deployVerticle(MainVerticle::class.java.name, DeploymentOptions().setWorker(true).setMultiThreaded(true))
    

    但是,此功能已被弃用,取而代之的是客户工作人员池。

    有关此主题的更多信息,我鼓励您查看Vert.x-core Kotlin documentation

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-23
      • 1970-01-01
      • 2018-09-09
      • 1970-01-01
      相关资源
      最近更新 更多