Я не совсем понимаю, как vert.x применяется для веб-сервера.
Концепция, которую я знаю для веб-сервера, основана на потоках.
Таким образом, четко определено, какой поток выполняет работу для какого сокета. Однако для каждого сокета вам нужен новый поток, что в конечном итоге дорого для многих сокетов.
Кроме того, существует концепция, основанная на событиях, которую предоставляет vert.x. Насколько я понял, это должно работать так или иначе:
В качестве примера веб-сервера:
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)
}
}
}
}
Кто-нибудь знает объяснение этому?
Проблема с вашим кодом заключается в том, что по умолчанию 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.
wrk
имеет некоторые проблемы, и вы должны использовать либо wrk2
, либо ab
. Если вас интересуют подробности, создайте отдельный вопрос.
OK. Я создал отдельный вопрос, пожалуйста, подпишитесь на эта ссылка.
есть ли существенная разница между работа и аб Apache для тестирования многопоточных запросов?