码迷,mamicode.com
首页 > 其他好文 > 详细

AbstractBootstrap的研读

时间:2015-04-01 19:27:19      阅读:214      评论:0      收藏:0      [点我收藏+]

标签:

  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, Object>。怎么处理Channel的IO事件呢,我们添加一个事件处理器ChannelHandler对象。

  1.   private volatile EventLoopGroup group;
  2.   private volatile ChannelFactory channelFactory;
  3.   private volatile SocketAddress localAddress;
  4.   private final Map, Object> options = new LinkedHashMap, Object>();
  5.   private final Map, Object> attrs = new LinkedHashMap, Object>();
  6.   private volatile ChannelHandler handler;

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

Bootstrap

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

  1. private ChannelFuture doConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
  2. final ChannelFuture regFuture = initAndRegister();
  3. final Channel channel = regFuture.channel();
  4. if (regFuture.cause() != null) {
  5. return regFuture;
  6. }
  7. final ChannelPromise promise = channel.newPromise();
  8. if (regFuture.isDone()) {
  9. doConnect0(regFuture, channel, remoteAddress, localAddress, promise);
  10. } else {
  11. regFuture.addListener(new ChannelFutureListener() {
  12. @Override
  13. public void operationComplete(ChannelFuture future) throws Exception {
  14. doConnect0(regFuture, channel, remoteAddress, localAddress, promise);
  15. }
  16. });
  17. }
  18. return promise;
  19. }
下面看下Bootstrap的使用
  1. EventLoopGroup group = new NioEventLoopGroup();
  2. try {
  3. Bootstrap b = new Bootstrap();
  4. b.group(group)
  5. .channel(NioSocketChannel.class)
  6. .option(ChannelOption.TCP_NODELAY, true)
  7. .handler(new ChannelInitializer<SocketChannel>() {
  8. @Override
  9. public void initChannel(SocketChannel ch) throws Exception {
  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(new EchoClientHandler());
  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. private final Map<ChannelOption<?>, Object> childOptions = new LinkedHashMap<ChannelOption<?>, Object>();
  2. private final Map<AttributeKey<?>, Object> childAttrs = new LinkedHashMap<AttributeKey<?>, Object>();
  3. private volatile EventLoopGroup childGroup;
  4. private volatile ChannelHandler childHandler;
这里有必要提下Java的Reactor模式,如下图所示,当然netty对下图的架构进行了修改:一个subReactor一个线程。后面细说。
技术分享
当一个请求来的时候,group接受该请求后,把客户端的Channel传递到childGroup来出来,这样就提供了业务处理能力,group大致对应mainReactor,childGroup对应subReactor和ThreadPool。  因为EventLoopGroup本质就是一个线程池。
  1. p.addLast(new ChannelInitializer<Channel>() { //当有Channel连接该监听端口是调用该
  2. @Override
  3. public void initChannel(Channel ch) throws Exception {
  4. ch.pipeline().addLast(new ServerBootstrapAcceptor(
  5. currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
  6. }
  7. });
仔细看这块代码。主Channel把IO事件派发给子Channel.看下他的使用吧:
  1. EventLoopGroup bossGroup = new NioEventLoopGroup(1);
  2. EventLoopGroup workerGroup = new NioEventLoopGroup();
  3. try {
  4. ServerBootstrap b = new ServerBootstrap();
  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(new LoggingHandler(LogLevel.INFO))
  20. /**
  21. * 子类的Hanlder是NioServerSockerChannel对应的ChannelPipeline的Handler
  22. */
  23. /**
  24. * 区别:ServerBootstrap中的handler是NioServerSocketChannel使用
  25. * 所有连接该监听端口的客户端都会执行它,父类的AbstractBootstrap中的Handler
  26. * 是个工厂类,他为没有新接入的客户端都创建一个新的Handler
  27. */
  28. .childHandler(new ChannelInitializer<SocketChannel>() {
  29. @Override
  30. public void initChannel(SocketChannel ch) throws Exception {
  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(new EchoServerHandler());
  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等东西。





AbstractBootstrap的研读

标签:

原文地址:http://www.cnblogs.com/gaoxing/p/4384784.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!