Vert.x 初体验


前言

Vert.x 核心思想:异步处理

一、Vert.x 是什么?

1.Vert.x 简介

Vert.x 采用类似 Node.js 的 eventloop callback 机制,优势是 Eventloop 是单线程场景下几乎是最快的并发解决方案,但也需要周边生态的支持,比如 DbClient/HttpClient 这些跟 IO 打交道的 API 需要支持异步回调的风格,社区干脆就整合或者自己实现了。整体启动时间大概是同规模 spring boot 工程的四分之一左右,基准内存占用少一半。

Vert.x 底层通信框架依赖于Netty,并封装了对Http协议的支持,因此可以非常方便的进行Web开发,且不依赖于任何中间件,不依赖中间件,编程会变得非常灵活,定制性非常强,安全性也会得到一定层度的提高。

2.Vert.x 优势

  1. Vert.x 支持多种编程语言。
  2. Vert.x 是一个异步非阻塞框架。
  3. Vert.x 不依赖中间件,底层依赖Netty,因此在使用 Vert.x 构建 Web 项目时,不依赖中间件。
  4. Vert.x 具有完善的生态,Vert.x 提供Web客户端操作、数据库操作、NoSQL数据库等操作,清新简洁,但足够使用。
  5. Vert.x 为微服务而生,提供了各种组件来构建基于微服务的应用程序,通过EventBus可以非常容易的进行服务之间的交互,并且提供了HAZELCAST来实现分布式。

3.Web 服务选型

对于实现一个简单的web服务,有很多种选择,简单划为三种:

  1. 使用 Java 中间件来实现,只要下载一个 Tomcat,再编写个 web 项目就可以对外提供服务。这种方式我们完全不需要考虑线程的交互,不需要考虑网络协议,只需要关注业务逻辑,可以说是一种全包的形式。
  2. 使用 Java 原生的 Socket 或者 NIO 来实现,但这种方式比较复杂,对编程功底要求最高,而且很难保证性能和稳定性。这种方式完全需要手动处理,很少会使用这种方式来实现HTTPServer,可以说这是最为原始形式。
  3. 介于全包和原始形式之间,就是用第三方的框架来实现,比如 Vert.x 或者偏底层的 Netty,可以利用框架封装的 API 简单的创建一个 HttpServer,并不需要关注底层的通信协议。这种方式更为灵活,一般来讲性能也更高,并且不依赖中间件。

二、Vert.X Hello World

使用 IDEA 创建普通的 spring boot 项目,然后引入 vertx 依赖,可以选择 maven 或 gradle。

1.引入依赖

依赖如下:

        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-core</artifactId>
            <vertx.version>3.9.4</vertx.version>
        </dependency>

2.代码实现

  1. 创建 MainVerticle 类继承 AbstractVerticle 类,重写 start() 方法。
  2. 事件监听:对于 Spring 容器的一些事件,可以监听并且触发相应的方法。通常的方法有两种:ApplicationListener 接口和 @EventListener 注解。

代码如下:

public class MainVerticle extends AbstractVerticle {

    @Override
    public void start() throws Exception {
        vertx.createHttpServer().requestHandler(req -> {
            req.response().putHeader("content-type", "text/plain")
                    .end("Hello from Vert.x!");
        }).listen(8888, http -> {
            if (http.succeeded()) {
                System.out.println("HTTP server started on port 8888");
            } else {
            }
        });
    }
}
@Slf4j
@SpringBootApplication
public class VertxApplication {

    public static void main(String[] args) {
        SpringApplication.run(VertxApplication.class, args);
    }

    @EventListener 
    public void deployVerticles(ApplicationReadyEvent event) {
        VertxOptions options = new VertxOptions();
        options.setWorkerPoolSize(200);
        Vertx vertx = Vertx.vertx(options);
        // 部署服务
        vertx.deployVerticle(MainVerticle.class.getName(), new DeploymentOptions(),
                result -> {
                    if (result.succeeded()) {
                        log.info("HTTP服务器部署成功");
                    } else {
                        log.error("HTTP服务器部署失败", result.cause());
                    }
                });
    }
}

三、Vert.X Web

Vert.x 提供了 Web 开发组件 vertx-web,提供了许多 Web 开发中常用的功能,比如参数封装、路由、国际化、认证和授权、session 和 cookie 以及模板等,可以非常方便的进行 Web 开发。

1.引入依赖

依赖如下:

        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-core</artifactId>
            <vertx.version>3.9.4</vertx.version>
        </dependency>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-web</artifactId>
            <version>${vertx.version}</version>
        </dependency>

2.代码实现

  1. 服务部署代码同 Hello World

代码如下:

public class RouterVerticle extends AbstractVerticle {

    @Override
    public void start() throws Exception {
        Router router = Router.router(vertx);
        router.route(HttpMethod.GET, "/hello").handler(req -> {
            req.response().putHeader("content-type", "text/plain")
                    .end("Hello from Vert.x!");
        });
        vertx.createHttpServer().requestHandler(router).listen(8888, http -> {
            if (http.succeeded()) {
                System.out.println("HTTP server started on port 8888");
            } else {
                System.err.println("HTTP server started error");
            }
        });
    }
}

四、Vert.x TCP

想要实现一个 http 服务非常简单, 使用 tomcat 或其他中间件就能实现。但是如果要实现 tcp 服务就没那么简单了,因为 tcp 是传输层协议,并不像 http 那样,有服务中间件封装底层的网络协议和线程的交互。要实现一个 tcp 服务,只能自己处理网络和线程问题。

1.引入依赖

依赖如下:

        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-core</artifactId>
            <vertx.version>3.9.4</vertx.version>
        </dependency>

2.代码实现

  1. 创建tcp服务:NetServer
  2. 监听指定端口的请求
  3. 处理请求并响应

代码如下:

server 端

@Slf4j
public class TcpServerVerticle extends AbstractVerticle {

    public static void main(String[] args) {
        Vertx vertx = Vertx.vertx();
        vertx.deployVerticle(TcpServerVerticle.class.getName(), new DeploymentOptions(),
                result -> {
                    if (result.succeeded()) {
                        log.info("TCP服务器部署成功");
                    } else {
                        log.error("TCP服务器部署失败", result.cause());
                    }
                });
    }

    @Override
    public void start() {
        vertx.createNetServer().connectHandler(socket -> {
            socket.handler(buffer -> {
                // 在这里应该解析报文,封装为协议对象,并找到响应的处理类,得到处理结果,并响应
                System.out.println("接收到的数据为:" + buffer.toString());
                // 按照协议响应给客户端
                socket.write(Buffer.buffer("Server Received"));
            }).closeHandler(close -> {
                System.out.println("客户端退出连接");
            });
        }).listen(9999, res -> {
            if (res.succeeded()) {
                System.out.println("TCP server started on port 9999");
            } else {
                System.err.println("TCP server started error");
            }
        });
    }
}

client 端

public class TcpClientVerticle extends AbstractVerticle {

    public static void main(String[] args) {
        Vertx vertx = Vertx.vertx();
        vertx.deployVerticle(TcpClientVerticle.class.getName());
    }

    @Override
    public void start() throws Exception {
        // 创建一个TCP客户端
        vertx.createNetClient().connect(9999, "localhost", conn -> {
            if (conn.succeeded()) {
                NetSocket socket = conn.result();
                // 向服务器写数据
                socket.write(Buffer.buffer("hello"));
                // 读取服务器的响应数据
                socket.handler(buffer -> System.out.println(buffer.toString()));
            } else {
                System.out.println("连接服务器异常");
            }
        });
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值