众所周知,国内知名框架 Dubbo 底层使用的是 Netty 作为网络通信,那么内部到底是如何使用的呢?今天我们就来一探究竟。

1. dubbo 的 Consumer 消费者如何使用 Netty

注意:此次代码使用了从 github 上 clone 的 dubbo 源码中的 dubbo-demo 例子。

代码如下:

System.setProperty("java.net.preferIPv4Stack", "true");ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-consumer.xml"});context.start();// @1DemoService demoService = (DemoService) context.getBean("demoService"); // get remote service proxyint a = 0;while (true) {try {Thread.sleep(1000);System.err.println( ++ a + " ");String hello = demoService.sayHello("world"); // call remote methodSystem.out.println(hello); // get result} catch (Throwable throwable) {throwable.printStackTrace();}}

当代码执行到 @1 的时候,会调用 Spring 容器的 getBean 方法,而 dubbo 扩展了 FactoryBean,所以,会调用 getObject 方法,该方法会创建代理对象。

这个过程中会调用 DubboProtocol 实例的 getClients(URL url) 方法,当这个给定的 URL 的 client 没有初始化则创建,然后放入缓存,代码如下:

这个 initClient 方法就是创建 Netty 的 client 的。

最终调用的就是抽象父类 AbstractClient 的构造方法,构造方法中包含了创建 Socket 客户端,连接客户端等行为。

public AbstractClient(URL url, ChannelHandler handler) throws RemotingException {doOpen();connect();
}

doOpent 方法用来创建 Netty 的 bootstrap :

protected void doOpen() throws Throwable {NettyHelper.setNettyLoggerFactory();bootstrap = new ClientBootstrap(channelFactory);bootstrap.setOption("keepAlive", true);bootstrap.setOption("tcpNoDelay", true);bootstrap.setOption("connectTimeoutMillis", getTimeout());final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);bootstrap.setPipelineFactory(new ChannelPipelineFactory() {public ChannelPipeline getPipeline() {NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyClient.this);ChannelPipeline pipeline = Channels.pipeline();pipeline.addLast("decoder", adapter.getDecoder());pipeline.addLast("encoder", adapter.getEncoder());pipeline.addLast("handler", nettyHandler);return pipeline;}});
}

connect 方法用来连接提供者:

protected void doConnect() throws Throwable {long start = System.currentTimeMillis();ChannelFuture future = bootstrap.connect(getConnectAddress());boolean ret = future.awaitUninterruptibly(getConnectTimeout(), TimeUnit.MILLISECONDS);if (ret && future.isSuccess()) {Channel newChannel = future.getChannel();newChannel.setInterestOps(Channel.OP_READ_WRITE);}
}

上面的代码中,调用了 bootstrap 的 connect 方法,熟悉的 Netty 连接操作。当然这里使用的是  jboss 的 netty3,稍微有点区别。当连接成功后,注册写事件,准备开始向提供者传递数据。

当 main 方法中调用 demoService.sayHello(“world”) 的时候,最终会调用 HeaderExchangeChannel 的 request 方法,通过 channel 进行请求。

public ResponseFuture request(Object request, int timeout) throws RemotingException {Request req = new Request();req.setVersion("2.0.0");req.setTwoWay(true);req.setData(request);DefaultFuture future = new DefaultFuture(channel, req, timeout);channel.send(req);return future;
}

send 方法中最后调用 jboss  Netty 中继承了  NioSocketChannel 的 NioClientSocketChannel 的 write 方法。完成了一次数据的传输。

2. dubbo 的 Provider 提供者如何使用 Netty

Provider demo 代码:

System.setProperty("java.net.preferIPv4Stack", "true");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
context.start();
System.in.read(); // press any key to exit

Provider 作为被访问方,肯定是一个 Server 模式的 Socket。如何启动的呢?

当 Spring 容器启动的时候,会调用一些扩展类的初始化方法,比如继承了 InitializingBean,ApplicationContextAware,ApplicationListener 。

而 dubbo 创建了 ServiceBean 继承了一个监听器。Spring 会调用他的 onApplicationEvent 方法,该类有一个 export 方法,用于打开 ServerSocket 。

然后执行了 DubboProtocol 的 createServer 方法,然后创建了一个NettyServer 对象。NettyServer 对象的 构造方法同样是  doOpen 方法和。

代码如下:

protected void doOpen() throws Throwable {NettyHelper.setNettyLoggerFactory();ExecutorService boss = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerBoss", true));ExecutorService worker = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerWorker", true));ChannelFactory channelFactory = new NioServerSocketChannelFactory(boss, worker, getUrl().getPositiveParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS));bootstrap = new ServerBootstrap(channelFactory);final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);channels = nettyHandler.getChannels();bootstrap.setPipelineFactory(new ChannelPipelineFactory() {public ChannelPipeline getPipeline() {NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this);ChannelPipeline pipeline = Channels.pipeline();pipeline.addLast("decoder", adapter.getDecoder());pipeline.addLast("encoder", adapter.getEncoder());pipeline.addLast("handler", nettyHandler);return pipeline;}});channel = bootstrap.bind(getBindAddress());
}

该方法中,看到了熟悉的 boss 线程,worker 线程,和 ServerBootstrap,在添加了编解码 handler  之后,添加一个 NettyHandler,最后调用 bind 方法,完成绑定端口的工作。和我们使用 Netty 是一摸一样。

