Netty 作为一个高性能的网络通讯框架,它内置了很多恰夺天工的设计,目的都是为了将网络通讯的性能做到极致,其中「对象池技术」也是实现这一目标的重要技术。

1.什么是对象池技术?

对象池技术是一种重用对象以减少对象创建和销毁带来的开销的方法。在对象池中,只有第一次访问时会创建对象,并将其维护在内存中,当再次需要使用对象时,会直接从对象池中获取对象,并在使用完毕后归还给对象池,而不是频繁地创建和销毁对象。

使用对象池技术的优点有以下几个:

  1. 提高性能:复用对象可以减少对象的创建和销毁次数,降低系统开销,提高系统性能和吞吐量。
  2. 减少内存碎片:对象池可以避免频繁地创建和销毁对象,减少内存碎片的产生,提高内存利用率。
  3. 避免频繁GC:减少了对象的创建和销毁,可以减少垃圾回收(GC)的频率,降低系统的负担,提高系统的稳定性。

2.对象池基本使用

Netty 对象池技术的核心实现类为 Recycler,Recycler 主要提供了以下 3 个方法:

  1. get():获取一个可重复使用的对象,如果对象池中有空闲对象,则返回其中一个;否则会创建一个新对象。
  2. recycle(T, Handle):回收一个对象,将对象放回对象池中以便下次复用。
  3. newObject(Handle):当对象池中没有可用对象时,此方法会被调用以创建新的对象实例。

接下来我们写一个 Recycler 对象池的使用 Demo,假设我们有一个 User 类,需要实现 User 对象的复用,具体实现代码如下:

public class UserRecyclerDemo {
private static final Recycler<User> userRecycler = new Recycler<User>() {
@Override
protected User newObject(Handle<User> handle) {
return new User(handle);
}
}; static final class User {
private String name;
private Recycler.Handle<User> handle;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public User(Recycler.Handle<User> handle) {
this.handle = handle;
}
public void recycle() {
handle.recycle(this);
}
} public static void main(String[] args) {
User user1 = userRecycler.get(); // 1.从对象池获取 User 对象
user1.setName("zhangsan"); // 2.设置 User 对象的属性
user1.recycle(); // 3.回收对象到对象池
User user2 = userRecycler.get(); // 4.从对象池获取对象
System.out.println(user1 == user2);
System.out.println(user2.getName());
}
}

以上程序的执行结果如下:

true

zhangsan

从上述结果可以看出,当第一次调用 userRecycler.get() 时,因为对象池中尚未存在 user 对象,所以创建了 name 为“zhangsan”的对象。但第二次再调用 userRecycler.get() 时,因为对象池中已经存在了 user 对象,所以直接从对象池中取出了 user 对象,所以 user1==user2 时,得到的结果是 true。

3.对象池技术应用

在 Netty 中,使用 Recycler 对象池管理对象的常见类有以下几个:

  1. PooledHeapByteBuf:管理堆内存中的 ByteBuf 对象。
  2. PooledDirectByteBuf:管理堆外内存中的 ByteBuf 对象。
  3. ChannelOutboundBuffer.Entry:Netty 出站缓冲区(ChannelOutboundBuffer)中,每一个待发送的消息都包装在一个 Entry 对象中。

4.实现原理

要搞清楚 Netty 对象池技术的实现原理,就要搞清楚 Netty 对象池的核心组件,以及组件之间的关系。

Netty 对象池技术的实现依靠以下 4 大组件:

  1. Stack(栈):每个线程都关联一个 Stack(使用 FastThreadLocal 进行存储),用于存储和管理该线程回收的对象。Stack 中存储的是 DefaultHandle 对象,这些 DefaultHandle 对象包装了实际要重用的对象。Stack 是与线程绑定的,每个线程从自己的 Stack 中获取对象。
  2. WeakOrderQueue(弱序队列):当某个线程(非主线程)回收对象时,这些对象不会直接放入主线程的 Stack 中,而是放入 WeakOrderQueue 中。WeakOrderQueue 存储的是从其他线程回收的对象,这些对象被包装在 DefaultHandle 中。WeakOrderQueue 与 Stack 关联,但属于非主线程。当主线程的 Stack 为空时,会尝试从 WeakOrderQueue 中获取对象。
  3. Link(链表):WeakOrderQueue 中的存储单元,用于存储回收的对象。Link 中存储的是 DefaultHandle 对象数组,这些数组包含从其他线程回收的对象。
  4. DefaultHandle:对象的包装类,在 Recycler 中缓存的对象都会包装成 DefaultHandle 类。DefaultHandle 中存储了实际要重用的对象,以及与之相关的元数据。

