vertx框架编程思想

vertx框架编程思想

vert.x编程简介:

初始化一个vertx实例,
使用一个启动verticle部署多个verticle,每个verticle都有自己的使命,它们公用一个vertx实例,
vertx是基于事件驱动,verticle部署时指定接受通知后的下一步操作,
它们之间通过eventbus通信,通过eventbus消息总线异步通知每个verticle进行消息处理;
vert.x为verticle提供Event Loop线程执行非阻塞操作,
阻塞操作可以通过vertx实例创建worker-thread线程进行业务相关比较耗时的操作。

为什么选用vertx框架

vertx 线程模型是线程安全的,不需要RD再投入过多的精力考虑多线程下编程的问题,并且初中级程序员也很难写出优雅的多线程代码;vertx框架的扩展组件丰富,支持HTTP2/MONGO/REDIS/CIRCUIT-BREKER/KOTILN/等等

vert.x线程安全的线程模型

为了充分利用多核CPU的性能,Vert.x中提供了一组Event Loop线程 基于Netty的NioEventLoopGroup实现。
每个Event Loop线程都可以处理事件。为了保证线程安全,防止资源争用,
Vert.x保证了某一个Handler总是被同一个Event Loop线程执行,
这样不仅可以保证线程安全,而且还可以在底层对锁进行优化提升性能
注意:在部署Verticle的时候,vert.x会根据配置创建一个Context并绑定到verticle上,以后该verticle绑定的Handler都会在该Context上执行,Context对应唯一一个EventLoop线程,而一个EventLoop线程对应多个Context,so 每个Handler都会在同一个EventLoop线程下执行,从而保证线程的安全

vertx事件模型流程

Vert.x以非阻塞IO的思想来实现高性能,非阻塞IO的实现,基于Event Loop Vertical和Worker Vertical的分离,
在Vert.x中,Event Loop用于接收,并将短业务操作交由其内部的Vertical来处理,该模块是非阻塞的,这样可以保证请求的处理效率;
阻塞任务通过Vert.x的事件机制脱离当前线程,转移到Worker Vertical中执行,并执行结果返回给Event Loop Vertical。
vert.x-worker-thread
vert.x-eventloop-thread
这一过程完成的核心是Event Bus,Event Bus中注册了所有的事件,通过事件匹配完成事件转移和结果返回,从而将整个流程衔接起来。

vertx结合kotlin-coroutines

vertx-lang-kotlin-coroutines集成了Kotlin coroutines,用于执行异步操作和事件处理。
这导致看起来像在使用同步执行代码的编程模型,但它并不阻塞内核线程。
vertx-lang-kotlin-coroutines使用协程: 协程是非常轻量级的线程,不同于底层内核线程,
因此当协程需要“阻塞”时,它将被暂停并释放其当前的内核线程,以便另一个协程可以处理事件

coroutines是异步回调的替代者

//标准vert.x timerAPI写法
vertx.setTimer(1000, tid -> {
    System.out.println("Event fired from timer")
});

//使用coroutines
  launch(vertx.dispatcher()) {
    awaitEvent<Long> { handler ->
      vertx.setTimer(1000, handler)
    }
    println("Event fired from timer")
  }
  • awaitEvent

The awaitEvent function suspends the execution of the coroutine until the timer fires and returns the value that was given to the handler
awaitEvent方法暂停执行协程,直到定时器返回结果给handler

标准的vert.x timerAPI是异步的,且逻辑也是写在回调Handler里的,所以代码看起来会是嵌套的,
但是上面的coroutines例子你会发现没有这个问题,所有的逻辑都是在变量timerId后面,
也就是说逻辑是线性的,直觉符合人类的思考方式,你会觉得上面的会阻塞1秒下面才会执行。

还需要想办法把vert.x的回调型API改成同步的,所以这里你会看到一个新的方法awaitEvent,
通过这个方法可以把handler(异步回调)以协程的方式进行处理,从而可以直接得到一个返回值,使之变成同步返回

  • awaitResult

    vertx 中存在很多这种Handler< AsynResult<…>>
    可以通过awaitResult 绑定该种类型的handler,以顺序的方式获取异步代码的执行结果

  • launch or suspend

可以通过这两种方式在代码中使用协程,如下:

    /**
      *awaitResult方法暂停执行协程,直到定时器返回结果给handler
     */
    suspend fun awaitResultExample(){
        val eb = vertx.eventBus()
        //注册消息的监听
        val message : MessageConsumer<String> = eb.consumer<String>("com.sdmjhca")
        message.handler { message ->
            println("msg received : ${message.body()}"+System.currentTimeMillis())
            message.reply("地瓜,你好,收到")
        }

        //开始发送消息,等待响应
        val res = awaitResult<Message<String>> { handler ->
            println(Thread.currentThread().name+"开始发送消息")
            //eb.send("com.sdmjhca","土豆,你好,收到请回复")
            //调用eb发送消息,并将发送的结果,付给handler
            eb.send("com.sdmjhca","土豆,你好,收到请回复",handler)
        }
        println("收到土豆的回复 : ${res.body()}"+System.currentTimeMillis())
    }

--------------------------------------

/**
     * process one-shot event
     * Calling launch allows running Vert.x handlers on a coroutine
     * with no suspend
     */
     fun awaitEventExample(){
        launch(vertx.dispatcher()){
            var timerId = awaitEvent<Long> { h: Handler<Long> ->
                vertx.setTimer(1000,h)
                println("定时器将在1秒后执行="+System.currentTimeMillis())
            }

            println("定时器执行完成Event fired from timer with id $timerId -------------"+System.currentTimeMillis())
        }
    }

vertx 相关代码的demo : https://github.com/sdmjhca/demo


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章