基于Netty的网络调用实现

作为一个分布式消息队列,通信的质量至关重要。基于TCP协议和Socket实现一个高效、稳定的通信程序并不容易,有很多大大小小的“坑”等待着经验不足的开发者。RocketMQ选择不重复发明轮子,基于Netty库来实现底层的通信功能。

1 Netty介绍

Netty是一个网络应用框架,或者说是一个Java网络开发库。Netty提供异步事件驱动的方式,使用它可以快速地开发出高性能的网络应用程序,比如客户端/服务器自定义协议程序,大大简化了网络程序的开发过程。

Netty是一个精心设计的框架,它从许多协议实现中吸收了丰富的经验,比如FTP、SMTP、HTTP等许多基于二进制和文本的传统协议。借助Netty,可以比较容易地开发出达到Java网络专家+并发编程专家水平的通信程序。

了解Netty前需要对Java NIO有个基本的了解,熟悉Channel、ByteBuffer、Selector等基本概念。对于Java网络编程经验不多的读者,可以试着先用Java NIO的基本类写一个简单的Client/Server程序,然后再用Netty对比着实现一遍,这样比较容易理解Netty里各种组件存在的原因。

2 Netty架构总览

如图13-1所示,Netty主要分为三部分:一是底层的零拷贝技术和统一通信模型;二是基于JVM实现的传输层;三是常用协议支持。如果想深入了解的话可以阅读一些专门介绍Netty的书籍。

图13-1 Netty整体架构

3 重新实现ByteBuffer

在网络通信中,CPU处理数据的速度大大快于网络传输数据的速度,所以需要引入缓冲区,将网络传输的数据放入缓冲区,累积足够的数据再发给CPU处理。

Netty使用自己重新实现的buffer API,而不是使用NIO的ByteBuffer来表示一个连续的字节序列。新实现的buffer类型ByteBuf可以从底层解决ByteBuffer的一些问题,是一种更适合日常网络应用开发需要的缓存类型。重新实现的ByteBuf特性包括允许使用自定义的缓存类型、透明的零拷贝实现、比ByteBuffer更快的响应速度等。

字节缓存在网络通信中会被频繁地使用,ByteBuf实现的是一个非常轻量级的字节数组包装器。ByteBuf有读操作和写操作,为了便于用户使用,该缓冲区维护了读索引和写索引。ByteBuf由三个片段构成:废弃段、可读段和可写段。其中,可读段表示缓冲区实际存储的可用数据。当用户使用read或者skip方法时,将会增加读索引。读索引之前的数据将进入废弃段,表示该数据已被使用过了。此外,用户可主动使用discardReadBytes清空废弃段以便得到更多的可写空间。简单来说和ByteBuffer相比,ByteBuf用在网络编程时更合适,更易用。

3 统一的异步I/O接口

传统的Java I/O API在应对不同的传输协议时需要使用不同的类型和方法。例如java.net.Socket和java.net.DatagramSocket,但它们没有相同的父类型,因此需要使用不同的调用方式执行Socket操作。因为在模式上不匹配,所以更换网络应用的传输协议时工作会变得很繁杂。由于(Java I/O API)缺乏协议间的可移植性,无法在不修改网络传输层的前提下增加多种协议的支持。从理论上讲,多种应用层协议可运行在多种传输层协议之上,例如TCP/IP、UDP/IP、SCTP和串口通信。

还有个复杂的情况是,Java的新I/O(NIO)API与原有的阻塞式I/O(OIO)API不兼容。这两者无论是在设计上还是在性能上,其特性都不相同,可是在开发时一般只选择某一种API。例如,在用户数较小的时候可以选择使用传统的OIO(Old I/O)API,毕竟与NIO相比使用OIO更加容易;但是当业务快速增长,服务器需要同时处理成千上万的客户连接时问题就来了,这时候不得不尝试使用NIO来解决,新的NIO Selector编程接口和Old I/O差别很大,很难做到快速升级。

Netty有一个被称为Channel的统一异步I/O编程接口,这个编程接口抽象了所有点对点的通信操作。这样,如果应用是基于Netty的某一种传输方式来实现的,则可以快速迁移到另一种传输实现上。Netty提供了几种拥有相同编程接口的基本传输实现:

·基于NIO的TCP/IP传输(io.netty.channel.nio);

·基于OIO的TCP/IP传输(io.netty.channel.oio);

·基于OIO的UDP/IP传输(io.netty.channel.oio);

·本地传输(io.netty.channel.local)。

切换不同的传输实现通常只需修改几行代码,而且由于核心API具有高度的可扩展性,很容易定制自己的传输实现。

4 基于拦截链模式的事件模型

一个定义良好并具有扩展能力的事件模型可以大大提高事件驱动程序的效率,Netty就具有定义良好的I/O事件模型,它采用严格的层次结构来区分不同的事件类型,Netty也允许在不破坏现有代码的情况下实现自己的事件类型。事件模型是Netty的一个亮点,很多NIO通信框架没有或者仅有有限的事件模型概念,当需要一个新的事件类型的时候常常需要修改已有的代码,有的甚至不允许进行自定义的扩展。

