本篇内容主要讲解“Netty在Dubbo中使用实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“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" class="com.infuq.facade.impl.QueryUserInfoFacadeImpl" />
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.NettyServer
protected 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中使用实例分析”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。