BootStrap在netty的应用程序中负责引导服务器和客户端。netty包含了两种不同类型的引导:
1. 使用服务器的ServerBootStrap,用于接受客户端的连接以及为已接受的连接创建子通道。
2. 用于客户端的BootStrap,不接受新的连接,并且是在父通道类完成一些操作。
ServerBootStrap的运行原理
服务端的ServerBootstrap类继承图:
客户端的Bootstrap类继承图:
根据ServerBootstrap源码分析
首先给出一个很简单的基于netty的聊天室的服务端的实例:
package netty.cookbook.simplechat; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import utils.LogUtil; /** * 启动服务端 */ public class SimpleChatServer { private int port; public SimpleChatServer(int port){ this.port = port; } public void run() throws Exception{ //NioEventLoopGroup是用来处理IO操作的多线程事件循环器 //boss用来接收进来的连接 EventLoopGroup bossGroup = new NioEventLoopGroup(); //用来处理已经被接收的连接; EventLoopGroup workerGroup = new NioEventLoopGroup(); try{ //是一个启动NIO服务的辅助启动类 ServerBootstrap sBootstrap = new ServerBootstrap(); //These EventLoopGroup's are used to handle all the events and IO for ServerChannel and Channel's. //为bootstrap设置acceptor的EventLoopGroup和client的EventLoopGroup //这些EventLoopGroups用于处理所有的IO事件 //?这里为什么设置两个group呢? sBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new SimpleChatServerInitializer()) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); LogUtil.log_debug("SimpleChatServer 启动了"); //绑定端口,开始接收进来的连接 ChannelFuture future = sBootstrap.bind(port).sync(); //等待服务器socket关闭 //在本例子中不会发生,这时可以关闭服务器了 future.channel().closeFuture().sync(); } finally { // workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); LogUtil.log_debug("SimpleChatServer 关闭了"); } } public static void main(String[] args) throws Exception { new SimpleChatServer(8080).run(); } }
根据上面的实例分析ServerBootStrap的运行流程:
1.实例化ServerBootstrap
ServerBootstrap sBootstrap = new ServerBootstrap();
2.配置ServerBootstrap的group()
//boss用来接收进来的连接 EventLoopGroup bossGroup = new NioEventLoopGroup(); //用来处理已经被接收的连接; EventLoopGroup workerGroup = new NioEventLoopGroup(); sBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new SimpleChatServerInitializer()) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true);
从上面可知,上面创建了两个EventLoopGroup,分别是boss和worker,然后配置到ServerBootstrap的group中。我们先来看看ServerBootstrap.group(),这个函数有两个重载的实现:
public ServerBootstrap group(EventLoopGroup group) { return group(group, group); } public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) { super.group(parentGroup); if (childGroup == null) { throw new NullPointerException("childGroup"); } if (this.childGroup != null) { throw new IllegalStateException("childGroup set already"); } this.childGroup = childGroup; return this; }
这里如果调用只传入了一个EventLoopGroup,最后也会调用group(EventLoopGroup parentGroup, EventLoopGroup childGroup)。 传入的两个EventLoopGroup分别叫做parentGroup和childGroup。
其实我觉得更加好理解的方式应该叫boss和worker。boss这个EventLoopGroup作为一个acceptor负责接收来自客户端的请求,然后分发给worker这个EventLoopGroup来处理所有的事件event和channel的IO。
查看上面的源码,我们可知,首先调用的是
super.group(parentGroup);
这个方法调用了ServerBootstrap的父类AbstractBootstrap的group(EventLoopGroup group) 方法,下面看看AbstractBootstrap中方法的定义:
public B group(EventLoopGroup group) { //传参不能为空 if (group == null) { throw new NullPointerException("group"); } //AbstractBootstrap的group属性如果非空,就抛出异常,说明this.group是单例的 if (this.group != null) { throw new IllegalStateException("group set already"); } this.group = group; return (B) this; }
从上面的源码AbstractBootstrap里面的这个this.group属性是单例的。我们先看看该属性的定义:
volatile EventLoopGroup group;
这里定义的是volatile的变量,提供可见性,而且变量是包级别的权限。最后将传入的EventLoopGroup赋值给AbstractBootstrap的group属性。
后面的ServerBootstrap的childGroup也是同样的实现,不过childGroup是单例的赋值给了ServerBootstrap的childGroup属性。ServerBootstrap中的定义如下:private volatile EventLoopGroup childGroup;
关于EventLoopGroup下的parentGroup和childGroup(boss线程池和worker线程池):
boos线程:监听服务端口,查看当前端口主要做了哪些事情
worker线程:当boos接收(accept)到一个客户(client)的请求,boos会安排一个worker,这个worker全程为这位客户服务(read/write)。如果当前端口业务繁忙,一个worker可能会为多个客户进行服务。这就是Netty里面Boss和worker之间的关系。
3.配置ServerBootstrap的channel()
这里以聊天室的实例为例
ServerBootstrap.channel(NioServerSocketChannel.class)
实际上是调用的是AbstractBootstrap里面的channel()函数,下面先粘贴出该方法的源码:
public B channel(Class<? extends C> channelClass) { if (channelClass == null) { throw new NullPointerException("channelClass"); } return channelFactory(new ReflectiveChannelFactory<C>(channelClass)); }
这里传入的是一个Class对象,根据传入的不同的Class对象,实例化不同的Channel,主要是有两种代表NIO和OIO的对象:NioServerSocketChannel和OioServerSocketChannel(两个对象会在另一篇博客中进行分析)。在函数体的最后调用:
channelFactory(new ReflectiveChannelFactory<C>(channelClass));
参数里面实例化了一个 ReflectiveChannelFactory对象,这个对象实现了ChannelFactory这个接口的。
下面进入这个函数,最后调用的是:
public B channelFactory(ChannelFactory<? extends C> channelFactory) { //判断传参非空 if (channelFactory == null) { throw new NullPointerException("channelFactory"); } //AbstractBootstrap的channelFactory属性非空 if (this.channelFactory != null) { throw new IllegalStateException("channelFactory set already"); } //传递给channelFactory属性 this.channelFactory = channelFactory; return (B) this; }
最后是把new的ReflectiveChannelFactory传递给了AbstractBootstrap的channelFactory属性,该属性定义如下:
private volatile ChannelFactory<? extends C> channelFactory;
4.配置ServerBootstrap的childHandler(ChannelHandler childHandler)
该函数的主要作用是设置channelHandler来处理客户端的请求的channel的IO。
这里我们一般都用ChannelInitializer这个类的实例或则继承自这个类的实例,在我的聊天室程序中实例如下:
ServerBootstrap.childHandler(new SimpleChatServerInitializer())
这里我是通过新建类SimpleChatServerInitializer继承自ChannelInitializer。具体的代码如下:
/** * 用来增加多个的处理类到ChannelPipeline上:包括编码,解码,SimpleChatServerHandler */ public class SimpleChatServerInitializer extends ChannelInitializer<SocketChannel>{ @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); pipeline.addLast("decoder", new StringDecoder()); pipeline.addLast("encoder", new StringEncoder()); pipeline.addLast("handler", new SimpleChatServerHandler()); System.out.println("SimpleChatClient:" + ch.remoteAddress()+"连接上"); } }
关于ChannelInitializer这个类可知道它最终是继承自ChannelHandler,这个类其实是往pipeline中添加了很多hannelHandler。在ServerBootstrap.childHandler(ChannelHandler childHandler)中的实现:
public ServerBootstrap childHandler(ChannelHandler childHandler) { if (childHandler == null) { throw new NullPointerException("childHandler"); } this.childHandler = childHandler; return this; }
由最后一句可知,其实就是讲传入的childHandler赋值给ServerBootstrap的childHandler属性。
5.配置ServerBootstrap的option(ChannelOption option, T value)
这里调用的是父类的AbstractBootstrap的option()方法,源码如下:
public <T> B option(ChannelOption<T> option, T value) { if (option == null) { throw new NullPointerException("option"); } if (value == null) { synchronized (options) { options.remove(option); } } else { synchronized (options) { options.put(option, value); } } return (B) this; }
其中最重要的一行代码就是:
options.put(option, value);
这里用到了options这个参数,在AbstractBootstrap的定义如下:
private final Map<ChannelOption<?>, Object> options = new LinkedHashMap<ChannelOption<?>,Object>();
可知是私有变量,而且是一个Map集合。这个变量主要是设置TCP连接中的一些可选项,而且这些属性是作用于每一个连接到服务器被创建的channel。
6.配置ServerBootstrap的childOption(ChannelOption childOption, T value)
这里调用的是父类的ServerBootstrap的childOption()方法,源码如下:
public <T> ServerBootstrap childOption(ChannelOption<T> childOption, T value) { if (childOption == null) { throw new NullPointerException("childOption"); } if (value == null) { synchronized (childOptions) { childOptions.remove(childOption); } } else { synchronized (childOptions) { childOptions.put(childOption, value); } } return this; }
这个函数功能与option()函数几乎一样,唯一的区别是该属性设定只作用于被acceptor(也就是boss EventLoopGroup)接收之后的channel。
相关推荐
3. **ServerBootstrap类**:这是Netty中启动服务器的主要入口点。在API接口文档中,你会看到如何配置ServerBootstrap以设置各种参数,如线程池、管道工厂等。 4. **Pipeline和Handler**:Netty使用Pipeline来处理...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。这个“netty-4.1.9.Final”版本是Netty框架的稳定版本,提供了完整的开发包,包含了所有必要的jar文件,以便...
- `ServerBootstrap`配置文件:这是Netty中启动服务器的入口,用来配置服务器的线程模型、处理器管道以及绑定的端口等。 - `WebSocketServerHandler`类:处理WebSocket连接的自定义处理器,会实现心跳检查、消息收发...
在Netty-SocketIO-Demo中,首先需要设置一个ServerBootstrap,指定一个NioEventLoopGroup作为工作线程组,并配置ChannelInitializer来添加自定义的ChannelHandler。然后,通过bind方法绑定监听的端口,启动服务器。 ...
import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel....
在实际应用中,开发者可以根据需要选择使用Netty提供的各种组件,如创建ServerBootstrap来启动服务器,定义ChannelPipeline配置处理器,以及编写自定义的ChannelInboundHandler和ChannelOutboundHandler来处理入站和...
在项目中,开发者通常会定义一个`ServerBootstrap`,它是Netty的启动类,用于初始化服务器的配置,如线程池、事件循环组、处理器链等。接着,会设置服务器监听的端口,并绑定处理器,这些处理器会处理接收到的客户端...
5. **Bootstrap** 和 **ServerBootstrap**:Bootstrap 用于创建客户端连接,ServerBootstrap 用于启动服务器。它们允许配置各种参数,如 EventLoopGroup(处理 I/O 事件的线程组)、Channel 实例等。 在 JavaNetty ...
3. 实现Netty的ServerBootstrap,配置线程池、通道处理器和绑定端口等。 4. 将Netty服务器作为Spring Boot的一个Bean注入到Spring容器中,以便于管理和控制。 5. 使用Spring的Service或Repository层处理业务逻辑,与...
6. **Bootstrap和ServerBootstrap**: Bootstrap用于创建客户端连接,ServerBootstrap用于创建服务端监听。它们分别定义了客户端和服务器的配置,并用于启动连接或监听。 7. **Handlers**: Netty提供了一系列预定义...
这涉及到创建一个ServerBootstrap,配置ChannelPipeline,添加适当的处理器(如DelimiterBasedFrameDecoder用于按特定分隔符解码数据),以及编写处理接收到的数据的业务逻辑。 此外,你可能还会遇到如何实现HTTP...
通过“Netty-API-文档中文版”,你可以详细了解到如何创建ServerBootstrap、Bootstrap、ChannelFuture、ChannelInboundHandlerAdapter等核心组件,以及如何配置和使用各种编解码器。文档还会介绍如何进行连接管理、...
Netty的核心组件包括Bootstrap(启动器)、ServerBootstrap(服务器启动器)、Channel(通道)、EventLoop(事件循环)和ChannelHandler(处理程序)。通过这些组件,开发者可以方便地创建出可伸缩、低延迟的网络...
这个压缩包“掘金-Netty 入门与实战-netty-demo.zip”包含了关于 Netty 的入门教程和实战示例,特别是通过 "netty-demo-pipeline-channelHandler" 这个文件名我们可以推测,它可能包含了一个展示 Netty ...
在使用时,可以参考Netty的官方文档,了解如何配置EventLoopGroup、创建ServerBootstrap、添加处理器等步骤,逐步搭建起一个完整的网络服务器。同时,也要注意版本兼容性和性能优化,以便在实际应用中发挥出Netty的...
然后,可以通过创建一个ServerBootstrap实例来配置服务器,指定绑定的端口和处理客户端连接的ChannelHandler。对于客户端,可以创建一个Bootstrap实例并配置连接到服务器的参数。Netty的API设计使得这些操作非常直观...
5. **Netty服务器**:在Netty中创建ServerBootstrap,配置BossGroup和WorkerGroup,指定通道处理器。使用WebSocketFrameDecoder和WebSocketFrameEncoder处理WebSocket帧。 6. **连接监听**:当新的客户端连接到达时...
2. **配置文件**:可能有 Netty 的配置,如 EventLoopGroup 的设置、ServerBootstrap 的配置等。 3. **测试用例**:用于验证 Netty 应用程序的正确性,通常包括启动服务器、连接到服务器、发送和接收数据的测试步骤...
1. **ObjectServerMain**: 这是服务器端程序,它创建一个 ServerBootstrap 实例,配置 EventLoopGroup(通常为 NioEventLoopGroup)和 Channel(通常是 NioServerSocketChannel)。然后,它设置 Pipeline,添加...
在启动时,我们会创建一个 EventLoopGroup(负责事件循环)和 ServerBootstrap(服务器引导类)或者 Bootstrap(客户端引导类),然后绑定监听端口或连接目标地址。 总的来说,“netty-websocket-example”项目是一...