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

Spring架构篇--2.7.2 远程通信基础--Netty原理--ServerBootstrap

前言:已经初始化了NioEventLoopGroup 的boosGroup 和 workerGroup ,那么ServerBootstrap的作用是干嘛的呢 ,本文在Spring架构篇–2.7.1 远程通信基础–Netty原理–NioEventLoopGroup 之后继续进行探究

1 首先回顾下 nettt 的使用demo:

public class DiscardServer {private int port;public DiscardServer(int port) {this.port = port;}public static void main(String[] args) {new DiscardServer(8080).run();}private void run() {NioEventLoopGroup boss = new NioEventLoopGroup();NioEventLoopGroup worker = new NioEventLoopGroup();try {ServerBootstrap server = new ServerBootstrap();server.group(boss,worker).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new DiscardServerHandler());}}).option(ChannelOption.SO_BACKLOG,128).childOption(ChannelOption.SO_KEEPALIVE,true);ChannelFuture f = server.bind(this.port).sync();System.out.println("8080服务已启动");f.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();} finally {boss.shutdownGracefully();worker.shutdownGracefully();}}
}

可以看到ServerBootstrap 的对象做了一系列的配置后最终 通过 bind(this.port).sync() 进行启动;

2 ServerBootstrap 类:

2.1 new ServerBootstrap() 工作内容:

public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerChannel>private static final InternalLogger logger = InternalLoggerFactory.getInstance(ServerBootstrap.class);
private final Map<ChannelOption<?>, Object> childOptions = new LinkedHashMap();
private final Map<AttributeKey<?>, Object> childAttrs = new ConcurrentHashMap();
// ServerBootstrap 对象赋值给 config
private final ServerBootstrapConfig config = new ServerBootstrapConfig(this);
private volatile EventLoopGroup childGroup;
private volatile ChannelHandler childHandler;public ServerBootstrap() {
}

AbstractBootstrap 类

public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable {static final Map.Entry<ChannelOption<?>, Object>[] EMPTY_OPTION_ARRAY = new Map.Entry[0];static final Map.Entry<AttributeKey<?>, Object>[] EMPTY_ATTRIBUTE_ARRAY = new Map.Entry[0];volatile EventLoopGroup group;private volatile ChannelFactory<? extends C> channelFactory;private volatile SocketAddress localAddress;private final Map<ChannelOption<?>, Object> options = new LinkedHashMap();private final Map<AttributeKey<?>, Object> attrs = new ConcurrentHashMap();private volatile ChannelHandler handler;AbstractBootstrap() {}}
  • 可以看到ServerBootstrap 继承了AbstractBootstrap类,当new ServerBootstrap() 时,对ServerBootstrap和AbstractBootstrap类都通过无参的构造方法,完成了这两个类的对象实例化;
  • 可以看到ServerBootstrap和AbstractBootstrap这两个类的属性非常相似,实际上 ServerBootstrap 用来放NioEventLoopGroup 工作线程的数据;AbstractBootstrap 用来放 boss 线程的数据;
  • 可以看到这里只是进行了初始化,里面的属性都还没有进行赋值,两个对象的属性值都是默认值;

2.2 ServerBootstrap ,AbstractBootstrap 的属性赋值:

2.2.1 server.group(boss,worker):完成对父类和子类 NioEventLoopGroup对象进行赋值
ServerBootstrap 类的 group 方法:

public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
// 父类AbstractBootstrap  的EventLoopGroup  赋值super.group(parentGroup);if (this.childGroup != null) {throw new IllegalStateException("childGroup set already");} else {
// 子类的EventLoopGroup   volatile EventLoopGroup group 赋值;this.childGroup = (EventLoopGroup)ObjectUtil.checkNotNull(childGroup, "childGroup");return this;}
}

super.group(parentGroup); 父类对象的赋值:
AbstractBootstrap 的group 方法:

static final Map.Entry<ChannelOption<?>, Object>[] EMPTY_OPTION_ARRAY = new Map.Entry[0];
static final Map.Entry<AttributeKey<?>, Object>[] EMPTY_ATTRIBUTE_ARRAY = new Map.Entry[0];
volatile EventLoopGroup group;
private volatile ChannelFactory<? extends C> channelFactory;
private volatile SocketAddress localAddress;
private final Map<ChannelOption<?>, Object> options = new LinkedHashMap();
private final Map<AttributeKey<?>, Object> attrs = new ConcurrentHashMap();
private volatile ChannelHandler handler;AbstractBootstrap() {
}
// 父类的EventLoopGroup  赋值
AbstractBootstrap(AbstractBootstrap<B, C> bootstrap) {this.group = bootstrap.group;this.channelFactory = bootstrap.channelFactory;this.handler = bootstrap.handler;this.localAddress = bootstrap.localAddress;synchronized(bootstrap.options) {this.options.putAll(bootstrap.options);}this.attrs.putAll(bootstrap.attrs);
}
// 父类group  AbstractBootstrap  类 对象的赋值 volatile EventLoopGroup group;
public B group(EventLoopGroup group) {ObjectUtil.checkNotNull(group, "group");if (this.group != null) {throw new IllegalStateException("group set already");} else {this.group = group;return this.self();}
}