简单来说,这 4 个组件的关系是,(每个)线程为了保证线程安全和高效性操作,所以会把使用的对象放到 Stack 栈中,且每个线程都有自己的 Stack 栈。当线程中的对象不再被使用时(也就是被回收时),并不会将回收对象直接放到 Stack 中(因为当前线程已经不再使用了),此时会将对象存放到 WeakOrderQueue 队列中,因为 WeakOrderQueue 队列相当于“线程共享的区域”,这样其他线程就可以方便的从 WeakOrderQueue 中获取对象进行重用了。而 WeakOrderQueue 中的存储单元是 Link 链表,它存储的是对象池中的包装对象 DefaultHandle,这就是这四大核心组件之间的关系。

5.线程如何获取对象?

在 Netty 中,获取对象池中对象的流程如下:

  1. 判断 Stack:线程首先会尝试从自己的 Stack 中获取对象。如果 Stack 中有对象,则直接弹出(pop)并返回。
  2. Stack 为空:如果 Stack 为空,线程会检查 WeakOrderQueue。如果 WeakOrderQueue 中有对象,则按照一定的规则(如“1/7规则”,每 7 个移动 1 个)将部分对象转移到 Stack 中,然后从 Stack 中弹出并返回。
  3. 创建新对象:如果 Stack 和 WeakOrderQueue 都为空,线程会调用 newObject() 方法创建一个新的对象,并包装成 DefaultHandle 后放入 Stack 中,然后返回该对象。

通过这样的设计,Netty 的 Recycler 对象池技术能够高效地重用对象,减少内存分配和垃圾收集的开销,提升性能。

课后思考

Netty 是如何利用池化技术管理内存的?讲讲它的具体实现?

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。

面试官:说说Netty对象池的实现原理?的更多相关文章

  1. 面试官:Netty的线程模型可不只是主从多Reactor这么简单

    笔者看来Netty的内核主要包括如下图三个部分: 其各个核心模块主要的职责如下: 内存管理 主要提高高效的内存管理,包含内存分配,内存回收. 网通通道 复制网络通信,例如实现对NIO.OIO等底层JA ...

  2. Netty源码解析 -- 对象池Recycler实现原理

    由于在Java中创建一个实例的消耗不小,很多框架为了提高性能都使用对象池,Netty也不例外. 本文主要分析Netty对象池Recycler的实现原理. 源码分析基于Netty 4.1.52 缓存对象 ...

  3. 面试官:Netty心跳检测机制是什么,怎么自定义检测间隔时间?

    哈喽!大家好,我是小奇,一位热爱分享的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 书接上回,昨天在地里干了一天的 ...

  4. 笑死,面试官又问我SpringBoot自动配置原理

    面试官:好久没见,甚是想念.今天来聊聊SpringBoot的自动配置吧? 候选者:嗯,SpringBoot的自动配置我觉得是SpringBoot很重要的"特性"了.众所周知,Spr ...

  5. Java对象池技术的原理及其实现

    看到一片有关于java 对象基础知识,故转载一下,同时学习一下. 摘 要 本文在分析对象池技术基本原理的基础上,给出了对象池技术的两种实现方式.还指出了使用对象池技术时所应注意的问题. 关键词 对象池 ...

  6. 面试官:你分析过mybatis工作原理吗?

    Mybatis工作原理也是面试的一大考点,必须要对其非常清晰,这样才能怼回去.本文建立在Spring+SpringMVC+Mybatis整合的项目之上. 我将其工作原理分为六个部分: 读取核心配置文件 ...

  7. 给面试官讲明白:一致性Hash的原理和实践

    "一致性hash的设计初衷是解决分布式缓存问题,它不仅能起到hash作用,还可以在服务器宕机时,尽量少地迁移数据.因此被广泛用于状态服务的路由功能" 01分布式系统的路由算法 假设 ...

  8. Netty轻量级对象池实现分析

    什么是对象池技术?对象池应用在哪些地方? 对象池其实就是缓存一些对象从而避免大量创建同一个类型的对象,类似线程池的概念.对象池缓存了一些已经创建好的对象,避免需要时才创建对象,同时限制了实例的个数.池 ...

  9. netty源码分析 - Recycler 对象池的设计

    目录 一.为什么需要对象池 二.使用姿势 2.1 同线程创建回收对象 2.2 异线程创建回收对象 三.数据结构 3.1 物理数据结构图 3.2 逻辑数据结构图(重要) 四.源码分析 4.2.同线程获取 ...

  10. 抓到 Netty 一个隐藏很深的内存泄露 Bug | 详解 Recycler 对象池的精妙设计与实现

    欢迎关注公众号:bin的技术小屋,如果大家在看文章的时候发现图片加载不了,可以到公众号查看原文 本系列Netty源码解析文章基于 4.1.56.Final版本 最近在 Review Netty 代码的 ...

