共计 4177 个字符,预计需要花费 11 分钟才能阅读完成。
本篇内容主要讲解“Netty 在 Dubbo 中使用实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让丸趣 TV 小编来带大家学习“Netty 在 Dubbo 中使用实例分析”吧!
当配置如下信息时
dubbo:application name= infuq-dubbo-provider / dubbo:registry protocol= zookeeper address= 127.0.0.1:2181 check= false / dubbo:protocol name= dubbo port= 20880 threads= 200 / dubbo:service ref= queryUserInfoFacade interface= com.infuq.facade.QueryUserInfoFacade version= 1.0.0 / bean id= queryUserInfoFacade >
Spring 在启动的过程中, 通过 DubboNamespaceHandler 解析上面的标签.
将每个标签与之对应的 BeanDefinition 注册到 BeanFactory 中.
Spring 再根据 BeanDefinition 生成对应的 Bean 实例.
上面的 dubbo:service / 标签最终会生成对应的 ServiceBean 实例.
// 源码位置: com.alibaba.dubbo.config.spring.ServiceBeanpublic class ServiceBean T extends ServiceConfig T implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener ContextRefreshedEvent , BeanNameAware, ApplicationEventPublisherAware { }
ServiceBean 实现了 ApplicationListener ContextRefreshedEvent 接口.
在 Spring 创建完所有的 Bean 之后, 最后会发布一个 ContextRefreshedEvent 事件.
因此 ServiceBean 的 onApplicationEvent() 方法会被执行.
public void onApplicationEvent(ContextRefreshedEvent event) { if (isDelay() !isExported() !isUnexported()) { if (logger.isInfoEnabled()) { logger.info( The service ready on spring started. service: + getInterface()); } // 暴露服务 export(); }}
接下来就进入到了服务暴露的过程.
服务暴露会完成两件事情. 第一件事情是通过 Netty 开启服务, 监听端口.
第二件事情是将服务注册到注册中心.
跟进 export() 方法, 最后会来到 DubboProtocol 类.
大体看下它是如何开启服务, 监听端口? 留意下, 有个属性 requestHandler.
public class DubboProtocol extends AbstractProtocol { private ExchangeHandler requestHandler = new ExchangeHandlerAdapter() {... };
private ExchangeServer createServer(URL url) { // 绑定 server = Exchangers.bind(url, requestHandler); }
}
跟进 bind() 方法, 最后会来到 NettyServer 的 doOpen() 方法.
留意下, 有个属性 nettyServerHandler.
// 源码位置: com.alibaba.dubbo.remoting.transport.netty4.NettyServerprotected void doOpen() throws Throwable { bootstrap = new ServerBootstrap();
bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory( NettyServerBoss , true)); workerGroup = new NioEventLoopGroup(getUrl().getPositiveParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS), new DefaultThreadFactory(NettyServerWorker , true));
// 重要的 Handler final NettyServerHandler nettyServerHandler = new NettyServerHandler(getUrl(), this); channels = nettyServerHandler.getChannels();
bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE) .childOption(ChannelOption.SO_REUSEADDR, Boolean.TRUE) .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT) .childHandler(new ChannelInitializer NioSocketChannel () { @Override protected void initChannel(NioSocketChannel ch) throws Exception { NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this); ch.pipeline() .addLast( decoder , adapter.getDecoder()) .addLast(encoder , adapter.getEncoder()) .addLast(handler , nettyServerHandler);// 处理请求和响应的 Handler } }); // bind ChannelFuture channelFuture = bootstrap.bind(getBindAddress()); channelFuture.syncUninterruptibly(); channel = channelFuture.channel();
}
从 DubboProtocol 类的 requestHandler 属性到 NettyServer 的 nettyServerHandler 属性.
这一路会经历很多 Handler, 经过层层封装, 最后才封装成 NettyServerHandler.
它会经历如下 Handler
NettyServerHandler
- NettyServer
- MultiMessageHandler
- HeartbeatHandler
- AllChannelHandler
- DecodeHandler
- HeaderExchangeHandler
- ExchangeHandler
当客户端连接服务端, 或者发送数据到服务端的时候,
首先会由 NettyServerHandler 处理请求, 然后依次将请求传递下去, 最后到 ExchangeHandler.
那么这些 Handler 是否都由同一个线程执行的吗? 并不是
如上图, 在 AllChannelHandler 中有个 executor 属性, 它是一个线程池.
NettyServerHandler
- NettyServer
- MultiMessageHandler
- HeartbeatHandler
- AllChannelHandler
以上这几个 Handler 是由同一个线程执行的, 是由 Netty 的 IO 线程执行的, 名称类似 NettyServerWorker-5-7
- DecodeHandler
- HeaderExchangeHandler
- ExchangeHandler
以上这几个 Handler 是由另一类线程执行的, 是由 AllChannelHandler 中的线程池执行的, 名称类似 DubboServerHandler-2.0.1.15:20880-thread-57
也就是说, Netty 的 IO 线程在接收到请求后, 先依次执行
NettyServerHandler - NettyServer -
MultiMessageHandler - HeartbeatHandler
- AllChannelHandler 这五个 Handler.
之后会由 AllChannelHandler 中的线程池执行后面的 DecodeHandler
- HeaderExchangeHandler - ExchangeHandler 这三个 Handler.
dubbo:protocol name= dubbo port= 20880 threads= 200 threadpool= fixed /
使用 threads=200, threadpool=fixed 就是在配置图中红色区域的线程池. 线程池也是调优的一个地方.
到此,相信大家对“Netty 在 Dubbo 中使用实例分析”有了更深的了解,不妨来实际操作一番吧!这里是丸趣 TV 网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!