在Netty中,ChannelPipeline内部的一个ChannelEvent被一组ChannelHandler处理。这个管道是Intercepting Filter(拦截过滤器)模式的一种高级形式的实现,因此对于一个事件如何被处理,以及管道内部处理器间的交互过程,用户拥有绝对的控制力。

5 高级组件

Netty提供了一系列的高级组件来让开发过程更加快捷,比如Codec框架、SSL/TLS支持、HTTP实现等。

首先看看Codec框架。从业务逻辑代码中分离协议处理部分可以让代码结构变得更清晰,但是如果从零开始实现会有很高的复杂性,比如处理分段消息,相互叠加的多层协议,还有些协议复杂到无法在一台独立的状态机上实现。Netty提供了一组构建在其核心模块之上的codec实现,是一种可扩展、可重用、可单元测试,并且是多层的codec框架,为用户提供容易维护的codec代码。

Netty还提供对SSL/TLS的支持,不同于传统阻塞式的I/O实现,在NIO模式下支持SSL功能不能只是简单地包装一下流数据并进行加密或解密工作,还需要借助于javax.net.ssl.SSLEngine。SSLEngine是一个有状态的实现,使用SSLEngine必须管理所有可能的状态,例如密码套件、密钥协商(或重新协商)、证书交换以及认证等,而且SSLEngine不是一个绝对的线程安全实现。在Netty内部,SslHandler封装了所有艰难的细节,以及使用SSLEngine可能带来的陷阱。用户只需要配置并将该SslHandler插入你的ChannelPipeline中即可,而且Netty允许实现像StartTlS那样的高级特性。

HTTP是互联网上最受欢迎的协议,与现有的HTTP实现相比,Netty的HTTP实现是相当与众不同的。在HTTP消息的低层交互过程中用户拥有绝对的控制力,因为Netty的HTTP实现只是一些HTTP Codec和HTTP消息类的简单组合,不存在任何限制,例如那种被迫选择的线程模型。用户可以根据自己的需求编写那种可以完全按照你期望的工作方式工作的客户端或服务器端代码,比如线程模型、连接生命期、快编码等。基于这种高度可定制化的特性,用户可以开发一个非常高效的HTTP服务器,例如要求持久化链接以及服务器端推送技术的聊天服务,需要保持链接直至整个文件下载完成的媒体流服务,需要上传大文件并且没有内存压力的文件服务,支持大规模混合客户端应用用于连接以万计的第三方异步web服务等。

Netty的WebSockets实现,WebSockets允许双向,全双工通信信道。在TCP socket中,它被设计为允许一个Web浏览器和Web服务器之间通过数据流交互。WebSocket协议已经被IETF列为RFC 6455规范,并且Netty实现了RFC 6455和一些老版本的规范。

此外Netty还支持Google Protocol Buffer,Google Protocol Buffers是快速实现一个高效的二进制协议的理想方案。通过使用ProtobufEncoder和ProtobufDecoder,我们可以把Google Protocol Buffers编译器(protoc)生成的消息类放入Netty的codec实现中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/187205.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【pytorch】深度学习入门一:pytorch的安装与配置(Windows版)

请支持原创,认准DannisTang(tangweixuan1995foxmail.com) 文章目录 第〇章 阅读前提示第一章 准备工作第一节 Python下载第二节 Python安装第三节 Python配置第四节 Pycharm下载第五节 Pycharm安装第六节 CUDA的安装 第二章 Anaconda安装与配…

Gitee 之初体验(上)

我们在项目开发或者自己学习的时候,总会存在这样的问题: 在一台电脑上编写完代码,想要再另外一台电脑上再去写,再或者和其他人一起协作等等场合,代码传来传去很麻烦。 这个时候,我们就可以去使用代码管理工…

LeetCode刷题---打家劫舍问题

顾得泉:个人主页 个人专栏:《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂,年薪百万! 一、打家劫舍 题目链接:打家劫舍 题目描述 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定…

Spring Security 6.x 系列(7)—— 源码分析之建造者模式

一、建造者模式 WebSecurity、HttpSecurity、AuthenticationManagerBuilder 都是框架中的构建者,把他们放到一起看看他们的共同特点: 查看AuthenticationManagerBuilder的继承结构图: 查看HttpSecurity的继承结构图: 查看WebSec…

数据结构(超详细讲解!!)第二十六节 图(上)

1.基本概念 图(Graph)是一种较线性表和树更为复杂的非线性结构。是对结点的前趋和后继个数不加限制的数据结构,用来描述元素之间“多对多”的关系(即结点之间的关系是任意的)。 一个图G (V,E)由顶点&…

excel 计算断面水质等级

