Netty实战 -- 使用Netty实现分布式框架Dubbo RPC

效果

在这里插入图片描述

⛽静态代理的优缺点

缺点: 不利于扩展,调用一次就要创建一次对象,从而造成不必要的内存空间浪费

优点: 可读性好,逻辑简单,清晰明了

2.3 动态代理方式


动态代理又分为:JDK动态代理CGLIB动态代理

在程序运行时,运用反射机制动态创建而成,达到调用服务

使用以上的Subject类和实现类

SubjectInvocationHandler处理器类

package com.wanshi.netty.dubborpc.netty;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

public class SubjectInvocationHandler implements InvocationHandler {

private Object obj;

public SubjectInvocationHandler(Object obj) {

this.obj = obj;

}

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

Object res = method.invoke(obj, args);

return res;

}

}

ProxyFactry工厂类

package com.wanshi.netty.dubborpc.netty;

import java.lang.reflect.Proxy;

public class ProxyFactry {

public static Subject getInstance() {

SubjectImpl subject = new SubjectImpl();

System.out.println(“美团外卖,使命必达,跑腿代买!”);

SubjectInvocationHandler subjectInvocationHandler = new SubjectInvocationHandler(subject);

Subject proxy = (Subject) Proxy.newProxyInstance(subject.getClass().getClassLoader(),

subject.getClass().getInterfaces(), subjectInvocationHandler);

return proxy;

}

}

测试类

public static void main(String[] args) {

Subject subject = ProxyFactry.getInstance();

String buy = subject.buy(“饮料”);

System.out.println(buy);

}

效果

在这里插入图片描述

⛽动态代理的优缺点

两种动态代理对照表

| | JDK原生动态代理 | CGLIB动态代理 |

| — | — | — |

| 核心原理 | 基于 ”接口实现“方式 | 基于类集成方式 |

| 优点 | Java原生支持的,不需要任何依赖 | 对与代理的目标对象无限制,无需实现接口 |

| 不足之处 | 只能基于接口实现 | 无法处理final方法 |

| 实现方式 | Java原生支持 | 需要引入Jar文件依赖 |

三、Netty实现DubboRPC

====================================================================================

3.1 需求说明


  1. dubbo 底层使用了Netty作为网络通讯框架,要求用Netty实现一个简单的RPC框架

  2. 模仿dubbo,消费者和提供者约定接口和协议,消费者远程调用提供者的服务,提供者返回一个字符串,消费者打印提供者返回的数据,底层使用Netty框架

3.2 剖析需求


  1. 创建接口,定义抽象方法,用于服务消费者与服务提供者之间的约定

  2. 创建一个提供者,该类需要监听消费者的请求,并按照约定返回数据

  3. 创建一个消费者,该类需要 透明的调用自己不存在的方法,内部使用Netty 请求提供者返回数据

在这里插入图片描述

3.3 效果图


在这里插入图片描述

3.4 核心源码


♻️共用接口API

HelloService

package com.wanshi.netty.dubborpc.publicinterface;

/**

  • 公共接口,提供服务

*/

public interface HelloService {

String hello(String msg);

}

♻️服务提供者

ServerBootstrap启动类

package com.wanshi.netty.dubborpc.provider;

import com.wanshi.netty.dubborpc.netty.NettyServer;

/**

  • 服务提供者启动类,监听消费者,并绑定端口8888

*/

public class ServerBootstrap {

public static void main(String[] args) {

NettyServer.startServer(“127.0.0.1”, 8888);

}

}

NettyServer

package com.wanshi.netty.dubborpc.netty;

import io.netty.bootstrap.ServerBootstrap;

import io.netty.channel.ChannelFuture;

import io.netty.channel.ChannelInitializer;

import io.netty.channel.ChannelPipeline;

import io.netty.channel.EventLoopGroup;

import io.netty.channel.nio.NioEventLoopGroup;

import io.netty.channel.socket.SocketChannel;

import io.netty.channel.socket.nio.NioServerSocketChannel;

import io.netty.handler.codec.string.StringDecoder;

import io.netty.handler.codec.string.StringEncoder;

/**

  • Netty服务器类,启动服务

*/

