启动

public synchronized void listen(Handler<NetSocket> handler, SocketAddress socketAddress, Handler<AsyncResult<Void>> listenHandler) {
  //检验
if (handler == null) {
throw new IllegalStateException("Set connect handler first");
}
if (listening) {
throw new IllegalStateException("Listen already called");
}
listening = true; listenContext = vertx.getOrCreateContext();
registeredHandler = handler;//逻辑 synchronized (vertx.sharedNetServers()) {// 监听多个不同网络接口(ip:port) Netserver 防止并发
this.actualPort = socketAddress.port();
String hostOrPath = socketAddress.host() != null ? socketAddress.host() : socketAddress.path();
id = new ServerID(actualPort, hostOrPath);
NetServerImpl shared = vertx.sharedNetServers().get(id);
if (shared == null || actualPort == ) { // mutil instances 的情况,利用 mutli core cpu
/**
* frist instances
*/
serverChannelGroup = new DefaultChannelGroup("vertx-acceptor-channels", GlobalEventExecutor.INSTANCE); // 采用单线程池,与HttpServer不同支出
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(availableWorkers);
sslHelper.validate(vertx);//验证ssl相关参数 bootstrap.childHandler(new ChannelInitializer<Channel>() {
@Override
/**
* connection accept 调度切换线程后触发
*/
protected void initChannel(Channel ch) throws Exception {
  //限流策略,读大于写,导致内存无限扩大,最终 OOM
if (isPaused()) {
ch.close();//超过服务承载能力,关闭连接
return;
}
//根据 EventLoop 挑出一个verticle.handlers
HandlerHolder<Handlers> handler = handlerManager.chooseHandler(ch.eventLoop());
if (handler != null) {//逻辑处理不为Null
if (sslHelper.isSSL()) {//是否在TCP基础上添加TLS支持
io.netty.util.concurrent.Future<Channel> handshakeFuture;
if (options.isSni()) {//是否启用sni,单服务多证书情况
VertxSniHandler sniHandler = new VertxSniHandler(sslHelper, vertx);
handshakeFuture = sniHandler.handshakeFuture();
ch.pipeline().addFirst("ssl", sniHandler);
} else {
SslHandler sslHandler = new SslHandler(sslHelper.createEngine(vertx));
handshakeFuture = sslHandler.handshakeFuture();
ch.pipeline().addFirst("ssl", sslHandler);
}
//侦听 TLS handshark
handshakeFuture.addListener(future -> {
if (future.isSuccess()) {
connected(handler, ch);
} else {
Handler<Throwable> exceptionHandler = handler.handler.exceptionHandler;
if (exceptionHandler != null) {
handler.context.executeFromIO(() -> {
exceptionHandler.handle(future.cause());
});
} else {
log.error("Client from origin " + ch.remoteAddress() + " failed to connect over ssl: " + future.cause());
}
}
});
} else {
connected(handler, ch);
}
}
}
}); applyConnectionOptions(bootstrap);//添加Connection Accept之后的附属选项 //添加一个instaces(verticle的Handlers)到handlerManager中
handlerManager.addHandler(new Handlers(handler, exceptionHandler), listenContext); try {
 //绑定指定网络接口
bindFuture = AsyncResolveConnectHelper.doBind(vertx, socketAddress, bootstrap);
//侦听绑定结果
bindFuture.addListener(res -> {
if (res.succeeded()) {
Channel ch = res.result();
log.trace("Net server listening on " + (hostOrPath) + ":" + ch.localAddress()); if (NetServerImpl.this.actualPort != -) {//检查正确性
NetServerImpl.this.actualPort = ((InetSocketAddress)ch.localAddress()).getPort();
}
NetServerImpl.this.id = new ServerID(NetServerImpl.this.actualPort, id.host);
serverChannelGroup.add(ch);
//启动的NetServer服务(verticle)添加到Vertx.sharedHttpMap中
vertx.sharedNetServers().put(id, NetServerImpl.this);
//初始化metrics
VertxMetrics metrics = vertx.metricsSPI();
if (metrics != null) {
this.metrics = metrics.createMetrics(new SocketAddressImpl(id.port, id.host), options);
}
} else {
vertx.sharedNetServers().remove(id);
}
}); } catch (Throwable t) {
if (listenHandler != null) {
 //出现异常回调给上层
vertx.runOnContext(v -> listenHandler.handle(Future.failedFuture(t)));
} else {
log.error(t);
}
listening = false;
return;
}
if (actualPort != ) {//尝试,bind成功,后续失败的情况
vertx.sharedNetServers().put(id, this);
}
actualServer = this;
} else {//other instances
actualServer = shared;
this.actualPort = shared.actualPort();
//初始化metrics
VertxMetrics metrics = vertx.metricsSPI();
this.metrics = metrics != null ? metrics.createMetrics(new SocketAddressImpl(id.port, id.host), options) : null;
//在actualServer基础上添加一个instaces(verticle的Handlers)到handlerManager中
actualServer.handlerManager.addHandler(new Handlers(handler, exceptionHandler), listenContext);
} // 侦听 bind 结果
actualServer.bindFuture.addListener(res -> {
if (listenHandler != null) {
AsyncResult<Void> ares;
if (res.succeeded()) {
ares = Future.succeededFuture();
} else {
listening = false;
ares = Future.failedFuture(res.cause());
}
//结果回调上层
listenContext.runOnContext(v -> listenHandler.handle(ares));
} else if (res.failed()) {
log.error("Failed to listen", res.cause());
listening = false;
}
});
}
return;
}

