赵计刚
每天进步一点点

netty4是2.5.6引入的,2.5.6之前的netty用的是netty3。在dubbo源码中相较于netty3,添加netty4主要仅仅改了两个类:NettyServer,NettyClient。还有就是编解码。

使用方式:

服务端:

1 <dubbo:provider server="netty4"/>

客户端:

1 <dubbo:consumer client="netty4" />

 

一、服务端 - NettyServer

  1 package com.alibaba.dubbo.remoting.transport.netty4;
  2 
  3 import com.alibaba.dubbo.common.Constants;
  4 import com.alibaba.dubbo.common.URL;
  5 import com.alibaba.dubbo.common.logger.Logger;
  6 import com.alibaba.dubbo.common.logger.LoggerFactory;
  7 import com.alibaba.dubbo.common.utils.ExecutorUtil;
  8 import com.alibaba.dubbo.common.utils.NetUtils;
  9 import com.alibaba.dubbo.remoting.Channel;
 10 import com.alibaba.dubbo.remoting.ChannelHandler;
 11 import com.alibaba.dubbo.remoting.RemotingException;
 12 import com.alibaba.dubbo.remoting.Server;
 13 import com.alibaba.dubbo.remoting.transport.AbstractServer;
 14 import com.alibaba.dubbo.remoting.transport.dispatcher.ChannelHandlers;
 15 import com.alibaba.dubbo.remoting.transport.netty4.logging.NettyHelper;
 16 
 17 import io.netty.bootstrap.ServerBootstrap;
 18 import io.netty.buffer.PooledByteBufAllocator;
 19 import io.netty.channel.ChannelFuture;
 20 import io.netty.channel.ChannelInitializer;
 21 import io.netty.channel.ChannelOption;
 22 import io.netty.channel.EventLoopGroup;
 23 import io.netty.channel.nio.NioEventLoopGroup;
 24 import io.netty.channel.socket.nio.NioServerSocketChannel;
 25 import io.netty.channel.socket.nio.NioSocketChannel;
 26 import io.netty.util.concurrent.DefaultThreadFactory;
 27 
 28 import java.net.InetSocketAddress;
 29 import java.util.Collection;
 30 import java.util.HashSet;
 31 import java.util.Map;
 32 
 33 public class NettyServer extends AbstractServer implements Server {
 34 
 35     private static final Logger logger = LoggerFactory.getLogger(NettyServer.class);
 36 
 37     private Map<String, Channel> channels; // <ip:port, channel>
 38 
 39     private ServerBootstrap bootstrap;
 40 
 41     private io.netty.channel.Channel channel;
 42 
 43     private EventLoopGroup bossGroup;
 44     private EventLoopGroup workerGroup;
 45 
 46     public NettyServer(URL url, ChannelHandler handler) throws RemotingException {
 47         super(url, ChannelHandlers.wrap(handler, ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME)));
 48     }
 49 
 50     @Override
 51     protected void doOpen() throws Throwable {
 52         NettyHelper.setNettyLoggerFactory();
 53 
 54         bootstrap = new ServerBootstrap();
 55 
 56         bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("NettyServerBoss", true));
 57         workerGroup = new NioEventLoopGroup(getUrl().getPositiveParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS),
 58                 new DefaultThreadFactory("NettyServerWorker", true));
 59 
 60         final NettyServerHandler nettyServerHandler = new NettyServerHandler(getUrl(), this);
 61         channels = nettyServerHandler.getChannels();
 62 
 63         bootstrap.group(bossGroup, workerGroup)
 64                 .channel(NioServerSocketChannel.class)
 65                 .childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE)
 66                 .childOption(ChannelOption.SO_REUSEADDR, Boolean.TRUE)
 67                 .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
 68                 .childHandler(new ChannelInitializer<NioSocketChannel>() {
 69                     @Override
 70                     protected void initChannel(NioSocketChannel ch) throws Exception {
 71                         NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this);
 72                         ch.pipeline()//.addLast("logging",new LoggingHandler(LogLevel.INFO))//for debug
 73                                 .addLast("decoder", adapter.getDecoder())
 74                                 .addLast("encoder", adapter.getEncoder())
 75                                 .addLast("handler", nettyServerHandler);
 76                     }
 77                 });
 78         // bind
 79         ChannelFuture channelFuture = bootstrap.bind(getBindAddress());
 80         channelFuture.syncUninterruptibly();
 81         channel = channelFuture.channel();
 82 
 83     }
 84 
 85     @Override
 86     protected void doClose() throws Throwable {
 87         try {
 88             if (channel != null) {
 89                 // unbind.
 90                 channel.close();
 91             }
 92         } catch (Throwable e) {
 93             logger.warn(e.getMessage(), e);
 94         }
 95         try {
 96             Collection<com.alibaba.dubbo.remoting.Channel> channels = getChannels();
 97             if (channels != null && channels.size() > 0) {
 98                 for (com.alibaba.dubbo.remoting.Channel channel : channels) {
 99                     try {
100                         channel.close();
101                     } catch (Throwable e) {
102                         logger.warn(e.getMessage(), e);
103                     }
104                 }
105             }
106         } catch (Throwable e) {
107             logger.warn(e.getMessage(), e);
108         }
109         try {
110             if (bootstrap != null) {
111                 bossGroup.shutdownGracefully();
112                 workerGroup.shutdownGracefully();
113             }
114         } catch (Throwable e) {
115             logger.warn(e.getMessage(), e);
116         }
117         try {
118             if (channels != null) {
119                 channels.clear();
120             }
121         } catch (Throwable e) {
122             logger.warn(e.getMessage(), e);
123         }
124     }
125 
126     public Collection<Channel> getChannels() {
127         Collection<Channel> chs = new HashSet<Channel>();
128         for (Channel channel : this.channels.values()) {
129             if (channel.isConnected()) {
130                 chs.add(channel);
131             } else {
132                 channels.remove(NetUtils.toAddressString(channel.getRemoteAddress()));
133             }
134         }
135         return chs;
136     }
137 
138     public Channel getChannel(InetSocketAddress remoteAddress) {
139         return channels.get(NetUtils.toAddressString(remoteAddress));
140     }
141 
142     public boolean isBound() {
143         return channel.isActive();
144     }
145 }