在工作中遇到根据水质监测结果要判断断面等级。写了下面的公式: 因子标准值 limits {COD: [15,15, 20, 15,20],氨氮: [0.15, 0.5, 1, 1.5, 2.0],总磷: [0.02, 0.1, 0.2, 0.3, 0.4] } excel公式: IFS(MAX(IF(M2>20,1,0), IF(N2>2,1,0), IF(O2&g…

RabbitMQ登录控制台显示--你与此网站的连接不是私密连接

一、RabbitMQ默认账号 Note: The default administrator username and password are guest and guest. 注:默认管理员用户名和密码为guest和guest 二、自己修改过或者注册的情况 由于本人之前用过,注册过账号密码,在登录时,用户名账号有异常出现以下问题 解决方案: 因为我的rab…

AI - Steering behaviorsII(碰撞避免,跟随)

Steering Behaviors系统中的碰撞避免,路径跟随,队长跟随 Collision Avoid 在物体前进的方向,延伸一定长度的向量进行检测。相当于物体对前方一定可使范围进行检测障碍物的碰撞 延伸的向量与碰撞物圆心的距离小于碰撞物的半径,则…

计算机体系结构----流水线技术(三)

本文仅供学习,不作任何商业用途,严禁转载。绝大部分资料来自----计算机系统结构教程(第二版)张晨曦等 计算机体系结构----流水线技术(三) 3.1 流水线的基本概念3.1.1 什么是流水线3.1.2 流水线的分类1. 部件级流水线、处理机级流…

C语言之结构体详解

C语言之结构体详解 文章目录 C语言之结构体详解1. 结构体类型的声明2. 结构体变量的创建和初始化3. 结构体的特殊声明4. 结构体的自引用结构体的自引用匿名结构体的自引用 5. 结构体内存对齐5.1 练习一5.2 练习三 6. 为什么存在内存对⻬? 1. 结构体类型的声明 struct tag {me…

05_属性描述符

05_属性描述符 文章目录 05_属性描述符一、属性描述符是什么?二、属性描述符①:查看属性描述②:设置属性描述符③:案例01.代码实现02.代码实现(优化) 一、属性描述符是什么? 属性描述符的结构 在…

类和对象——(3)再识对象

归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍 收藏⭐ 留言​📝 你说那里有你的梦想,…

MySQL官网推荐书籍

MySQL官网推荐书籍 图片有防盗链csdn转存失败。有图版传送门MySQL官网推荐书籍 高效的MySQL性能:Daniel Nichter的最佳实践和技术 Daniel Nichter 向您展示了如何应用直接影响 MySQL 性能的最佳实践和技术。您将学习如何通过分析查询执行、为常见 SQL 子句和表联接…

KMP基础架构

前言 Kotlin可以用来开发全栈, 我们所熟悉的各个端几乎都支持(除了鸿蒙) 而我们要开发好KMP项目需要一个好的基础架构,这样不仅代码更清晰,而且能共享更多的代码 正文 我们可以先将KMP分为前端和服务端 它们两端也能共享一些代码,比如接口声明,bean类,基础工具类等 前端和…

Go语言 值传递

官方说法,Go中只有值传递,没有引用传递 而Go语言中的一些让你觉得它是引用传递的原因,是因为Go语言有值类型和引用类型,但是它们都是值传递。 值类型 有int、float、bool、string、array、sturct等 引用类型有slice&#xff0c…

Logstash使用指南

介绍 Logstash是一个开源数据收集引擎,具有实时管道功能。它可以动态地将来自不同数据源的数据统一起来,并将数据标准化到你所选择的目的地。尽管Logstash的早期目标是搜集日志,现在它的功能已完全不只于此。任何事件类型都可以加入分析&…

docker (镜像分层、阿里云镜像推送/拉去)-day02

一、镜像概念 Docker 镜像是 Docker 容器的基础,它提供了一种可重复使用的、跨平台的部署方式,使得应用程序的部署和运行变得简单和高效。 把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),打包好…

C语言练习记录(蓝桥杯练习)(小蓝数点)

目录 小蓝数点 第一题程序的输出结果是?: 第二题下面代码的执行结果是什么?: 第三题下面代码的执行结果是什么?: 第四题关于关系操作符说法错误的是?: 第五题对于下面代码段,y的值为? 第六题sum 21 …

Java 数据结构篇-用链表、数组实现栈

🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 栈的说明 2.0 用链表来实现栈 2.1 实现栈 - 入栈方法(push) 2.2 实现栈 - 出栈(pop) 2.3 实现栈 - 查看栈顶元素…

国产linux单用户模式破解无密码登陆 (麒麟系统用户登录密码遗忘解决办法)

笔者手里有一批国产linu系统,目前开始用在日常的工作生产环境中,我这个老程序猿勉为其难的充当运维的或网管的角色。 国产linux系统常见的为麒麟Linux,统信UOS等,基本都是基于debian再开发的linux。 问题描述: 因为…