第04篇:手写JavaRPC框架之搞定网络通信
作者: 西魏陶渊明
博客: https://blog.springlearn.cn/
天下代码一大抄, 抄来抄去有提高, 看你会抄不会抄!
一、前言
- 听说你Sql写的很溜,那么你知道服务端的Sql是如何被传输到SQL服务器执行的吗?
- 听说你10分钟能写两个接口,那你知道数据是如何在两个系统中通讯的吗?
- 听说你微服务玩的很熟练,那你知道微服务的基础是什么吗?
可以这样说,我们写的任何系统都离不开通讯,离不开网络编程,就没有现在我们发达的互联网世界。就没有什么分布式,没有什么微服务。所以由此可见网络编程是非常基础的知识。
但是我们思考下,有多少同学真正使用过Java网络通信的API了呢
? 相信百分之80的小伙伴可能都没用过? 为什么呢? 因为我们站在巨人的肩膀上, 底层的代码都被层层的封装起来了,为了使我们能专注于业务的开发。这虽然提高了我们的开发效率。但是呢? 从另一个方面讲,他不利于我们的技术成长,使我们只会用,而不去思考为什么这么用。逐渐沦为CRUD Body。
个人如果想成长,想打破这种现状, 那么网络通信是一定要掌握的,当你掌握了这些,才算掌握了一点核心技术。当你掌握了这些,才能收获一些不一样的东西,看问题的维度又会有所提升。
本系列文章, 我们会一起来写RPC框架,而网络通讯是必要要掌握的知识,如果说以前你不懂,那么没关系跟着小编来Coding。我们一起来从0到1搭建一个网络通信层,然后以此为基础实现一个Java RPC框架吧。
二、目标
2.1 目标介绍
本篇文章是我们的第四篇,内容主要是实现网络通讯。通信层框架主要使用的是Netty进行实现, 说到Netty可能很多同学都没有用过。而要想实现通讯Netty就必须要知道,所以本篇内容篇幅较多。
- 第一个目标,快速学习Netty的架构,掌握Netty 核心的API,最终唯我所用。
- 第二个目标,使用Netty完成我们的通信层。
内容非常的硬核,难度指数比较大,也主要是偏向于实战。请专注学习,内容中如果有差错,欢迎提出。小编会积极回复,并改正。
三、Netty API 学习
前面第三篇我们学习了搞定序列化,在上一篇中我们介绍了这幅图,序列化就是将数据转换成二进制数据,在网络管道中传输。今天开头还是这一张图, 不过今天要说的不在是里面的数据,而是要研究下如何来构建一个通信的管道。本篇文章我们要利用Netty搭建一个网络管道。
这张图是对第一张图的一个细化,可以看到在这个管道的里面有一个双向的数据流【双工】。
客服端向服务端发送数据,服务端也可以同时向客户端发送数据。这个过程叫做全双工。为什么呢? 因为这个管道是TCP管道。我们所知道的Dubbo也是在此基础上实现的。所以说dubbo和http是平级的关系。
- 一个inbound入栈方向,负责将二进制数据转换成Java对象
- 一个outbound出库方向,负责将Java对象转换成二进制对象
3.1 ChannelPipeline 网络管道
上面的那个管道在Netty中就是 ChannelPipeline
, ChannelPipeline
是Netty 中一个非常重要的组件,我们说的管道,就可以理解成是这个类,在这个管道中有两个方向的流向。如下
- ChannelInboundHandler 入栈
- ChannelOutboundHandler 出栈
只有管道还不行,要对管道中流动的数据进行处理。怎么来处理呢? 就是 ChannelHandler
3.2 ChannelHandler 管道处理器
ChannelHandle
通道处理器是最顶层接口, ChannelHandler
和 ChannelPipeline
的关系,好比这张图。
ChannelPipeline
相当于是管道,而 ChannelHandler
相当于管道中的每个拦路虎, 通过对数据的拦截,然后进行处理。下面这张图比较形象。
Netty
要想学的好, ChannelHandler
学习不能少,下面是 Netty
中 ChannelHandler
的类关系图。想要处理数据只用继承这其中的一些类就可以了。
请记住这张图,我们下面会利用这些管道处理器来实现我们的网络通信。
3.3 入栈管道解码器
编码器本质上就是一个
ChannelHandler
, 所以上图我们也能看出来它是实现了ChannelHandler
的。
二进制数据转换成Java对象就要我们来搞一个入栈的解码器,通过上面的图我们知道Netty给我们提供了一个
入栈方向的类。ByteToMessageDecoder
。那么我们就先实现他,直接看代码。
/*** 请求解码器负责将二进制数据转换成能处理的协议* 个人博客:https://java.springlearn.cn* 公众号:西魏陶渊明 {关注获取学习源码}*/
@Slf4j
public abstract class ChannelDecoder extends ByteToMessageDecoder {/*** 解码方法** @param ctx 通道上下文信息* @param in 网络传过来的信息(注意粘包和拆包问题)* @param out in中的数据转换成对象调用out.add方法* @throws Exception 未知异常*/@Overridepublic void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {doDecode(ctx, in, out);}/*** 解码方法** @param ctx 通道上下文信息* @param in 网络传过来的信息(注意粘包和拆包问题)* @param out in中的数据转换成对象调用out.add方法* @throws Exception 未知异常*/protected abstract void doDecode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception;
}
doDecode 方法,通过读取ByteBuf中数据,然后经过的规则处理,就是协议处理,然后反序列化成Java对象,然后调用out.add()。
这个规则处理,就是协议,我们在本系列文章的第二篇,就说了我们的协议是什么,如下这张图。那么我们就按照这个规则来解析数据吧。
- 实际上这里我们还要面对黏包和拆包的问题。什么是黏包和拆包呢?
3.4 黏包和拆包及解决方案
我们举一个例子,前两天某某国前首相安老三,遇到刺客了。这时候你很悲伤想发一个说说: 只要人没事就好。
拆包:
只要人没事就好 = 只要人没 + 事就好。
就是形容一条完整的数据报文,因为某些原因,数据被分成多段进行传输了,当你读取数据的时候,读到的不是完整的数据,而是一半的数据。此时意思就比较尴尬了。只要人没,事就好
第04篇:手写JavaRPC框架之搞定网络通信相关推荐
- 第02篇:手写JavaRPC框架之设计思路
作者: 西魏陶渊明 博客: https://blog.springlearn.cn/ 天下代码一大抄, 抄来抄去有提高, 看你会抄不会抄! 一.前言 隔壁老李又在喷我了: "完犊子了,小编这 ...
- 第四篇 - 手写RPC框架
Github源码下载地址:https://github.com/chenxingxing6/myrpc 一.前言 RPC(Remote Procedure Call)-远程过程调用,它是一种通过网络从 ...
- 第一篇 - 手写SpringMvc框架
Github源码下载地址:https://github.com/chenxingxing6/springmvc CSDN源码下载地址:https://download.csdn.net/downloa ...
- 手写bind_一次搞定前端“四大手写”
本文首发于个人GitHub博客 要问程序员最心虚的面试题,如果要投票选择,手撕代码一定是前三位的.其中在前端领域,以手写 bind.手写深拷贝.手写 EventHub(发布-订阅).手写 Promis ...
- 手写篇:如何手写RPC框架?
手写篇:如何手写RPC框架? 首先我们讲下什么是RPC? RPC(Remote Procedure Call)远程过程调用协议,他是一种通过网络从远程计算机程序请求服务.简单的来说,就是通过网络进行远 ...
- Marco's Java【Dubbo 之手写Dubbo框架实现远程调用】
前言 关于Dubbo入门的网上教程也特别多,因此我没有专门出关于Dubbo的系列博文(主要呢- 也是在忙些工作上的事儿),用Dubbo特别简单,但是想要把Dubbo学好,学精还得花费不少时间的,特别是 ...
- 视频教程-手写Java框架系列教程之一反射(含配套资料)-Java
手写Java框架系列教程之一反射(含配套资料) 张长志技术全才.擅长领域:区块链.大数据.Java等.10余年软件研发及企业培训经验,曾为多家大型企业提供企业内训如中石化,中国联通,中国移动等知名企业 ...
- 【Java ORM】手写ORM框架:源代码、jar、生成JavaDoc文档
SORMSourceCode 把这个手写框架取名为SORM. (1)源代码(Eclipse项目文件):GitHub地址 (2)jar包.源代码.JavaDoc文档.使用说明:Github地址 一个简单 ...
- onclick 源码_精读:手写React框架 解析Hooks源码
写在开头: 去年发表过一篇手写React,带diff算法,异步setState队列的文章,有一位阿里的朋友在下面评论,让我可以用hooks实现一次,也很简单,我当时觉得,这人有病,现在回过头来看,还是 ...
- 手写ORM框架----(数据库单表CRUD万能框架)
目录 一.准备 1.1 ORM介绍 1.2 准备工作 二.手写ORM的CRUD 2.1 数据库准备 2.2 所需注解 2.3 实体类student 2.4 CRUD 2.4.1 添加功能 2.4.2 ...
最新文章
- 网站优化中应该注意的细节有哪些?
- MASM5.0汇编环境安装
- oracle如何清空一个用户下的所有表中的数据?
- Linux iptables 配置详解
- session的简介
- Mybatis的入门到精通这一篇文章就够了
- CodeForces 780B ——The Meeting Place Cannot Be Changed(二分法)
- 圈子圈套 pdf_名字叫什么? 如何圈套好域名
- 一文读懂:完整的支付系统整体架构!
- 手机WIFI共享 打造便携式WIFI热点
- html5 黑色圆圈,html5使用canvas画空心圆与实心圆_html5教程技巧
- Word 2016双击格式刷无法连用的问题
- 最详细教程:Zotero和Better BibTeX安装,以及如何在R markdown中引用文献
- Mathlab基础——常用命令
- 【Ant Design】图标大全(网断专用)
- 老罗斯柴尔德的第一桶金
- YOLOV5检测代码detect.py注释与解析
- js设计模式与开发实践(读书笔记)
- 普华永道区块链白皮书:区块链让城市更加智能 普华永道 中文精简版
- 一键安装nginx脚本