netty4的写法与netty3有很大不同,下面是netty3:(http://www.cnblogs.com/java-zhao/p/7625596.html

 1 /**
 2      * 启动netty服务,监听客户端连接
 3      */
 4     @Override
 5     protected void doOpen() throws Throwable {
 6         NettyHelper.setNettyLoggerFactory();
 7         ExecutorService boss = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerBoss", true));
 8         ExecutorService worker = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerWorker", true));
 9         ChannelFactory channelFactory = new NioServerSocketChannelFactory(boss, worker, getUrl().getPositiveParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS));
10         bootstrap = new ServerBootstrap(channelFactory);
11 
12         final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
13         channels = nettyHandler.getChannels();
14         // https://issues.jboss.org/browse/NETTY-365
15         // https://issues.jboss.org/browse/NETTY-379
16         // final Timer timer = new HashedWheelTimer(new NamedThreadFactory("NettyIdleTimer", true));
17         bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
18             public ChannelPipeline getPipeline() {
19                 NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this);
20                 ChannelPipeline pipeline = Channels.pipeline();
21                 /*int idleTimeout = getIdleTimeout();
22                 if (idleTimeout > 10000) {
23                     pipeline.addLast("timer", new IdleStateHandler(timer, idleTimeout / 1000, 0, 0));
24                 }*/
25                 pipeline.addLast("decoder", adapter.getDecoder());
26                 pipeline.addLast("encoder", adapter.getEncoder());
27                 pipeline.addLast("handler", nettyHandler);
28                 return pipeline;
29             }
30         });
31         // bind
32         channel = bootstrap.bind(getBindAddress());
33     }

 

