1.介绍
本节主要解释服务器引导类server boot的核心API的使用。
2.服务器引导进程
ServerBootstrap的用法基本是固定的。通常,刚接触Netty的学生会发现这些模板代码太多,难以理解。我们只需要记住几个核心配置。
指定线程模型:
通过.group(bossGroup, workerGroup) 给引导类配置两大线程组,这个引导类的线程模型也就定型了。其中 bossGroup 表示**端口,accept 新连接的线程组;workerGroup 表示处理每一条连接的数据读写的线程组;
指定 IO 模型:
通过.channel(NioServerSocketChannel.class) 来指定 NIO 模型。如果指定 IO 模型为 BIO,那么这里配置上 OioServerSocketChannel.class 类型即可,通常都是使用 NIO,因为 Netty 的优势就在于 NIO;
指定处理逻辑:
通过 childHandler () 方法,给这个引导类创建一个 ChannelInitializer,这里主要就是定义后续每条连接的数据读写,业务处理逻辑;
绑定端口号:
调用 bind (80),端口号自定义,不要和其他应用的端口号有冲突即可。
3.核心方法
方法说明group()用来指定线程模型channel()用来指定 IO 模型handler()用来指定服务端通道需要处理的业务逻辑(了解)childHandler()用来指定客户端通道需要处理的业务逻辑(掌握)attr()给服务端通道绑定自定义属性(了解)childAttr()给客户端通道绑定自定义属性(掌握)option()给服务端通道设置配置(了解)childOption()给客户端通道设置配置(了解)bind()用来绑定端口号
注意:客户端和服务器连接后,会维护一个通道Channel,可以给它分配逻辑处理器和属性配置;当然,它也是服务器启动时的一个特殊通道。
在开发中,我们需要定制的方法主要是childHandler()和childAttr()。ChildHandler()用于绑定业务逻辑,childAttr()用于设置通道属性。例如,绑定用户身份信息。其他方法的使用比较固定,知道就行。
4.核心方法的详细解释
4.1绑定()
Bind()主要用于绑定本地端口号。
示例:
ChannelFuture future=serverBootstrap.bind(80);future.addListener(new GenericFutureListener<Future<? super Void>>() { public void operationComplete(Future<? super Void> future) { if (future.isSuccess()) { System.out.println("端口绑定成功!"); } else { System.err.println("端口绑定失败!"); } }});
代码升级,如果绑定端口已经存在,端口号递增。当然,实际情况很少会增加端口号。一般是在上线前确定端口号,否则客户端不知道端口号,无法连接。
示例:
private static void bind(ServerBootstrap serverBootstrap, final int port) { ChannelFuture future=serverBootstrap.bind(port); future.addListener(new GenericFutureListener<Future<? super Void>>() { public void operationComplete(Future<? super Void> future) { if (future.isSuccess()) { System.out.println("端口[" + port + "]绑定成功!"); } else { System.err.println("端口[" + port + "]绑定失败!"); //递归重新绑定端口号 bind(serverBootstrap, port + 1); } } });}
4.2属性()
attr()方法可以为服务器的通道指定一些自定义属性,也就是NioServerSocketChannel,可以通过channel.attr()进行检索。
示例:
//省略了其它模板代码serverBootstrap.attr(AttributeKey.newInstance("serverName"), "nettyServer")
综上所述,一般来说attr()用的比较少,知道就好。
4.3 childAttr()
ChildAttr可以为每个连接指定一个自定义属性,该属性可以通过channel.attr()进行检索。
示例:
//省略了其它模板代码serverBootstrap.childAttr(AttributeKey.newInstance("clientKey"), "clientValue")
综上,常见的应用场景,客户端成功登录后,绑定对应的通道标识。下一次,你只需要判断通道是否有标识符就可以知道它是否登录了。
4.4处理程序()
Handler()用于在服务器启动期间指定一些逻辑。
示例:
//省略了其它模板代码serverBootstrap.handler(new ChannelInitializer<NioServerSocketChannel>() { protected void initChannel(NioServerSocketChannel ch) { System.out.println("服务端启动中"); }});
综上所述,可以在服务器启动的过程中做一些初始化工作,比如读取数据库的配置数据,放入缓存中。这可以作为一种理解。
4.5儿童处理器()
Child()用于指定处理新连接数据的读写处理逻辑。
示例:
//省略了其它模板代码serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() { protected void initChannel(NioSocketChannel ch) { //责任链,指定自定义处理业务的 Handler ch.pipeline().addLast(new NettyServerHandler()); }});
综上,这是核心,主要管理业务逻辑,处理双向链表,后面会详细讲解。
4.6选项()
Option()为服务器通道设置一些属性,最常见的是so_backlog。
示例:
//省略了其它模板代码serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024)
指示系统用来临时存储已完成的三次握手请求的队列的最大长度。如果频繁建立连接,而服务器创建新连接的速度很慢,则可以适当调整该参数。事实上,客户机请求也在服务器端排队。服务器端的两个线程组分别监控和处理客户端连接。一旦并发高了,服务器端处理不了,就会把等待处理的请求放到一个临时队列里。这和Java线程池的思想是一样的。
4.7子选项()
ChildOption()为每个连接设置一些与TCP底层相关的属性。
示例:
//省略了其它模板代码serverBootstrap .childOption(ChannelOption.SO_KEEPALIVE, true) .childOption(ChannelOption.TCP_NODELAY, true)
代码描述:
ChannelOption.SO_KEEPALIVE 表示是否开启 TCP 底层心跳机制,true 未开启;ChannelOption.TCP_NODELAY 表示是否开启 Nagle 算法,true 表示关闭,false 表示开启,通俗地说,如果要求高实时性,有数据发送时就马上发送,就关闭,如果需要减少发送次数减少网络交互,就开启。
5.摘要
掌握本节的核心知识点,如下:
四个核心流程,分别是①设置线程组;②设置 IO 模型;③指定连接读写处理逻辑;④绑定端口号;核心方法的使用场景,重点掌握①bind ();②childAttr ();③childHandler ();④childOption () 的使用。
本文来自又何必自找失落╮投稿,不代表舒华文档立场,如若转载,请注明出处:https://www.chinashuhua.cn/24/624623.html