public class NettyServer {

/**

  • 开启服务方法,调用内部私有启动服务方法,此类写法很常用,进一层的封装了API

  • @param hostName

  • @param port

*/

public static void startServer(String hostName, int port) {

startServer0(hostName, port);

}

/**

  • 真正启动服务的方法

  • @param hostName

  • @param port

*/

private static void startServer0(String hostName, int port) {

//创建2个线程,一个为主线程仅创建1个,另外创建工作线程CPU核数*2个

EventLoopGroup bossGroup = new NioEventLoopGroup(1);

EventLoopGroup workerGroup = new NioEventLoopGroup();

try {

//服务器启动类

ServerBootstrap serverBootstrap = new ServerBootstrap();

//初始化参数

serverBootstrap.group(bossGroup, workerGroup)

.channel(NioServerSocketChannel.class)

.childHandler(new ChannelInitializer() {

@Override

protected void initChannel(SocketChannel ch) throws Exception {

ChannelPipeline pipeline = ch.pipeline();

pipeline.addLast(new StringDecoder());

pipeline.addLast(new StringEncoder());

pipeline.addLast(new NettyServerHandler());

}

});

System.out.println(“服务端提供服务准备就绪…”);

//绑定端口,启动服务,异步执行方法

ChannelFuture channelFuture = serverBootstrap.bind(hostName, port).sync();

channelFuture.channel().closeFuture().sync();

} catch (Exception e) {

e.printStackTrace();

} finally {

//优雅的关闭线程

bossGroup.shutdownGracefully();

workerGroup.shutdownGracefully();

}

}

}

♻️服务消费者

ClientBootstrap

package com.wanshi.netty.dubborpc.consumer;

import com.wanshi.netty.dubborpc.netty.NettyClient;

import com.wanshi.netty.dubborpc.publicinterface.HelloService;

public class ClientBootstrap {

public static final String providerName = “hello#”;

public static void main(String[] args) throws InterruptedException {

NettyClient client = new NettyClient();

HelloService service = (HelloService) client.getBean(HelloService.class, providerName);

for (;😉 {

Thread.sleep(2000);

String hello = service.hello(“你好鸭 dubbo~”);

System.out.println(“服务端返回的结果:” + hello + “\n\n”);

}

}

}

NettyClient

package com.wanshi.netty.dubborpc.netty;

import io.netty.bootstrap.Bootstrap;

import io.netty.channel.ChannelInitializer;

import io.netty.channel.ChannelOption;

import io.netty.channel.ChannelPipeline;

import io.netty.channel.EventLoopGroup;

import io.netty.channel.nio.NioEventLoopGroup;

import io.netty.channel.socket.SocketChannel;

import io.netty.channel.socket.nio.NioSocketChannel;

import io.netty.handler.codec.string.StringDecoder;

import io.netty.handler.codec.string.StringEncoder;

import java.lang.reflect.Proxy;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class NettyClient {

//创建线程池,大小为CPU核数*2

private ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

//将客户端处理器提升至全局变量

private NettyClientHandler clientHandler;

//记录调用服务的次数

private int count;

/**

  • 代理对象,执行方法,这里用到了代理模式

  • @param serviceClass

  • @param providerName

  • @return

*/

public Object getBean(final Class<?> serviceClass, String providerName) {

return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),

new Class<?>[]{serviceClass}, (proxy, method, args) -> {

System.out.println(“(proxy, method, args) 进入,第” + (++count) + “次调用远程服务”);

if (clientHandler == null) {

initClient();

}

clientHandler.setParam(providerName + args[0]);

return executorService.submit(clientHandler).get();

});

}

/**

  • 初始化客户端

*/

public void initClient() {

clientHandler = new NettyClientHandler();

EventLoopGroup group = new NioEventLoopGroup();

Bootstrap bootstrap = new Bootstrap();

bootstrap.group(group)

.channel(NioSocketChannel.class)

.option(ChannelOption.TCP_NODELAY, true)

.handler(new ChannelInitializer() {

@Override

protected void initChannel(SocketChannel ch) throws Exception {

ChannelPipeline pipeline = ch.pipeline();

pipeline.addLast(new StringDecoder());

pipeline.addLast(new StringEncoder());

pipeline.addLast(clientHandler);

}

});

try {

bootstrap.connect(“127.0.0.1”, 8888).sync();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

四、源码下载

=========================================================================

本教程已上传至GitHub代码托管平台,希望点个Star鸭~

NettyDubboRPC

使用Git爬取GitHub文件

♨️往期精彩热文回顾

=============================================================================

✈️ **[Netty进阶 – WebSocket长连接开发

]( )**

✈️ **[Netty进阶 – 非阻塞网络编程 实现群聊+私聊+心跳检测系统

]( )**

✈️ **[Postman测试工具调试接口详细教程【向后端发送Json数据并接收返回的Json结果】

]( )**

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
**

✈️ **[Netty进阶 – 非阻塞网络编程 实现群聊+私聊+心跳检测系统

]( )**

✈️ **[Postman测试工具调试接口详细教程【向后端发送Json数据并接收返回的Json结果】

]( )**

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-jvn8TCy3-1715854276235)]

[外链图片转存中…(img-TjlsUy3l-1715854276236)]

[外链图片转存中…(img-ZRAKZTmN-1715854276236)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值