二、客户端 - NettyClient

  1 package com.alibaba.dubbo.remoting.transport.netty4;
  2 
  3 import com.alibaba.dubbo.common.Constants;
  4 import com.alibaba.dubbo.common.URL;
  5 import com.alibaba.dubbo.common.Version;
  6 import com.alibaba.dubbo.common.logger.Logger;
  7 import com.alibaba.dubbo.common.logger.LoggerFactory;
  8 import com.alibaba.dubbo.common.utils.NetUtils;
  9 import com.alibaba.dubbo.remoting.ChannelHandler;
 10 import com.alibaba.dubbo.remoting.RemotingException;
 11 import com.alibaba.dubbo.remoting.transport.AbstractClient;
 12 import com.alibaba.dubbo.remoting.transport.netty4.logging.NettyHelper;
 13 
 14 import io.netty.bootstrap.Bootstrap;
 15 import io.netty.buffer.PooledByteBufAllocator;
 16 import io.netty.channel.Channel;
 17 import io.netty.channel.ChannelFuture;
 18 import io.netty.channel.ChannelInitializer;
 19 import io.netty.channel.ChannelOption;
 20 import io.netty.channel.nio.NioEventLoopGroup;
 21 import io.netty.channel.socket.nio.NioSocketChannel;
 22 import io.netty.util.concurrent.DefaultThreadFactory;
 23 
 24 import java.util.concurrent.TimeUnit;
 25 
 26 public class NettyClient extends AbstractClient {
 27 
 28     private static final Logger logger = LoggerFactory.getLogger(NettyClient.class);
 29 
 30     private static final NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup(Constants.DEFAULT_IO_THREADS, new DefaultThreadFactory("NettyClientWorker", true));
 31 
 32     private Bootstrap bootstrap;
 33 
 34     private volatile Channel channel; // volatile, please copy reference to use
 35 
 36     public NettyClient(final URL url, final ChannelHandler handler) throws RemotingException {
 37         super(url, wrapChannelHandler(url, handler));
 38     }
 39 
 40     @Override
 41     protected void doOpen() throws Throwable {
 42         NettyHelper.setNettyLoggerFactory();
 43         final NettyClientHandler nettyClientHandler = new NettyClientHandler(getUrl(), this);
 44         bootstrap = new Bootstrap();
 45         bootstrap.group(nioEventLoopGroup)
 46                 .option(ChannelOption.SO_KEEPALIVE, true)
 47                 .option(ChannelOption.TCP_NODELAY, true)
 48                 .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
 49                 //.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getTimeout())
 50                 .channel(NioSocketChannel.class);
 51 
 52         if (getTimeout() < 3000) {
 53             bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000);
 54         } else {
 55             bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getTimeout());
 56         }
 57 
 58         bootstrap.handler(new ChannelInitializer() {
 59             protected void initChannel(Channel ch) throws Exception {
 60                 NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyClient.this);
 61                 ch.pipeline()//.addLast("logging",new LoggingHandler(LogLevel.INFO))//for debug
 62                         .addLast("decoder", adapter.getDecoder())
 63                         .addLast("encoder", adapter.getEncoder())
 64                         .addLast("handler", nettyClientHandler);
 65             }
 66         });
 67     }
 68 
 69     protected void doConnect() throws Throwable {
 70         long start = System.currentTimeMillis();
 71         ChannelFuture future = bootstrap.connect(getConnectAddress());
 72         try {
 73             boolean ret = future.awaitUninterruptibly(3000, TimeUnit.MILLISECONDS);
 74 
 75             if (ret && future.isSuccess()) {
 76                 Channel newChannel = future.channel();
 77                 try {
 78                     // Close old channel
 79                     Channel oldChannel = NettyClient.this.channel; // copy reference
 80                     if (oldChannel != null) {
 81                         try {
 82                             if (logger.isInfoEnabled()) {
 83                                 logger.info("Close old netty channel " + oldChannel + " on create new netty channel " + newChannel);
 84                             }
 85                             oldChannel.close();
 86                         } finally {
 87                             NettyChannel.removeChannelIfDisconnected(oldChannel);
 88                         }
 89                     }
 90                 } finally {
 91                     if (NettyClient.this.isClosed()) {
 92                         try {
 93                             if (logger.isInfoEnabled()) {
 94                                 logger.info("Close new netty channel " + newChannel + ", because the client closed.");
 95                             }
 96                             newChannel.close();
 97                         } finally {
 98                             NettyClient.this.channel = null;
 99                             NettyChannel.removeChannelIfDisconnected(newChannel);
100                         }
101                     } else {
102                         NettyClient.this.channel = newChannel;
103                     }
104                 }
105             } else if (future.cause() != null) {
106                 throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server "
107                         + getRemoteAddress() + ", error message is:" + future.cause().getMessage(), future.cause());
108             } else {
109                 throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server "
110                         + getRemoteAddress() + " client-side timeout "
111                         + getConnectTimeout() + "ms (elapsed: " + (System.currentTimeMillis() - start) + "ms) from netty client "
112                         + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion());
113             }
114         } finally {
115             if (!isConnected()) {
116                 //future.cancel(true);
117             }
118         }
119     }
120 
121     @Override
122     protected void doDisConnect() throws Throwable {
123         try {
124             NettyChannel.removeChannelIfDisconnected(channel);
125         } catch (Throwable t) {
126             logger.warn(t.getMessage());
127         }
128     }
129 
130     @Override
131     protected void doClose() throws Throwable {
132         //can't shutdown nioEventLoopGroup
133         //nioEventLoopGroup.shutdownGracefully();
134     }
135 
136     @Override
137     protected com.alibaba.dubbo.remoting.Channel getChannel() {
138         Channel c = channel;
139         if (c == null || !c.isActive())
140             return null;
141         return NettyChannel.getOrAddChannel(c, getUrl(), this);
142     }
143 }

