Концепция vert.x относительно веб-сервера?

Я не совсем понимаю, как vert.x применяется для веб-сервера.

Концепция, которую я знаю для веб-сервера, основана на потоках.

  1. Вы запускаете свой веб-сервер, который затем работает.
  2. Затем для каждого подключающегося клиента вы получаете сокет, который затем передается собственному обработчику потока.
  3. Затем обработчик потока обрабатывает задачи для этого конкретного сокета.

Таким образом, четко определено, какой поток выполняет работу для какого сокета. Однако для каждого сокета вам нужен новый поток, что в конечном итоге дорого для многих сокетов.

Кроме того, существует концепция, основанная на событиях, которую предоставляет vert.x. Насколько я понял, это должно работать так или иначе:

  1. Экземпляр Vertx развертывает Verticles.
  2. Verticle работают в фоновых потоках, но не у каждой Verticle есть собственный поток. Например, в экземпляре Vertx может быть развернуто 1000 вертикалей, но экземпляр Vertx обрабатывает только 8 потоков (количество ядер * 2).
  3. Затем идут циклы событий. Я не уверен, как они относятся к вершинам. Я читал, что каждая вершина имеет 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()
    }
}

Этот веб-сервер может быть развернут несколько раз в экземпляре 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)
            }
        }
    }
}

Кто-нибудь знает объяснение этому?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
367
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Проблема с вашим кодом заключается в том, что по умолчанию Vert.x использует максимум один поток для каждой вершины (если вершин больше, чем доступных потоков, один поток должен обрабатывать несколько вершин).

Таким образом, если вы выполняете 100 запросов к одному экземпляру одной вершины, запросы обрабатываются одним потоком.

Чтобы решить вашу проблему, вы должны развернуть несколько экземпляров вашей вертикали, т.е.

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

при этом всегда будут получены 4 ответа почти одновременно, потому что работают 4 экземпляра вершины и, следовательно, используются 4 потока.

В предыдущих версиях Vert.x вы также могли просто настроить многопоточность для вершины, если не хотели устанавливать определенное количество экземпляров.

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

Однако эта функция устарела и заменена пулами рабочих операций клиентов.

Для получения дополнительной информации по этой теме я рекомендую вам взглянуть на Документация Vert.x-core Kotlin

Ответ принят как подходящий

Там есть несколько серьезных проблем.

Когда вы делаете это:

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 вершины, но только одна из них будет фактически прослушивать порт. Таким образом, вы не получаете больше параллелизма.

Во-вторых, когда вы используете Thread.sleep в своем коде Vert.x, вы блокируете поток цикла событий.

В-третьих, ваш тест с клиентом неверен. Создание WebClient очень дорого, поэтому, создавая их один за другим, вы на самом деле выдаете запросы очень медленно. Если вы действительно хотите протестировать свое веб-приложение, используйте что-то вроде https://github.com/wg/wrk.

есть ли существенная разница между работа и аб Apache для тестирования многопоточных запросов?

NikolaS 24.06.2020 12:23
wrk имеет некоторые проблемы, и вы должны использовать либо wrk2, либо ab. Если вас интересуют подробности, создайте отдельный вопрос.
Alexey Soshin 24.06.2020 15:14

OK. Я создал отдельный вопрос, пожалуйста, подпишитесь на эта ссылка.

NikolaS 28.06.2020 17:47

Другие вопросы по теме