热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

深入浅析Netty在Dubbo中是如何应用的

国内知名框架Dubbo底层使用的是Netty作为网络通信,那么内部到底是如何使用的呢?今天通过本文给大家详细讲解,对Netty在Dubbo中应用相关知识感兴趣的朋友跟随小编一起看看吧

众所周知,国内知名框架 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();
 // @1
 DemoService demoService = (DemoService) context.getBean("demoService"); // get remote service proxy
 int a = 0;
 while (true) {
  try {
   Thread.sleep(1000);
   System.err.println( ++ a + " ");

   String hello = demoService.sayHello("world"); // call remote method
   System.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,稍微有点区别。点击这篇:教你用 Netty 实现一个简单的 RPC。当连接成功后,注册写事件,准备开始向提供者传递数据。

当 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 调用。

到此这篇关于深入浅析Netty 在 Dubbo 中是如何应用的的文章就介绍到这了,更多相关Netty 在 Dubbo中应用内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


推荐阅读
  • 烤鸭|本文_Spring之Bean的生命周期详解
    烤鸭|本文_Spring之Bean的生命周期详解 ... [详细]
  • Spring Boot 中静态资源映射详解
    本文深入探讨了 Spring Boot 如何简化 Web 应用中的静态资源管理,包括默认的静态资源映射规则、WebJars 的使用以及静态首页的处理方法。通过本文,您将了解如何高效地管理和引用静态资源。 ... [详细]
  • 本文探讨了2019年前端技术的发展趋势,包括工具化、配置化和泛前端化等方面,并提供了详细的学习路线和职业规划建议。 ... [详细]
  • 本文作者分享了在阿里巴巴获得实习offer的经历,包括五轮面试的详细内容和经验总结。其中四轮为技术面试,一轮为HR面试,涵盖了大量的Java技术和项目实践经验。 ... [详细]
  • 阿里云ecs怎么配置php环境,阿里云ecs配置选择 ... [详细]
  • 本文介绍了如何利用 Spring Boot 和 Groovy 构建一个灵活且可扩展的动态计算引擎,以满足钱包应用中类似余额宝功能的推广需求。我们将探讨不同的设计方案,并最终选择最适合的技术栈来实现这一目标。 ... [详细]
  • 本文详细介绍如何使用CSS自定义HTML5视频播放器的样式,涵盖常见属性及跨浏览器兼容性问题。发布时间:2020-09-14 14:46:29;来源:亿速云;阅读量:58;作者:小新。 ... [详细]
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 本题来自WC2014,题目编号为BZOJ3435、洛谷P3920和UOJ55。该问题描述了一棵不断生长的带权树及其节点上小精灵之间的友谊关系,要求实时计算每次新增节点后树上所有可能的朋友对数。 ... [详细]
  • Nature Microbiology: 人类肠道古菌基因组目录
    本研究揭示了人类肠道微生物群落中古细菌的多样性,分析了来自24个国家、农村和城市人群的1,167个非冗余古细菌基因组。研究鉴定了多个新分类群,并探讨了古菌对宿主的适应性及其与社会人口特征的关系。 ... [详细]
  • 简化报表生成:EasyReport工具的全面解析
    本文详细介绍了EasyReport,一个易于使用的开源Web报表工具。该工具支持Hadoop、HBase及多种关系型数据库,能够将SQL查询结果转换为HTML表格,并提供Excel导出、图表显示和表头冻结等功能。 ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • 深入解析Spring启动过程
    本文详细介绍了Spring框架的启动流程,帮助开发者理解其内部机制。通过具体示例和代码片段,解释了Bean定义、工厂类、读取器以及条件评估等关键概念,使读者能够更全面地掌握Spring的初始化过程。 ... [详细]
  • 深入解析Hadoop的核心组件与工作原理
    本文详细介绍了Hadoop的三大核心组件:分布式文件系统HDFS、资源管理器YARN和分布式计算框架MapReduce。通过分析这些组件的工作机制,帮助读者更好地理解Hadoop的架构及其在大数据处理中的应用。 ... [详细]
  • Eclipse 中 JSP 开发环境配置指南
    本文详细介绍了如何在 Eclipse 集成开发环境中配置 JSP 运行环境,包括必要的软件下载、Tomcat 服务器的配置以及常见问题的解决方法。 ... [详细]
author-avatar
蒣彬彬
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有