netty3:http://www.cnblogs.com/java-zhao/p/7811040.html

 1 protected void doOpen() throws Throwable {
 2         NettyHelper.setNettyLoggerFactory();
 3         bootstrap = new ClientBootstrap(channelFactory);
 4         // config
 5         // @see org.jboss.netty.channel.socket.SocketChannelConfig
 6         bootstrap.setOption("keepAlive", true);
 7         bootstrap.setOption("tcpNoDelay", true);
 8         bootstrap.setOption("connectTimeoutMillis", getTimeout());
 9         final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
10         bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
11             public ChannelPipeline getPipeline() {
12                 NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyClient.this);
13                 ChannelPipeline pipeline = Channels.pipeline();
14                 pipeline.addLast("decoder", adapter.getDecoder());
15                 pipeline.addLast("encoder", adapter.getEncoder());
16                 pipeline.addLast("handler", nettyHandler);
17                 return pipeline;
18             }
19         });
20     }
21 
22 protected void doConnect() throws Throwable {
23         long start = System.currentTimeMillis();
24         ChannelFuture future = bootstrap.connect(getConnectAddress());
25         try {
26             boolean ret = future.awaitUninterruptibly(getConnectTimeout(), TimeUnit.MILLISECONDS);
27 
28             if (ret && future.isSuccess()) {
29                 Channel newChannel = future.getChannel();
30                 newChannel.setInterestOps(Channel.OP_READ_WRITE);
31                 try {
32                     // 关闭旧的连接
33                     Channel oldChannel = NettyClient.this.channel; // copy reference
34                     if (oldChannel != null) {
35                         try {
36                             if (logger.isInfoEnabled()) {
37                                 logger.info("Close old netty channel " + oldChannel + " on create new netty channel " + newChannel);
38                             }
39                             oldChannel.close();
40                         } finally {
41                             NettyChannel.removeChannelIfDisconnected(oldChannel);
42                         }
43                     }
44                 } finally {
45                     if (NettyClient.this.isClosed()) {
46                         try {
47                             if (logger.isInfoEnabled()) {
48                                 logger.info("Close new netty channel " + newChannel + ", because the client closed.");
49                             }
50                             newChannel.close();
51                         } finally {
52                             NettyClient.this.channel = null;
53                             NettyChannel.removeChannelIfDisconnected(newChannel);
54                         }
55                     } else {
56                         NettyClient.this.channel = newChannel;
57                     }
58                 }
59             } else if (future.getCause() != null) {
60                 throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server "
61                         + getRemoteAddress() + ", error message is:" + future.getCause().getMessage(), future.getCause());
62             } else {
63                 throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server "
64                         + getRemoteAddress() + " client-side timeout "
65                         + getConnectTimeout() + "ms (elapsed: " + (System.currentTimeMillis() - start) + "ms) from netty client "
66                         + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion());
67             }
68         } finally {
69             if (!isConnected()) {
70                 future.cancel();
71             }
72         }
73     }

还有就是编解码。

后续会做netty4源码阅读计划。

 

posted on 2018-01-02 20:42  赵计刚  阅读(7443)  评论(1编辑  收藏  举报