随机推荐

  1. HarmonyOS 性能优化

    如何合理使用动效来获得更好的性能 组件转场动画使用 transition: 推荐使用转场动画(transition)而不是组件动画(animateTo),因为 transition 只需要在条件改变时 ...

  2. nuxt按需引入组件库(却加载所有图标问题),nuxt性能优化。

    做一个官网,nuxt按需引入了antd_vue组件库,但是项目打包时,图标却又500K+,经过排查,发现icon和其他组件环环相扣的.如下:(我引入了这个翻页的组件,里面包含了两个翻页的图标) 但是它 ...

  3. 牛客网-SQL专项训练19

    ①下列哪个语句是授予用户SQLTest对数据库Sales的CUSTOMERS表的列cid.cname的查询权限(C) 解析: 授予权限的语法: GRANT <权限> ON 表名(列名) T ...

  4. HarmonyOS NEXT应用开发案例——行程地址交换动画

    介绍 本示例介绍使用显式动画 animateTo 实现左右地址交换动画.该场景多用于机票.火车票购买等出行类订票软件中. 效果预览图 使用说明 加载完成后显示地址交换动画页面,点击中间的图标,左右两边 ...

  5. 【实用教程】在配备持久内存的实例上部署Redis应用

    简介:配备持久内存的实例(例如re7p.r7p.re6p)提供了超大CPU内存配比,Redis应用运行在这类实例上可以大幅度降低单GiB内存的成本.本文以部分操作系统为例,介绍如何在这类实例上快速部署 ...

  6. 一文详解 | 开放搜索兼容Elasticsearch做召回引擎

    ​简介:开放搜索发布开源兼容版,支持阿里云Elasticsearch做搜索召回引擎,本文详细介绍阿里云ES用户如何通过接入开放搜索兼容版丰富行业分词库,提升查询语义理解能力,无需开发.算法投入,即可获 ...

  7. 【ESSD技术解读-03】阿里云块存储企业级特性之异步复制

    ​简介: 在大数据时代,数据就是企业的核心资产,是企业的生命线.在现实世界中,灾难时有发生,当发生灾难时,容灾能力成为企业能否生存的关键.云上容灾服务,通常称为 DRaaS(灾难恢复即服务)不但能够省 ...

  8. Alibaba FFI -- 跨语言编程的探索

    ​简介: 跨语言编程时现代程序语言中非常重要的一个方向,也被广泛应用于复杂的设计与实现中. 跨语言编程是现代程序语言中非常重要的一个方向,也被广泛应用于复杂系统的设计与实现中.本文是 GIAC 202 ...

  9. Python:Lambda

    Lambda >>> (lambda: 3)() # Using a lambda expression as an operator in a call exp. 经过查阅资料,理 ...

  10. Python:Short Circuiting -- “OR”

    Short Circuiting Operator Checks if: Evaluates from left to right up to: Example AND All values are ...