处理

private void connected(HandlerHolder<Handlers> handler, Channel ch) {
EventLoop worker = ch.eventLoop();
//配置context映射,因为eventloopSize < verticle Size情况 ; 1 eventloop: N verticle
ContextImpl.setContext(handler.context); NetServerImpl.this.initChannel(ch.pipeline());//初始化属性和配置 VertxNetHandler nh = new VertxNetHandler(ctx -> new NetSocketImpl(vertx, ctx, handler.context, sslHelper, metrics)) {
@Override
/**
* 接收消息处理
* @param connection 客户端连接
* @param context 当前 verticle 上下文
* @param msg 接收的消息对象
*/
protected void handleMessage(NetSocketImpl connection, ContextImpl context, ChannelHandlerContext chctx, Object msg) throws Exception {
connection.handleMessageReceived(msg);
}
}; //为了调用close方法释放socket资源
nh.addHandler(conn -> socketMap.put(ch, conn));
nh.removeHandler(conn -> socketMap.remove(ch)); ch.pipeline().addLast("handler", nh);//添加消息逻辑处理 NetSocketImpl sock = nh.getConnection();//获取当前连接
handler.context.executeFromIO(() -> {
if (metrics != null) {
sock.metric(metrics.connected(sock.remoteAddress(), sock.remoteName()));
}
//client connection 处理
handler.handler.connectionHandler.handle(sock);
});
}
 
note: NetServer 与 HttpServer 不同处在Http大量短连接请求,所以采用单独线程池处理connection/accept,
NetServer是单线程池模型,其中有一个EventLoop(Thread)还需额外处理client/accept事件,切记不在
Eventloop中做阻塞操作,需额外处理client/accept 的EventLoop处理时间过长,会造成client connection慢
的现象.