2.2.2 channel(NioServerSocketChannel.class):
AbstractBootstrap 类 private volatile ChannelFactory<? extends C> channelFactory; 对象赋值
调用 AbstractBootstrap 类中 channel(NioServerSocketChannel.class) 方法:

public B channel(Class<? extends C> channelClass) {
//  先使用ReflectiveChannelFactory 反射工厂类,对传入的channel 进行包装
// 调用channelFactory 对父类AbstractBootstrap 对象channel 工厂进行初始化return this.channelFactory((io.netty.channel.ChannelFactory)(new ReflectiveChannelFactory((Class)ObjectUtil.checkNotNull(channelClass, "channelClass"))));
}
// 工厂方法调用
public B channelFactory(io.netty.channel.ChannelFactory<? extends C> channelFactory) {return this.channelFactory((ChannelFactory)channelFactory);
}
// AbstractBootstrap 对象属性的初始化@Deprecated
public B channelFactory(ChannelFactory<? extends C> channelFactory) {ObjectUtil.checkNotNull(channelFactory, "channelFactory");if (this.channelFactory != null) {throw new IllegalStateException("channelFactory set already");} else {this.channelFactory = channelFactory;return this.self();}
}
// channel类反射工厂的创建
public class ReflectiveChannelFactory<T extends Channel> implements ChannelFactory<T> {private final Constructor<? extends T> constructor;public ReflectiveChannelFactory(Class<? extends T> clazz) {ObjectUtil.checkNotNull(clazz, "clazz");try {// 赋值 NioServerSocketChannel 类的构造器,使得在需要实例化channel 对象的时候// 可以通过改channel 的无参构造方法完成对象实例化this.constructor = clazz.getConstructor();} catch (NoSuchMethodException var3) {throw new IllegalArgumentException("Class " + StringUtil.simpleClassName(clazz) + " does not have a public non-arg constructor", var3);}}// 对当前的channel 通过反射调用channel 对象的无参构造方法public T newChannel() {try {return (Channel)this.constructor.newInstance();} catch (Throwable var2) {throw new ChannelException("Unable to create Channel from class " + this.constructor.getDeclaringClass(), var2);}}public String toString() {return StringUtil.simpleClassName(ReflectiveChannelFactory.class) + '(' + StringUtil.simpleClassName(this.constructor.getDeclaringClass()) + ".class)";}
}
  • 通过channle 方法可以看到,完成了对父类AbstractBootstrap 对象 channel 工厂的属性初始化;
  • 在真正需要NioServerSocketChannel 对象的时候,可以通过ReflectiveChannelFactory的 newChannel() 方法完成对 NioServerSocketChannel 无参的构造方法调用,从而实例化一个NioServerSocketChannel的对象出来;

2.2.3 childHandler(new ChannelInitializer() { }):
调用ServerBootstrap 类中 childHandler(ChannelHandler childHandler) 方法:

public ServerBootstrap childHandler(ChannelHandler childHandler) {this.childHandler = (ChannelHandler)ObjectUtil.checkNotNull(childHandler, "childHandler");return this;
}

对ServerBootstrap 事件处理属性private volatile ChannelHandler childHandler; 赋值;

2.2.4 option(ChannelOption.SO_BACKLOG,128):
AbstractBootstrap 的option 方法,对父类AbstractBootstrap 对象options 顺序赋值:

// private final Map<ChannelOption<?>, Object> options = new LinkedHashMap(); 属性赋值
public <T> B option(ChannelOption<T> option, T value) {ObjectUtil.checkNotNull(option, "option");synchronized(this.options) {if (value == null) {this.options.remove(option);} else {this.options.put(option, value);}}return this.self();
}

2.2.5 childOption(ChannelOption.SO_KEEPALIVE,true):
ServerBootstrap 类中的childOption 方法:

// private final Map<ChannelOption<?>, Object> childOptions = new LinkedHashMap(); 赋值
public <T> ServerBootstrap childOption(ChannelOption<T> childOption, T value) {ObjectUtil.checkNotNull(childOption, "childOption");synchronized(this.childOptions) {if (value == null) {this.childOptions.remove(childOption);} else {this.childOptions.put(childOption, value);}return this;}
}
  • 可以看到上面的这些步骤先是对ServerBootstrap 和AbstractBootstrap 对象实例化 然后为其属性进行赋值操作;
  • 将NioEventLoopGroup worker = new NioEventLoopGroup(); 的worker 对象对其ServerBootstrap 的EventLoopGroup childGroup 赋值;然后将 NioEventLoopGroup boss = new NioEventLoopGroup(); 对象对其AbstractBootstrap 的 volatile EventLoopGroup group 属性赋值;
  • 对AbstractBootstrap 的channel 工厂类属性 private volatile ChannelFactory<? extends C> channelFactory; 赋值为NioServerSocketChannel 对象工厂;
  • 对AbstractBootstrap 的options 属性赋值key:ChannelOption.SO_BACKLOG, value :128;
  • 对ServerBootstrap 的childOptions 属性赋值key:ChannelOption.SO_KEEPALIVE, value: true;

以上步骤都是初始化和赋值操作,没有socket 端口的绑定,以及时间监听的处理,那么这些处理就只剩在bind(this.port).sync() 进行处理,由于bind 方法嵌套较深,所有放在下一篇继续探究;

相关文章:

Spring架构篇--2.7.2 远程通信基础--Netty原理--ServerBootstrap

前言&#xff1a;已经初始化了NioEventLoopGroup 的boosGroup 和 workerGroup &#xff0c;那么ServerBootstrap的作用是干嘛的呢 &#xff0c;本文在Spring架构篇–2.7.1 远程通信基础–Netty原理–NioEventLoopGroup 之后继续进行探究 1 首先回顾下 nettt 的使用demo&#x…...

awk编辑器

文章目录 一.awk概述1.概述2.作用3.awk的工作过程4.awk 工作原理及命令格式5.awk的基本操作及其内置变量5.1 awk的-F操作5.2 awk的-v操作5.3 内置变量 二.awk 打印1.基本打印用法1.1 默认打印1.2打印文件内容 2.对行进行操作2.1 只打印行号&#xff08;有多少行&#xff09;2.2…...

DicomObjects.Core 3.0.17 Crack

DicomObjects.NET 核心版简介 DicomObjects.Core Assembly DicomObjects.NET 核心版简介 DicomObjects.Core 由一组相互关联但独立的 .核心兼容的“对象”&#xff0c;使开发人员能够快速轻松地将DICOM功能添加到其产品中&#xff0c;而无需了解或编程DICOM标准的复杂性。此帮助…...

电脑怎么通过网络传输文件?

可以通过网络在电脑之间传输文件吗&#xff1f; “由于天气的原因&#xff0c;我的老板决定让所有员工在家工作。但是我很多工作文件都在公司的电脑中&#xff0c;怎么才能将公司的文件远程传输到我家里的电脑上&#xff1f;电脑可以通过网络远程传输文件吗&#xff1f;” …...

人工智能之深度学习

第一章 人工智能概述 1.1人工智能的概念和历史 1.2人工智能的发展趋势和挑战 1.3人工智能的伦理和社会问题 第二章 数学基础 1.1线性代数 1.2概率与统计 1.3微积分 第三章 监督学习 1.1无监督学习 1.2半监督学习 1.3增强学习 第四章 深度学习 1.1神经网络的基本原理 1.2深度…...

性能测试设计阶段

性能测试设计阶段 性能测试是软件测试中的关键环节&#xff0c;它可以帮助我们评估软件系统在压力下的运行稳定性和性能表现。性能测试设计阶段是性能测试的基础&#xff0c;只有经过充分的设计&#xff0c;才能保证性能测试的有效性和准确性。 在性能测试设计阶段&#xff0c;…...

leetCode !! word break

方法一&#xff1a;字典树动态规划 首先,创建node类&#xff0c;每个对象应该包含:一个node array nexts(如果有通往’a’的路&#xff0c;那么对应的nexts[0]就不该为null); 一个boolean 变量&#xff08;如果到达的这个字母恰好是字典中某个候选串的结尾&#xff0c;那么 标记…...

基础学习——关于list、numpy、torch在float和int等数据类型转换方面的总结

系列文章目录 Numpy学习——创建数组及常规操作&#xff08;数组创建、切片、维度变换、索引、筛选、判断、广播&#xff09; Tensor学习——创建张量及常规操作&#xff08;创建、切片、索引、转换、维度变换、拼接&#xff09; 基础学习——numpy与tensor张量的转换 基础学习…...

华纳云美国Linux服务器常用命令分享

美国Linux服务器系统目前也是跟Windows操作系统一样用户量非常多&#xff0c;其简单的纯命令操作模式可以节省很多系统空间&#xff0c;本文小编就来分享一些美国Linux服务器系统常用的命令&#xff0c;希望能够给刚入门的美国Linux服务器系统的用户提供一些操作参考。 1、系统…...

【minio】8.x版本与SpringBoot版本不兼容报错

错误异常&#xff1a; <minio.version>8.4.3</minio.version><spring-boot.version>2.6.13</spring-boot.version>Description:An attempt was made to call a method that does not exist. The attempt was made from the following location:io.min…...

如何用chatGPT赚钱?

赚钱思路 1&#xff09;初级-账号 对于新事物的出现&#xff0c;很多人对此都是抱着一个看热闹的态度&#xff0c;大家对于这个东西的整体认知水平是很低的&#xff01; 所以这个时候的思路就是快速去抢占市场&#xff0c;去各个平台发一些和ChatGPT相关的视频和文章去抢占市…...

【Go编程语言】流程控制

流程控制 文章目录 流程控制一、if 语句1.if 嵌套语句 二、switch 语句三、for 循环四、string 程序的流程控制结构一具有三种&#xff1a;顺序结构&#xff0c;选择结构&#xff0c;循环结构 顺序结构&#xff1a;从上到下&#xff0c;逐行执行。默认的逻辑 选择结构&#xf…...

Sql Server 自动备份

Sql Server 自动备份 文章目录 Sql Server 自动备份1. 打开SQL Server&#xff0c;在管理下找到”维护计划”&#xff0c;右键点击”维护计划向导”&#xff0c;如图&#xff1b;2. 再次点击维护计划向导3. 在选择维护任务下勾选”备份数据库”、”清楚维护任务”4.选择需要备份…...

ThreadLocal的应用

1. ThreadLocal 是什么 JDK 对ThreadLocal的描述为&#xff1a; 此类提供线程局部变量。这些变量与普通变量的不同之处在于&#xff0c;每个访问一个变量的线程&#xff08;通过其get或set方法&#xff09;都有自己的、独立初始化的变量副本。ThreadLocal 实例通常是类中的私有…...

中值滤波_中值滤波原理

均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(以目标象素为中心的周围8个象素,构成一个滤波模板,即去掉目标象素本身).再用模板中的全体像素的平均值来代替原来像素值.均值滤波也称为线性滤波,其采用的主要方法为领域平均法…...

day15 - 使用图像金字塔进行图像拼接

在我们之前的学习过程中&#xff0c;使用的都是恒定大小的图像&#xff0c;但是在某些情况下&#xff0c;我们需要使用不同分辨率的&#xff08;相同&#xff09;图像。例如&#xff0c;当在图像中搜索某些东西&#xff08;例如人脸&#xff09;时&#xff0c;我们不确定对象将…...

算法修炼之筑基篇——筑基一层初期(解决01背包问题)

✨博主&#xff1a;命运之光 ✨专栏&#xff1a;算法修炼之练气篇​​​​​ ✨博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;学习了算法修炼之练气篇想必各位蒟蒻们的基础已经非常的扎实了&#xff0c;下来我们进阶到算法修炼之筑基篇的学习。筑基期和练气期…...

JVM的空间结构

目录 一、概述 二、分类 1.程序计数器区域(Program Counter Register)&#xff1a; 2.Java虚拟机栈(Stack)&#xff1a; 3.堆区(Heap)&#xff1a; 4.方法区(Method Area)&#xff1a; 5.本地方法栈(Native Method Stack)&#xff1a; 一、概述 JVM分为5个主要区域&…...

图像分割的常用算法

图像分割是指将一幅图像划分成多个子区域或像素集合的过程&#xff0c;其中每个子区域或像素集合具有一定的统计特征或语义信息。图像分割是图像处理中的基础任务&#xff0c;其应用涵盖了医学影像、计算机视觉、机器人技术等多个领域。常用的图像分割算法包括&#xff1a; 1.…...

AI歌手真的可以吗

你听过AI歌手吗&#xff1f;近日&#xff0c;“AI孙燕姿”火遍全网&#xff0c;AI孙燕姿翻唱林俊杰的《她说》、周董的《爱在西元前》、赵雷的《成都》等等歌曲让网友听了直呼&#xff1a;“听了一晚上&#xff0c;出不去了。”你认为AI歌手会取代流行歌手成为主流吗&#xff1…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...