作者: 西魏陶渊明

博客: 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 通道处理器是最顶层接口, ChannelHandlerChannelPipeline 的关系,好比这张图。

ChannelPipeline 相当于是管道,而 ChannelHandler 相当于管道中的每个拦路虎, 通过对数据的拦截,然后进行处理。下面这张图比较形象。

Netty 要想学的好, ChannelHandler 学习不能少,下面是 NettyChannelHandler 的类关系图。想要处理数据只用继承这其中的一些类就可以了。

请记住这张图,我们下面会利用这些管道处理器来实现我们的网络通信。

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框架之搞定网络通信相关推荐

  1. 第02篇:手写JavaRPC框架之设计思路

    作者: 西魏陶渊明 博客: https://blog.springlearn.cn/ 天下代码一大抄, 抄来抄去有提高, 看你会抄不会抄! 一.前言 隔壁老李又在喷我了: "完犊子了,小编这 ...

  2. 第四篇 - 手写RPC框架

    Github源码下载地址:https://github.com/chenxingxing6/myrpc 一.前言 RPC(Remote Procedure Call)-远程过程调用,它是一种通过网络从 ...

  3. 第一篇 - 手写SpringMvc框架

    Github源码下载地址:https://github.com/chenxingxing6/springmvc CSDN源码下载地址:https://download.csdn.net/downloa ...

  4. 手写bind_一次搞定前端“四大手写”

    本文首发于个人GitHub博客 要问程序员最心虚的面试题,如果要投票选择,手撕代码一定是前三位的.其中在前端领域,以手写 bind.手写深拷贝.手写 EventHub(发布-订阅).手写 Promis ...

  5. 手写篇:如何手写RPC框架?

    手写篇:如何手写RPC框架? 首先我们讲下什么是RPC? RPC(Remote Procedure Call)远程过程调用协议,他是一种通过网络从远程计算机程序请求服务.简单的来说,就是通过网络进行远 ...

  6. Marco's Java【Dubbo 之手写Dubbo框架实现远程调用】

    前言 关于Dubbo入门的网上教程也特别多,因此我没有专门出关于Dubbo的系列博文(主要呢- 也是在忙些工作上的事儿),用Dubbo特别简单,但是想要把Dubbo学好,学精还得花费不少时间的,特别是 ...

  7. 视频教程-手写Java框架系列教程之一反射(含配套资料)-Java

    手写Java框架系列教程之一反射(含配套资料) 张长志技术全才.擅长领域:区块链.大数据.Java等.10余年软件研发及企业培训经验,曾为多家大型企业提供企业内训如中石化,中国联通,中国移动等知名企业 ...

  8. 【Java ORM】手写ORM框架:源代码、jar、生成JavaDoc文档

    SORMSourceCode 把这个手写框架取名为SORM. (1)源代码(Eclipse项目文件):GitHub地址 (2)jar包.源代码.JavaDoc文档.使用说明:Github地址 一个简单 ...

  9. onclick 源码_精读:手写React框架 解析Hooks源码

    写在开头: 去年发表过一篇手写React,带diff算法,异步setState队列的文章,有一位阿里的朋友在下面评论,让我可以用hooks实现一次,也很简单,我当时觉得,这人有病,现在回过头来看,还是 ...

  10. 手写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 ...

最新文章

  1. 网站优化中应该注意的细节有哪些?
  2. MASM5.0汇编环境安装
  3. oracle如何清空一个用户下的所有表中的数据?
  4. Linux iptables 配置详解
  5. session的简介
  6. Mybatis的入门到精通这一篇文章就够了
  7. CodeForces 780B ——The Meeting Place Cannot Be Changed(二分法)
  8. 圈子圈套 pdf_名字叫什么? 如何圈套好域名
  9. 一文读懂:完整的支付系统整体架构!
  10. 手机WIFI共享 打造便携式WIFI热点
  11. html5 黑色圆圈,html5使用canvas画空心圆与实心圆_html5教程技巧
  12. Word 2016双击格式刷无法连用的问题
  13. 最详细教程:Zotero和Better BibTeX安装,以及如何在R markdown中引用文献
  14. Mathlab基础——常用命令
  15. 【Ant Design】图标大全(网断专用)
  16. 老罗斯柴尔德的第一桶金
  17. YOLOV5检测代码detect.py注释与解析
  18. js设计模式与开发实践(读书笔记)
  19. 普华永道区块链白皮书:区块链让城市更加智能 普华永道 中文精简版
  20. 一键安装nginx脚本

热门文章

  1. 日历看板 element日历组件
  2. Ubuntu20.04虚拟机安装、配置、美化教程
  3. 如何禁止树莓派屏幕休眠
  4. Docker Desktop 安装使用教程
  5. Unity3D 世界坐标转屏幕坐标的坑
  6. 从零开始做UI-静电的sketch设计教室 视频教程
  7. Axure常见的几种原型图
  8. 人大金仓数据库工程师培训实战教程(同步复制、读写分离、集群高可用)
  9. linux 统计文件字节和行数,Linux命令-统计文件中的字节数、字数、行数:wc
  10. python笔记——jieba库