vertx的NetServer模块的更多相关文章

  1. vertx的HttpServer模块

    Start HttpServer /** * 启动 HttpServer * multi instances 采用 synchronized防止线程安全问题 * addHandlers 方法是acto ...

  2. linux安装perl模块

    查询perl CPAN模块   shell>perl -MCPAN -e shell cpan>install module_name   手动安装perl CPAN模块 从 CPAN(h ...

  3. perl模块安装

    转自: http://www.cnblogs.com/itech/archive/2009/08/10/1542832.html http://www.mike.org.cn/blog/index.p ...

  4. vertx模块HAManager高可用

    HAManager public HAManager(VertxInternal vertx, DeploymentManager deploymentManager, ClusterManager ...

  5. vertx模块DeploymentManager部署管理器

    DeploymentManager public DeploymentManager(VertxInternal vertx) { this.vertx = vertx; loadVerticleFa ...

  6. Vertx.vertx()初始框图和模块

    Vertx.vertx()实例 一.构造方法 1. VertxImpl构造方法 选择 transports protocol , default select 模型 if (options.getPr ...

  7. vertx实例的fileSystem文件系统模块

    初始化 //根据OS区分实现 System.getProperty("os.name").toLowerCase(); Utils.isWindows() ? new Window ...

  8. Vertx eventbus模块解析

    eventbus 事件總線 協議棧 TCP分包,粘包解決採用方案: 消息定长(定義消息体總长度),消息分为消息头和消息体 dataType bytes description int 4 包体总大小 ...

  9. 开始学nodejs——net模块

    net模块的组成部分 详见 http://nodejs.cn/api/net.html 下面整理出了整个net模块的知识结构,和各个事件.方法.属性的用法 net.Server类 net.Socket ...

随机推荐

  1. Android数据库优化

    1.索引 简单的说,索引就像书本的目录,目录可以快速找到所在页数,数据库中索引可以帮助快速找到数据,而不用全表扫描,合适的索引可以大大提高数据库查询的效率.(1). 优点大大加快了数据库检索的速度,包 ...

  2. 数据分析三剑客之Matplotlib

    Matplotlib绘图和可视化 简介 我的前面两篇文章介绍了 Nimpy ,Pandas .今天来介绍一下Matplotlib. 简单来说,Matplotlib 是 Python 的一个绘图库.它包 ...

  3. Verilog语言实现并行(循环冗余码)CRC校验

    1 前言 (1)    什么是CRC校验? CRC即循环冗余校验码:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定.循环冗余检查(CRC)是一种数据传输检错功能, ...

  4. (转)调用System.gc没有立即执行的解决方法

    调用System.gc没有立即执行的解决方法 查看源码 当我们调用System.gc()的时候,其实并不会马上进行垃圾回收,甚至不一定会执行垃圾回收,查看系统源码可以看到 /** * Indicate ...

  5. python第十天

    函数 1.函数:完成特定功能的代码块,作为一个整体,对其进行特定的命名,该名字就代表函数 在现实中,很多问题要通过一些工具进行处理==>可以将工具提前生产出来,并命名==>通过名字就可以找 ...

  6. vue的v-model指令

    v-model指令用来绑定表单,数据传值. 如上,当在信息1输入框(表单)中输入值时,数据会对应变化:在信息2输入框中输入值时,数据并未变化. <div id="app"&g ...

  7. cannot update the cursor rep,since it is read-only

    操作DBF文件,开发机器读写都OK,但部署到服务器上后报:cannot update the cursor rep,since it is read-only 网上寻找解决方案英文答案比较多,也没有给 ...

  8. sass补充(2019-3-9)

    @each 输出 格式: @each $var in value,value1,value2{ } eg: @each $var1 in 100px,200px,300px{ .box{ width: ...

  9. J.U.C-三剑客[semaphore\CyclicBarrier\CountDownLatch]

    一.semaphore信号量,底层也是基于AQS 使用: /** * 可以理解为控制某个资源最多有多少个线程同时执行,(比如洗手间,并行与排队) * 如果满了只能等待直到其它资源释放(可以理解为并发量 ...

  10. [译]Async/Await - Best Practices in Asynchronous Programming

    原文 避免async void async void异步方法只有一个目的:使得event handler异步可行,也就是说async void只能用于event handler. async void ...