• AbstractBootstrap的研读


      AbstractBootstrap是一个工具类,用来配置和启动Channel的,下面看下AbstractBootstrap的类继承,ServerBootstrap用于启动ServerChannel的,是服务端的工具类,Bootstrap是用于启动Channel,是客户端的工具类,bind用于udp等无连接的传输,bind用于有连接的传输。

      AbstractBootstrap

      该类用来配置启动一个Channel,那么配置启动一个Channel需要那些条件?首先需要一个Channel,AbstractBootstrap提供了一个ChannelFactory对象用来创建Channel,一个Channel会对应一个EventLoop用于IO的事件处理,在Channel的整个生命周期中会绑定一个EventLoop,这里可理解给Channel分配一个线程进行IO事件处理,结束后回收该线程,但是AbstractBootstrap没有提供EventLoop而是提供了一个EventLoopGroup,EventLoop继承EventLoopGroup,在某些情况下可以把EventLoopGroup当EventLoop来用,EventLoopGroup中包含多个Eventloop,当一个连接到达,Netty会注册一个Channel,然后EventLoopGroup会分配一个EventLoop绑定到这个channel。不管是服务器还是客户端的Channel都需要绑定一个本地端口这就有了SocketAddress类的对象localAddress,Channel有很多选项所有有了options对象LinkedHashMap<channeloption<?>, Object>。怎么处理Channel的IO事件呢,我们添加一个事件处理器ChannelHandler对象。

    1.   privatevolatileEventLoopGroup group;
    2.   privatevolatileChannelFactory channelFactory;
    3.   privatevolatileSocketAddress localAddress;
    4.   private final Map,Object> options =newLinkedHashMap,Object>();
    5.   private final Map,Object> attrs =newLinkedHashMap,Object>();
    6.   privatevolatileChannelHandler handler;

      AbstractBootstrap还有一个重要方法doBind(),为什么这个方法会在父类实现而不是在ServerBootstrap中实现,注解里面写了bind()方法不仅可以在ServerBootstrap中绑定一个端口用于监听,也可以用在BootStrap中用于无连接的数据传输。这里主要调用Channel的bind方法。因为netty中多有的操作都是异步的。所以所有IOC操作都返回future的子类。然后判断是否OK,有时间写一篇该文章。

    Bootstrap

    客户端的帮助类,用来配置启动一个channel,该类有2个主要方法,一个init用于初始化通道,一个是doConnect(),这里面会生成一个客户端的Channel。

    1. privateChannelFuture doConnect(finalSocketAddress remoteAddress,finalSocketAddress localAddress){
    2. finalChannelFuture regFuture = initAndRegister();
    3. finalChannel channel = regFuture.channel();
    4. if(regFuture.cause()!=null){
    5. return regFuture;
    6. }
    7. finalChannelPromise promise = channel.newPromise();
    8. if(regFuture.isDone()){
    9. doConnect0(regFuture, channel, remoteAddress, localAddress, promise);
    10. }else{
    11. regFuture.addListener(newChannelFutureListener(){
    12. @Override
    13. publicvoid operationComplete(ChannelFuture future)throwsException{
    14. doConnect0(regFuture, channel, remoteAddress, localAddress, promise);
    15. }
    16. });
    17. }
    18. return promise;
    19. }
    下面看下Bootstrap的使用
    1. EventLoopGroup group =newNioEventLoopGroup();
    2. try{
    3. Bootstrap b =newBootstrap();
    4. b.group(group)
    5. .channel(NioSocketChannel.class)
    6. .option(ChannelOption.TCP_NODELAY,true)
    7. .handler(newChannelInitializer<SocketChannel>(){
    8. @Override
    9. publicvoid initChannel(SocketChannel ch)throwsException{
    10. ChannelPipeline p = ch.pipeline();
    11. if(sslCtx !=null){
    12. p.addLast(sslCtx.newHandler(ch.alloc(), HOST, PORT));
    13. }
    14. //p.addLast(new LoggingHandler(LogLevel.INFO));
    15. p.addLast(newEchoClientHandler());
    16. }
    17. });
    18. // Start the client.
    19. ChannelFuture f = b.connect(HOST, PORT).sync();//
    20. // Wait until the connection is closed.
    21. f.channel().closeFuture().sync();
    22. }finally{
    23. // Shut down the event loop to terminate all threads.
    24. group.shutdownGracefully();
    25. }
    ServerBootstrap:
    这个用于配置和启动服务端的Channel,该类添加了几个新的成员属性:
    1. privatefinalMap<ChannelOption<?>,Object> childOptions =newLinkedHashMap<ChannelOption<?>,Object>();
    2. privatefinalMap<AttributeKey<?>,Object> childAttrs =newLinkedHashMap<AttributeKey<?>,Object>();
    3. privatevolatileEventLoopGroup childGroup;
    4. privatevolatileChannelHandler childHandler;
    这里有必要提下Java的Reactor模式,如下图所示,当然netty对下图的架构进行了修改:一个subReactor一个线程。后面细说。
    当一个请求来的时候,group接受该请求后,把客户端的Channel传递到childGroup来出来,这样就提供了业务处理能力,group大致对应mainReactor,childGroup对应subReactor和ThreadPool。  因为EventLoopGroup本质就是一个线程池。
    1. p.addLast(newChannelInitializer<Channel>(){//当有Channel连接该监听端口是调用该
    2. @Override
    3. publicvoid initChannel(Channel ch)throwsException{
    4. ch.pipeline().addLast(newServerBootstrapAcceptor(
    5. currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
    6. }
    7. });
    仔细看这块代码。主Channel把IO事件派发给子Channel.看下他的使用吧:
    1. EventLoopGroup bossGroup =newNioEventLoopGroup(1);
    2. EventLoopGroup workerGroup =newNioEventLoopGroup();
    3. try{
    4. ServerBootstrap b =newServerBootstrap();
    5. b.group(bossGroup, workerGroup)
    6. /**
    7. * 设置服务端的Channel,Netty通过Channel工厂类创建不同的Channel,对于服务端,
    8. * Netty需要创建NioServerSocketChannel,
    9. */
    10. .channel(NioServerSocketChannel.class)
    11. /**
    12. * 设置TCP的参数,这里设置了套接字的最大连接个数。
    13. */
    14. .option(ChannelOption.SO_BACKLOG,100)
    15. /**
    16. * 设置父类的Handler,父类的handler是客户端新接入的接连SocketChannel对应的ChannelPipeline
    17. * 的handler
    18. */
    19. .handler(newLoggingHandler(LogLevel.INFO))
    20. /**
    21. * 子类的Hanlder是NioServerSockerChannel对应的ChannelPipeline的Handler
    22. */
    23. /**
    24. * 区别:ServerBootstrap中的handler是NioServerSocketChannel使用
    25. * 所有连接该监听端口的客户端都会执行它,父类的AbstractBootstrap中的Handler
    26. * 是个工厂类,他为没有新接入的客户端都创建一个新的Handler
    27. */
    28. .childHandler(newChannelInitializer<SocketChannel>(){
    29. @Override
    30. publicvoid initChannel(SocketChannel ch)throwsException{
    31. ChannelPipeline p = ch.pipeline();
    32. if(sslCtx !=null){
    33. p.addLast(sslCtx.newHandler(ch.alloc()));
    34. }
    35. //p.addLast(new LoggingHandler(LogLevel.INFO));
    36. p.addLast(newEchoServerHandler());
    37. }
    38. });
    39. /**
    40. *每个channel绑定一个ChannelPipeline,一个ChannelPipeline里面添加了很多handler
    41. */
    42. // Start the server.
    43. ChannelFuture f = b.bind(PORT).sync();
    44. // Wait until the server socket is closed.
    45. f.channel().closeFuture().sync();
    46. }finally{
    47. // Shut down all event loops to terminate all threads.
    48. bossGroup.shutdownGracefully();
    49. workerGroup.shutdownGracefully();
    50. }
     
     
     
    下面讲下异步处理的Future等东西。
     





  • 相关阅读:
    手机验证码登录注册--
    防止注册机,登录时-验证码图片的生成=前端vue+后端node
    VUE中数据排序sort() / 数据反转 reverse() 的使用
    将后台数据数组对象(对象里边包含数组对象)---改为前端想要的数组对象--改变key值(替换)
    vue--ui:antd pro框架--vue.config.js引入高德地图--描绘轨迹
    创建数据库-表-增加,设置主键
    mysql--各种安装包版本安装
    Vuex异步请求存取步骤
    从后往前查找去掉字符串最指定元素
    python安装第三方库
  • 原文地址:https://www.cnblogs.com/gaoxing/p/4384784.html
Copyright © 2020-2023  润新知