基于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.rhkb.cn/news/205811.html

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

相关文章

VOC数据集转换为COCO数据集

VOC数据集格式 get_list.py import os import random import shutil# 设置随机种子 random.seed(1000)# 判断Annotations和JpegImages是否对应 train_precent=0.8 label_path= "../../Annotations" print(os.path.abspath(label_path)) save="../Main" pr…

【开源】基于Vue和SpringBoot的学校热点新闻推送系统

项目编号: S 047 ,文末获取源码。 \color{red}{项目编号:S047,文末获取源码。} 项目编号:S047,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 新闻类型模块2.2 新闻档案模块2.3 新…

Docker的项目资源参考

Docker的项目资源包括以下内容: Docker官方网站:https://www.docker.com/ Docker Hub:https://hub.docker.com/ Docker文档:https://docs.docker.com/ Docker GitHub仓库:https://github.com/docker Docker官方博客…

CentOS7安装MiniO

目录 1、简介 2、安装 2.1、Binary 2.2、RPM(RHEL)就是红帽,CentOS就用这个 2.3、DEB(Ubuntu/Debian) 2.4、创建指定的目录并且将下载的安装包上传上去 3、启动MiniO服务 3.1、脚本如下: 4、进入服务…

[个人笔记] vCenter6.7使用自建SSL证书

SSL - 运维篇 第三章 vCenter6.7使用自建SSL证书 SSL - 运维篇系列文章回顾vCenter6.7使用自建SSL证书vCenter 6.7 上传文件到ShellvCenter 6.7 Shell 替换SSL证书全流程测试&验证 参考链接 系列文章回顾 第二章 FortiGate防火墙使用自建SSL证书 vCenter6.7使用自建SSL证书…

Python基础语法之学习占位符

Python基础语法之学习占位符 一、代码二、效果 一、代码 name "张三" sex "男" age 10 money 12.5# 通过占位符完成拼接 print("姓名:%s" % name) print("姓名:%s,性别:%s" % (name, sex))text…

RabbitMQ消息模型之Routing-Direct

Routing Direct 在Fanout模式中,一条消息,会被所有订阅的队列都消费。但是在某些场景下,我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange。 在Direct模型下: 队列与交换机的绑定,不能是任意…

【算法刷题】Day9

文章目录 611. 有效三角形的个数![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/9d627e680e9144a2b67474a1d80aa030.png)题解:代码: LCR 179. 查找总价格为目标值的两个商品题解:代码: 611. 有效三角形的个数 原题链…

肖sir__mysql之视图__009

mysql之视图 一、什么是视图 视图是一个虚拟表(逻辑表),它不在数据库中以存储形式保存(本身包含数据),是在使用视图的时候动态生成。 二、视图作用 1、查询数据库中的非常复的数据 例如:多表&a…

Bitcoin SV 和 Bitcoin Core 之间首次跨链原子交换

我们已经执行了 Bitcoin SV 和 Bitcoin Core 之间的首次原子交换。 这一成就代表了比特币 SV 的重大进步,以去信任的方式促进了与其他区块链的无缝互操作性。 图片源自Gemini 在上一篇文章中,我们解释了原子交换的高级理论。 我们深入研究了使用哈希时间…

高项备考葵花宝典-项目范围管理输入、输出、工具和技术

项目范围管理包括确保项目“做”且“只做”所需的全部工作(即不能少做,也不能多做,如果多做,就要消耗团队额外的时间和资源,并且无法被认可),以成功完成项目。项目范围管理主要在于定义和控制哪…

Windows核心编程 注册表

目录 注册表概述 打开关闭注册表 创建删除子健 查询写入删除键值 子健和键值的枚举 常用注册表操作 注册表概述 注册表是Windows操作系统、硬件设备以及客户应用程序得以正常运行和保存设置的核心"数据库",也可以说是一个非常巨大的树状分层结构的…

Django路由分发

首先明白一点,Django的每一个应用下都可以有自己的templates文件夹,urls.py文件夹,static文件夹,基于这个特点,Django能够很好的做到分组开发(每个人只写自己的app),作为老大&#x…

使用tomcat搭建简易文件服务器

步骤 1、在本机另外部署一个tomcat作为文件服务器 可以像我这样将tomcat文件复制一个做为服务器 2、在webapps下新建文件夹uploadfiles,这个文件夹就是用来存储上传的文件的 (记住一定要是在作为服务器的tomcat的webapps下) 3、修改conf/…

Redis集群模式

Redis集群主要有三种模式 主从复制模式(Master-Slave)、哨兵模式(Sentinel)和Cluster模式 主从复制模式:适用于数据备份和读写分离场景,配置简单,但在主节点故障时需要手动切换。哨兵模式&…

vue005——vue组件入门(非单文件组件和单文件组件)

一、非单文件组件 1.1、单文件组件的使用 1.1.1、局部注册 1、第一步&#xff1a;创建school组件 2、第二步&#xff1a;注册组件&#xff08;局部注册&#xff09; 3、第三步&#xff1a;使用组件&#xff08;编写组件标签&#xff09; <!DOCTYPE html> <html>…

kettle入门教程

一、概述 1.什么是kettle Kettle是一款开源的ETL(Extract-Transform-Load)工具&#xff0c;纯java编写&#xff0c;可以在Window、Linux、Unix上运行&#xff0c;绿色无需安装&#xff0c;数据抽取高效稳定。 2.kettle工程存储方式 &#xff08;1&#xff09;以XML形式存储 …

37 - 数据库参数设置优化,失之毫厘差之千里

MySQL 是一个灵活性比较强的数据库系统&#xff0c;提供了很多可配置参数&#xff0c;便于我们根据应用和服务器硬件来做定制化数据库服务。如果现在让你回想&#xff0c;你可能觉得在开发的过程中很少去调整 MySQL 的配置参数&#xff0c;但我今天想说的是我们很有必要去深入了…

什么是PDM图纸管理系统?PDM图纸管理系统主要功能有哪些?

PDM (Product Data Management) 图纸管理系统 是用于管理企业内部图纸和相关文件的软件系统。它提供了一个集中存储、组织和跟踪图纸和文件的平台&#xff0c;以确保团队成员能够轻松访问、共享和更新所需的工程设计和制造数据。 彩虹PDM系统|PDM产品数据管理系统|BOM管理|工艺…

Kubernetes(K8s)资源管理-03

资源管理 资源管理介绍 在kubernetes中&#xff0c;所有的内容都抽象为资源&#xff0c;用户需要通过操作资源来管理kubernetes。 kubernetes的本质上就是一个集群系统&#xff0c;用户可以在集群中部署各种服务&#xff0c;所谓的部署服务&#xff0c;其实就是在kubernetes集…