当前位置: 首页 > news >正文

Netty简介

Netty

  • Netty初体验
  • 基础概念
  • Reactor模型
    • 传统的阻塞IO模型
    • 基础Reactor模型
    • 多线程Reactor模型

为什么要使用Netty?
(NIO的框架,用于解决高并发出现的问题)

在这里插入图片描述

*BIO:同步且阻塞的IO
NIO:同步且非阻塞的IO(不是说线程)
AIO:异步且非阻塞的IO
还没有实现业务,光写整个流程就非常繁琐。NIO除了实现起来复杂之外,还存在一些需要解决的棘手问题,比如客户端断线重连如何实现,心跳处理(客户端在一定的时间内,不断的向服务器发送信息告诉服务器还在)、半包读写处理等等一些列问题,此时需要有这么一个框架,用于解决和优化NIO存在的问题,它就是Netty。

目的:客户端越来越多,随着客户端的增多,代码的复杂程度就变高,netty帮我们降低了编写nio的代码复杂程度*


Netty初体验

第一步:引入依赖

<dependencies><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.35.Final</version></dependency>
</dependencies>

服务器端

public class NettyServer {public static void main(String[] args) throws Exception {//创建只处理连接请求的线程组EventLoopGroup bossGroup = new NioEventLoopGroup(10);//创建只处理客户端读写业务的线程组EventLoopGroup workGroup = new NioEventLoopGroup(10);//创建服务端启动对象ServerBootstrap bootstrap = new ServerBootstrap();//配置参数bootstrap.group(bossGroup,workGroup)//使用NioServerSocketChannel作为服务器的通道实现.channel(NioServerSocketChannel.class)//配置用于存放因没有空闲线程导致连接请求被暂存放到队列中的队列长度.option(ChannelOption.SO_BACKLOG,1024)//创建通道初始化的对象并配置该对象,向该对象中添加处理器来实现具体的业务.childHandler(new ChannelInitializer<SocketChannel>() {//初始化通道@Overrideprotected void initChannel(SocketChannel ch) throws Exception {//添加处理器,处理器里面是真正处理业务的ch.pipeline().addLast(new NettyServerHandler());}});//配置groupSystem.out.println("Netty服务器启动了");//同步阻塞地启动服务器ChannelFuture channelFuture = bootstrap.bind(9090).sync();//只要服务没关闭,该方法会一直阻塞channelFuture.channel().closeFuture().sync();System.out.println("================a");bossGroup.shutdownGracefully();workGroup.shutdownGracefully();}
}
public class NettyServerHandler extends ChannelInboundHandlerAdapter {//当有客户端发送数据来的时候该方法就会被调用@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf buf = (ByteBuf) msg;System.out.println("客户端发送的数据:"+buf.toString(StandardCharsets.UTF_8));}//读完数据之后调用的方法:发送数据给客户端@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception {//创建携带的ByteBuf对象ByteBuf buf = Unpooled.copiedBuffer("hello client".getBytes(StandardCharsets.UTF_8));ctx.writeAndFlush(buf);}//异常捕获@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {System.out.println(cause.getMessage());ctx.close();}
}

客户端

public class NettyClient {public static void main(String[] args) throws Exception {//创建一个线程组用于事件循环EventLoopGroup eventLoopGroup = new NioEventLoopGroup();//创建客户端启动对象Bootstrap bootstrap = new Bootstrap();//设置相关参数bootstrap.group(eventLoopGroup)//使用NioSocketChannel作为客户端的通道实现.channel(NioSocketChannel.class)//创建通道初始化对象并设置handler业务处理器.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {//添加处理器,处理器里面是实现具体业务的ch.pipeline().addLast(new NettyClientHandler());}});System.out.println("Netty客户端启动了");//告知客户端的服务器的地址,并启动客户端ChannelFuture channelFuture = bootstrap.connect("127.0.0.1",9090).sync();channelFuture.channel().closeFuture().sync();//阻塞等待完成操作后关闭通道eventLoopGroup.shutdownGracefully();}
}
public class NettyClientHandler extends ChannelInboundHandlerAdapter {//当客户端完成连接服务器后调用该方法@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {ByteBuf buf = Unpooled.copiedBuffer("hello server".getBytes(StandardCharsets.UTF_8));ctx.writeAndFlush(buf);}//当通道有读事件发生时调用的方法:读取服务器返回的数据@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf buf = (ByteBuf) msg;System.out.println("来自服务器"+ctx.channel().remoteAddress()+"的消息"+buf.toString(StandardCharsets.UTF_8));}
}

基础概念

NIO中实现多路复用的核心类是Selector,当多路复用器Selector调用select方法时,将会查找发生事件的
channel,问题是,该如何在多个注册到selector上的channel中找到哪些channel发生了事件,此时NIO不同的版本有不同的做法。
epoll函数
poll函数
select函数

在这里插入图片描述

Reactor模型

不同的线程决定了程序的性能,多线程是为了充分利用CPU

传统的阻塞IO模型

在这里插入图片描述
客户端连接服务端之后,会等客户端输入完之后,最后响应给客户端,才能紧接着为其它的客户端执行任务,因为等待会耗费大量时间,所以并没有把CPU用到极致

基础Reactor模型

在这里插入图片描述
可以执行完连接之后,让别的客户端来拿来处理自己的任务,各个操作之间是独立的,充分利用服务端之间的性能(可能是连接的,也可以是读的,也可以是写的)

多线程Reactor模型

在这里插入图片描述

相关文章:

Netty简介

Netty Netty初体验基础概念Reactor模型传统的阻塞IO模型基础Reactor模型多线程Reactor模型 为什么要使用Netty&#xff1f; &#xff08;NIO的框架&#xff0c;用于解决高并发出现的问题&#xff09; *BIO:同步且阻塞的IO NIO:同步且非阻塞的IO&#xff08;不是说线程&#x…...

基于TCP/IP对等模型对计算机网络知识点的整合

目录 前言 应用层 Telnet SSH FTP/TFTP SNMP&#xff1a;简单的网络管理协议 HTTP&#xff1a;超文本传输协议 SMTP&#xff1a;电子邮件传输协议 DNS&#xff1a;域名解析协议 DHCP&#xff1a;动态主机配置协议 NTP&#xff1a;网络时钟协议 传输层 TCP UDP 端…...

【SQL应知应会】表分区(一)• Oracle版

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习&#xff0c;有基础也有进阶&#xff0c;有MySQL也有Oracle 分区表 • Oracle版 前言一、分区表1.什么是表分区…...

PostgreSQL 常用空间处理函数

1.OGC标准函数 管理函数&#xff1a; 添加几何字段 AddGeometryColumn(, , , , , ) 删除几何字段 DropGeometryColumn(, , ) 检查数据库几何字段并在geometry_columns中归档 Probe_Geometry_Columns() 给几何对象设置空间参考&#xff08;在通过一个范围做空间查询时常用&…...

ubuntu初始化/修改root密码

1.登录ubuntu后&#xff0c;使用sudo passwd root命令&#xff0c;进行root密码的初始化/修改&#xff0c;注&#xff1a;这里需要保证两次输入的密码都是同一个&#xff0c;才可成功 ubuntugt-ubuntu22-04-cmd-v1-0-32gb-100m:~/ocr$ sudo passwd root New password: Retype…...

【Linux后端服务器开发】select多路转接IO服务器

目录 一、高级IO 二、fcntl 三、select函数接口 四、select实现多路转接IO服务器 一、高级IO 在介绍五种IO模型之前&#xff0c;我们先讲解一个钓鱼例子。 有一条大河&#xff0c;河里有很多鱼&#xff0c;分布均匀。张三是一个钓鱼新手&#xff0c;他钓鱼的时候很紧张&a…...

支持向量机(iris)

代码&#xff1a; import pandas as pd from sklearn.preprocessing import StandardScaler from sklearn import svm import numpy as np# 定义每一列的属性 colnames [sepal-length, sepal-width, petal-length, petal-width, class] # 读取数据 iris pd.read_csv(data\\i…...

24考研数据结构-第二章:线性表

目录 第二章&#xff1a;线性表2.1线性表的定义&#xff08;逻辑结构&#xff09;2.2 线性表的基本操作&#xff08;运算&#xff09;2.3 线性表的物理/存储结构&#xff08;确定了才确定数据结构&#xff09;2.3.1 顺序表的定义2.3.1.1 静态分配2.3.1.2 动态分配2.3.1.3 mallo…...

Mybatis 动态 sql 是做什么的?都有哪些动态 sql?能简述动态 sql 的执行原理不?

OGNL表达式 OGNL&#xff0c;全称为Object-Graph Navigation Language&#xff0c;它是一个功能强大的表达式语言&#xff0c;用来获取和设置Java对象的属性&#xff0c;它旨在提供一个更高的更抽象的层次来对Java对象图进行导航。 OGNL表达式的基本单位是"导航链"&a…...

250_C++_typedef std::function<int(std::vector<int> vtBits)> fnChkSstStt

假设我们需要定义一个函数类型来表示一个能够计算整数向量中所有元素之和的函数。 首先,我们定义一个函数,它的参数是一个 std::vector 类型的整数向量,返回值是 int 类型,表示所有元素之和: int sumVectorElements(std::vector<int> vt) {int sum = 0;for (int n…...

无涯教程-jQuery - Transfer方法函数

Transfer 效果可以与effect()方法一起使用。这会将元素的轮廓转移到另一个元素。尝试可视化两个元素之间的交互时非常有用。 Transfer - 语法 selector.effect( "transfer", {arguments}, speed ); 这是所有参数的描述- className - 传输元素将收到的可选类名。…...

openGauss学习笔记-24 openGauss 简单数据管理-模式匹配操作符

文章目录 openGauss学习笔记-24 openGauss 简单数据管理-模式匹配操作符24.1 LIKE24.2 SIMILAR TO24.3 POSIX正则表达式 openGauss学习笔记-24 openGauss 简单数据管理-模式匹配操作符 数据库提供了三种独立的实现模式匹配的方法&#xff1a;SQL LIKE操作符、SIMILAR TO操作符…...

JAVASE---数据类型与变量

1. 字面常量 常量即程序运行期间&#xff0c;固定不变的量称为常量&#xff0c;比如&#xff1a;一个礼拜七天&#xff0c;一年12个月等。 public class Demo{ public static void main(String[] args){ System.Out.println("hello world!"); System.Out.println(…...

IDEA Groovy 脚本一键生成实体类<mybatisplus>

配置数据库&#xff08;mysql&#xff09; 一键生成&#xff08;右键点击table&#xff09; 配置自己的groovy脚本 import com.intellij.database.model.DasTable import com.intellij.database.util.Case import com.intellij.database.util.DasUtil import com.intellij.data…...

无涯教程-jQuery - Puff方法函数

吹气效果可以与show/hide/toggle一起使用。通过按比例放大元素并同时隐藏它&#xff0c;可以形成粉扑效果。 Puff - 语法 selector.hide|show|toggle( "puff", {arguments}, speed ); 这是所有参数的描述- model - 效果的模式。可以是"显…...

什么叫前后端分离?为什么需要前后端问题?解决了什么问题?

单体架构出现的问题 引出&#xff1a;来看一个单体项目架构的结构 通过上述可以看到单体架构主要存在以下几点问题&#xff1a; 开发人员同时负责前端和后端代码开发&#xff0c;分工不明确开发效率低前后端代码混合在一个工程中&#xff0c;不便于管理对开发人员要求高(既会前…...

Vector<T> 动态数组(随机访问迭代器)(答案)

答案如下 //------下面的代码是用来测试你的代码有没有问题的辅助代码,你无需关注------ #include <algorithm> #include <cstdlib> #include <iostream> #include <vector> #include <utility> using namespace std; struct Record { Record…...

Istio 故障注入与重试的实验

故障注入 Istio流量治理有故障注入的功能&#xff0c;在接收到用户请求程序的流量时&#xff0c;注入故障现象&#xff0c;例如注入HTTP请求错误&#xff0c;当有流量进入Sidecar时&#xff0c;直接返回一个500的错误请求代码。 通过故障注入可以用来测试整个应用程序的故障恢…...

Java设计模式-中介者模式

中介者模式 1.中介者模式含义 中介者模式&#xff0c;就是用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地互相引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立的改变它们之间的交互。 其实中介者模式很简单的&#xff0c;就像它的名字一样&a…...

OpenCV实现高斯模糊加水印

# coding:utf-8 # Email: wangguisendonews.com # Time: 2023/4/21 10:07 # File: utils.pyimport cv2 import PIL from PIL import Image import numpy as np from watermarker.marker import add_mark, im_add_mark import matplotlib.pyplot as plt# PIL Image转换成OpenCV格…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

省略号和可变参数模板

本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...

leetcode73-矩阵置零

leetcode 73 思路 记录 0 元素的位置&#xff1a;遍历整个矩阵&#xff0c;找出所有值为 0 的元素&#xff0c;并将它们的坐标记录在数组zeroPosition中置零操作&#xff1a;遍历记录的所有 0 元素位置&#xff0c;将每个位置对应的行和列的所有元素置为 0 具体步骤 初始化…...