作者:莫那 鲁道http://cnblogs.com/stateis0/p/9062171.html

目录

  • dubbo 的 Consumer 消费者如何使用 Netty
  • dubbo 的 Provider 提供者如何使用 Netty
  • 总结

前言

众所周知,国内知名框架 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 就简短的介绍到这里。

good luck!!!!

推荐阅读(点击即可跳转阅读)

1. SpringBoot内容聚合

2.

面试题内容聚合​mp.weixin.qq.com

3. 设计模式内容聚合

4. Mybatis内容聚合

5. 多线程内容聚合

将serversocket 写在按钮事件中连接不上_看 Netty 在 Dubbo 中如何应用相关推荐

  1. 将serversocket 写在按钮事件中连接不上_Java服务器的模型—TCP连接/流量优化

    本文很长哦,但请给我一点时间. 通常,我们的应用程序不需要并行处理成千上万的用户,也不需要在一秒钟内处理成千上万的消息.我们只需要应付数十或数百个并发连接的用户,就可以在内部应用程序或某些微服务应用程 ...

  2. 看 Netty 在 Dubbo 中如何应用

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

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

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

  4. LJL-Solution-vss2005在项目中连接不上 解决方案

    vss2005 在单独打开的时候可以连接上,在项目中连接不上的解决方案: 打开vs-->工具-->选项--->源代码管理--->当前源代码管理插件:改为 Microsoft V ...

  5. 用navixt连接mysql连接不上_迪兰RX 5600 XT X战神评测:中端的芯,旗舰的用料

    [PConline 评测]RX 5600 XT发布有一段时间了,这款产品有着非常出色的能耗比和不俗的游戏性能,本应在市场有一番大作为,不过由于首发价格诚意稍显不足,所以没有吸引到很多人.但通常情况下电 ...

  6. firebase连接不上_如何在Firebase上托管Blazor应用程序

    firebase连接不上 介绍 (Introduction) In this article, we will learn how to deploy a Blazor application on ...

  7. python向mysql中添加数据标签_用python在MySQL中写入数据和添加数据

    在笔者之前的博文中,已介绍了用python连接与mysql数据库的知识.包括如何安装python连接mysql的pymysql包,如何通过cusor语句将python与mysql连接起来,以及如何用p ...

  8. ux设计中的各种地图_如何在UX设计中使用颜色

    ux设计中的各种地图 Color is the mother tongue of the subconscious. 颜色是潜意识的母语. - Carl Jung -荣格 Color has more ...

  9. 亚马逊 ec2 连接不上_在Amazon EC2上设置WordPress

    亚马逊 ec2 连接不上 The general consensus of opinion, is that self hosting a WordPress blog is the best way ...

最新文章

  1. 自制MVC之工具类插件一
  2. centos7 利用 crontab 执行 定时任务 计划任务
  3. Java程序员校招蚂蚁金服,mysql培训考试
  4. PHP——访问网站根目录解决方案
  5. 如何在Linux(CentOS, Debian, Fedora和Ubuntu)上安装MyCLI
  6. 别跟我谈EF抵抗并发,敢问你到底会不会用EntityFramework
  7. Java 集合系列目录(Category)
  8. 手把手教你使用Python网络爬虫获取招聘信息
  9. c语言下面程序的功能是求圆的周长和面积.请改正程序中带*行中,2012年计算机等级考试二级C语言上机题(5)...
  10. nyoj-673-悟空的难题(数组标记)
  11. asp.net中实现群发邮件功能
  12. 为别人着想的表达才是最好的表达
  13. 靠模仿红牛成为饮料界的“黑马”,东鹏特饮的未来如何谱写?
  14. Appium之切换输入法
  15. 互联网+是什么意思?
  16. 命名空间“System”中不存在类型或命名空间名“Data”
  17. kubernetes 系列之 - 暴露运行的服务端口
  18. Maven 设置项目编码
  19. python opencv 拍照_在jupyter noteb中使用opencv显示网络摄像头中的图像
  20. ad中按钮开关的符号_火速收藏!电工最常用电气元件实物图及对应符号

热门文章

  1. 技术团队的工程师文化:效率与价值
  2. 亿级流量 | 蚂蚁金服分布式事务实践解析
  3. autopoi升级到4.0版本修改方法
  4. maven项目中整合grunt构建工具(二)-js合并、压缩技术
  5. JEECG 商业版本和开源版本有什么区别呢?
  6. net core框架介绍
  7. Objective-C 日记③ 字符串
  8. Python(pycharm)在windows下路径 ( ' / ' 与' \ ' )的问题
  9. ios. GCD 倒计时时间
  10. Apple Notification Center Service--ANCS【转】