3. 总结

可以看到,dubbo 使用 Netty 还是挺简单的,消费者使用 NettyClient,提供者使用 NettyServer,Provider  启动的时候,会开启端口监听,使用我们平时启动 Netty 一样的方式。

而 Client 在 Spring getBean 的时候,会创建 Client,当调用远程方法的时候,将数据通过 dubbo 协议编码发送到 NettyServer,然后 NettServer 收到数据后解码,并调用本地方法,并返回数据,完成一次完美的 RPC 调用。

好,关于 dubbo 如何使用 Netty 就简短的介绍到这里。

作者:莫那·鲁道

https://www.cnblogs.com/stateis0/p/9062171.html

Netty 在 Dubbo 中是如何应用的?相关推荐

  1. Netty第二章 2020 7-4——Netty在Dubbo中的应用(3)关于单一长连接

    dubbo中单一长连接的理解和常见误区 1.低版本dubbo dubbo默认是单一长连接,那么这个默认在哪里,长连接又是什么意思,单一长连接又是什么意思呢? 首先dubbo底层用的是netty,所以长 ...

  2. 看 Netty 在 Dubbo 中如何应用

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:莫那 鲁道 cnblogs.com/stateis0/p/9 ...

  3. 将serversocket 写在按钮事件中连接不上_看 Netty 在 Dubbo 中如何应用

    作者:莫那 鲁道http://cnblogs.com/stateis0/p/9062171.html 目录 dubbo 的 Consumer 消费者如何使用 Netty dubbo 的 Provide ...

  4. Dubbo中的连接控制,你真的理解吗?

    欢迎关注方志朋的博客,回复"666"获面试宝典 前言 刚发现微信公众号有了标签功能,于是乎,我将我 Dubbo 相关的文章都打上了标签,仔细一统计,这已经是我第 41 篇原创的 D ...

  5. 线程组名称_Netty在Dubbo中的线程名称

    在项目中,我们会使用RocketMQ和Dubbo.前者用于发送或消费消息,后者用于两个模块之间的接口调用. RocketMQ和Dubbo在它们的底层都使用Netty作为网络通信的框架.那么今天我们就来 ...

  6. 服务化改造实践 | 如何在 Dubbo 中支持 REST

    什么是 REST REST 是 Roy Thomas Fielding [[1]](#fn1) 在 2000 年他的博士论文 [[2]](#fn2) "架构风格以及基于网络的软件架构设计&q ...

  7. 服务化改造实践 | 如何在 Dubbo 中支持 REST 1

    什么是 REST REST 是 Roy Thomas Fielding [[1]](#fn1) 在 2000 年他的博士论文 [[2]](#fn2) "架构风格以及基于网络的软件架构设计&q ...

  8. 在Dubbo中使用高效的Java序列化(Kryo和FST)

    作者:沈理 文档版权: Apache 2.0许可证 署名-禁止演绎 完善中-- TODO 生成可点击的目录 目录 序列化漫谈 启用Kryo和FST 注册被序列化类 无参构造函数和Serializabl ...

  9. dubbo 消费者也要暴露端口吗_一文详细解读 Dubbo 中的 http 协议

    (给ImportNew加星标,提高Java技能) 转自:Kirito的技术分享,作者:kiritomoe 太阳红彤彤,花儿五颜六色,各位读者朋友好,又来到了分享 Dubbo 知识点的时候了.说到 Du ...

最新文章

  1. 查询服务器上几张显卡命令
  2. python计算数据百分比_概率计算:定义概率分布数据结构,Python实现概率分布计算...
  3. 苹果被正式起诉!欧盟:滥用主导地位,利用App Store扭曲竞争
  4. 小工具-销售订单概览屏幕的特性显示
  5. VisualStudio配置中文提示
  6. Thinkphp5内核大型程序员交流博客系统源码
  7. Linux中执行shell脚本的5种方法总结
  8. java两个栈怎么完成初始化_Spring bean初始化及销毁你必须要掌握的回调方法
  9. python 气泡图 聚类_用SPSS制作气泡图
  10. 虚拟机启动失败/检查打开虚拟化-解决方案小结
  11. 【解决方案】IPv6的445端口被运营商封禁,导致无法正常使用Windows共享文件夹
  12. arduino编译失败_保存后,Arduino代码将无法编译
  13. 测试渲染用什么软件,【2人回答】3DMax2014用的是VRay3.0测试和出图渲染参数怎么设置-3D溜溜网...
  14. 阿里云ACP云计算对象存储OSS例题
  15. 基于随机无迹σ变异的改进HHO算法
  16. 【Android】打包生成APK教程
  17. Android App自动化测试: OPEN-STF环境搭建
  18. 2019年云计算产业市场前景研究,云计算技术发展趋势
  19. 基于SpringBoot的健身房管理系统【附源码】
  20. macos双系统 wintogo_我的 WinToGo 踩坑指南

热门文章

  1. cout的输出格式初探
  2. 基于Docker + Consul + Nginx + Consul-template的服务负载均衡实现
  3. iOS一个灵活可扩展的开源Log库
  4. Spring Boot 多模块与 Maven 私有仓库
  5. resize函数缩小图片的尺寸 车辆检测
  6. Android--面试题整理(二)
  7. Spring 文件上传功能
  8. 与1000天的我约定
  9. ref out 的使用
  10. 高流量大并发Linux TCP性能调优