Netty源码分析---waken方法详解

2027年新疆职业院校技能大赛“网络系统管理”A模块网络构建真题 2027年新疆职业院校技能大赛“网络系统管理”A模块——网络构建真题,仅供学习使用。 阅读详情

相关文章链接

位运算详解

waken方法详解

ThreadPerTaskExecutor与线程创建详解

processSelectedKeys() vs runAllTasks()

NioServerSocketChannel-Unsafe初始化详解

NioEventLoop的run方法详解

NioEventLoopGroup深度解析

inEventLoop方法详解

executionMask详解

Netty源码分析–认真系列(一)

Netty源码分析–认真系列(二)

问题一:SelectStrategy.CONTINUE 和 BUSY_WAIT

1. 这两种状态确实很少见

是的!在 NioEventLoop 中,这两个状态基本不会出现。

让我看看实际的代码:

// DefaultSelectStrategy 的实现
public final class DefaultSelectStrategy implements SelectStrategy {
    @Override
    public int calculateStrategy(IntSupplier selectSupplier, boolean hasTasks) throws Exception {
        // 只会返回两种情况:
        // 1. 如果有任务:返回 selectSupplier.get()(即 selectNow() 的返回值)
        // 2. 如果没任务:返回 SelectStrategy.SELECT(-1)
        return hasTasks ? selectSupplier.get() : SelectStrategy.SELECT;
    }
}

所以实际上只会返回:

  • SelectStrategy.SELECT(-1):没有任务时
  • >= 0 的数字:有任务时,selectNow() 的返回值

2. selectNow() 不会返回 CONTINUE 或 BUSY_WAIT

int selectNow() throws IOException {
    return selector.selectNow();  // JDK 的方法
}

selectNow() 的返回值:

  • >= 0:表示有多少个 Channel 准备好了
  • 永远不会返回负数
  • 永远不会返回 -2 或 -3

JDK 文档说明:

// java.nio.channels.Selector.selectNow()
// Returns: The number of keys, possibly zero
// 返回值:准备好的 key 的数量,可能是 0

3. CONTINUE 和 BUSY_WAIT 是为了扩展性

这两个常量是为了让 Netty 的设计更灵活,允许自定义的 SelectStrategy 实现返回这些值。

CONTINUE 的用途:

case SelectStrategy.CONTINUE:
    continue;  // 跳过本次循环,直接开始下一次

使用场景(理论上):

// 自定义的 SelectStrategy
public class MySelectStrategy implements SelectStrategy {
    @Override
    public int calculateStrategy(IntSupplier selectSupplier, boolean hasTasks) {
        if (某些特殊条件) {
            return SelectStrategy.CONTINUE;  // 跳过本次循环
        }
        return hasTasks ? selectSupplier.get() : SelectStrategy.SELECT;
    }
}

BUSY_WAIT 的用途:

case SelectStrategy.BUSY_WAIT:
    // fall-through to SELECT since the busy-wait is not supported with NIO

为什么 NIO 不支持?

  • Busy-wait 是指不断轮询,不阻塞
  • 这会消耗大量 CPU
  • NIO 的设计理念是事件驱动,不需要 busy-wait
  • 所以即使返回 BUSY_WAIT,也会 fall-through 到 SELECT

4. 总结

实际使用中:
├─ SelectStrategy.SELECT (-1)     ✓ 常见(没任务时)
├─ >= 0 的数字                     ✓ 常见(有任务时,selectNow() 返回)
├─ SelectStrategy.CONTINUE (-2)   ✗ 几乎不用
└─ SelectStrategy.BUSY_WAIT (-3)  ✗ 几乎不用

selectNow() 的返回值:
├─ 0      ✓ 没有 Channel 准备好
├─ 1      ✓ 有 1 个 Channel 准备好
├─ 2      ✓ 有 2 个 Channel 准备好
└─ ...    ✓ 更多

selectNow() 不会返回:
✗ -1 (SELECT)
✗ -2 (CONTINUE)
✗ -3 (BUSY_WAIT)

问题二:wakenUp 的作用

这是一个非常重要但容易混淆的机制。让我用最详细的方式解释。

1. wakenUp 是什么?

private final AtomicBoolean wakenUp = new AtomicBoolean();

wakenUp 是一个原子布尔变量,用于标记"是否有人想要唤醒 EventLoop"。

2. 为什么需要 wakenUp?

让我用一个问题场景来说明:

问题场景:竞态条件
时间线:

T1: EventLoop 线程准备调用 select()
    准备阻塞...

T2: 外部线程提交任务
    execute(task)
    addTask(task)  // 任务已加入队列
    selector.wakeup()  // 想要唤醒 EventLoop

T3: EventLoop 线程调用 select()
    selector.select()  // 开始阻塞

问题:
    如果 T2 的 wakeup() 在 T3 的 select() 之前调用
    那么 select() 可能不会被唤醒!
    因为 wakeup() 的效果只对"下一次" select() 有效

用图解释:

情况 A:正常情况
EventLoop 线程          外部线程
    |                      |
    |--select()            |
    |   阻塞中...          |
    |                      |--execute(task)
    |                      |
    |                      |--wakeup()
    |                      |
    |<--被唤醒              |
    |                      |
    ✓ 正常工作


情况 B:问题情况
EventLoop 线程          外部线程
    |                      |
    |--准备 select()       |
    |                      |--execute(task)
    |                      |
    |                      |--wakeup()
    |                      |   (但 select 还没开始)
    |                      |
    |--select()            |
    |   阻塞中...          |
    |   (wakeup 的效果已经用掉了)
    |                      |
    ✗ 无法被唤醒!任务得不到处理

3. wakenUp 如何解决这个问题?

完整的流程
// ===== EventLoop 线程 =====

// 步骤 1:准备 select 之前,设置 wakenUp = false
boolean oldWakenUp = wakenUp.getAndSet(false);
// 现在 wakenUp = false

// 步骤 2:调用 select(可能阻塞)
select(oldWakenUp);
    selector.select(timeoutMillis);

// 步骤 3:select 返回后,检查 wakenUp
if (wakenUp.get()) {
    // 如果 wakenUp = true,说明有人想唤醒
    selector.wakeup();  // 再唤醒一次,确保安全
}


// ===== 外部线程 =====

// 步骤 A:提交任务
execute(task);
addTask(task);

// 步骤 B:尝试唤醒
wakeup(false);
    // 尝试将 wakenUp 从 false 改为 true
    if (wakenUp.compareAndSet(false, true)) {
        // 成功改为 true,调用 wakeup
        selector.wakeup();
    }
详细的时间线分析

场景 1:wakeup() 在 select() 之前

T1: EventLoop 线程
    wakenUp.getAndSet(false)  // wakenUp = false

T2: 外部线程
    execute(task)
    addTask(task)
    wakenUp.compareAndSet(false, true)  // wakenUp = true ✓
    selector.wakeup()  // 调用 wakeup

T3: EventLoop 线程
    selector.select()  // 立即返回(因为刚才 wakeup 了)

T4: EventLoop 线程
    if (wakenUp.get())  // wakenUp = true
        selector.wakeup()  // 再唤醒一次

结果:✓ 正常工作

场景 2:wakeup() 在 select() 之后

T1: EventLoop 线程
    wakenUp.getAndSet(false)  // wakenUp = false

T2: EventLoop 线程
    selector.select()  // 开始阻塞

T3: 外部线程
    execute(task)
    addTask(task)
    wakenUp.compareAndSet(false, true)  // wakenUp = true ✓
    selector.wakeup()  // 唤醒 selector

T4: EventLoop 线程
    selector.select() 返回(被唤醒)

T5: EventLoop 线程
    if (wakenUp.get())  // wakenUp = true
        selector.wakeup()  // 再唤醒一次(这次可能不需要,但为了安全)

结果:✓ 正常工作

场景 3:wakeup() 在 select() 和检查之间

T1: EventLoop 线程
    wakenUp.getAndSet(false)  // wakenUp = false

T2: EventLoop 线程
    selector.select()  // 开始阻塞

T3: 外部线程
    execute(task)
    addTask(task)
    wakenUp.compareAndSet(false, true)  // wakenUp = true ✓
    selector.wakeup()  // 唤醒 selector

T4: EventLoop 线程
    selector.select() 返回

T5: 外部线程(又提交了一个任务)
    execute(task2)
    addTask(task2)
    wakenUp.compareAndSet(false, true)  // 失败!wakenUp 已经是 true
    // 不调用 selector.wakeup()

T6: EventLoop 线程
    if (wakenUp.get())  // wakenUp = true
        selector.wakeup()  // 再唤醒一次,确保 task2 也能被处理

结果:✓ 正常工作(通过再次 wakeup 确保安全)

4. wakenUp 的状态转换

初始状态:wakenUp = false

EventLoop 准备 select:
    wakenUp.getAndSet(false)  // 确保是 false
    ↓
    wakenUp = false

外部线程提交任务:
    wakenUp.compareAndSet(false, true)  // 尝试改为 true
    ↓
    如果成功:wakenUp = true,调用 selector.wakeup()
    如果失败:wakenUp 已经是 true,不需要再 wakeup

EventLoop select 返回:
    if (wakenUp.get())  // 检查是否为 true
        selector.wakeup()  // 再唤醒一次
    ↓
    下次循环会重新设置为 false

5. 用代码示例说明

// 示例:完整的交互过程

// ===== 循环开始 =====

// EventLoop 线程
wakenUp.getAndSet(false);  // wakenUp = false
System.out.println("准备 select,wakenUp = " + wakenUp.get());  // false

selector.select();  // 阻塞

// ===== 此时外部线程提交任务 =====

// 外部线程
execute(() -> System.out.println("任务"));
addTask(task);
System.out.println("任务已加入队列");

if (wakenUp.compareAndSet(false, true)) {
    System.out.println("wakenUp 改为 true,调用 wakeup");
    selector.wakeup();
} else {
    System.out.println("wakenUp 已经是 true,不需要 wakeup");
}

// ===== EventLoop 被唤醒 =====

// EventLoop 线程
System.out.println("select 返回");

if (wakenUp.get()) {
    System.out.println("wakenUp = true,再唤醒一次");
    selector.wakeup();
}

processSelectedKeys();
runAllTasks();  // 处理任务

// ===== 循环结束,回到开始 =====

6. 总结

wakenUp 的作用:

  1. 标记作用:标记是否有人想要唤醒 EventLoop
  2. 防止丢失唤醒:确保在任何时机提交任务都能唤醒 EventLoop
  3. 避免重复唤醒:如果已经有人唤醒了,就不需要再唤醒

关键点:

// EventLoop 线程
wakenUp.getAndSet(false);  // 重置为 false
select();                  // 可能阻塞
if (wakenUp.get()) {       // 检查是否有人想唤醒
    selector.wakeup();     // 再唤醒一次,确保安全
}

// 外部线程
if (wakenUp.compareAndSet(false, true)) {  // 尝试改为 true
    selector.wakeup();                     // 唤醒 selector
}

为什么要"再唤醒一次"?

因为 selector.wakeup() 的效果只对"下一次" select() 有效。如果在 select() 返回后又有新任务提交,需要确保下一次 select() 也能被唤醒。

希望这次解释清楚了!wakenUp 是一个精妙的设计,用于解决并发场景下的唤醒问题。

我来详细解释一下 wakenUp.compareAndSet(false, true) 这个方法的作用和原理。

阿里平头哥与华为芯片的比较 阿里平头哥与华为芯片代表了中国AI芯片领域的两种典型发展路径:平头哥通过兼容CUDA生态快速切入市场,以较低成本提供接近国际水平的AI算力;华为则坚持全栈自研路线,构建从芯片到框架的完整技术体系,更注重供应链安全和自主可控。从短期来看,平头哥PPU在单卡性能参数上全面超越昇腾910B,接近英伟达H20水平,且成本优势明显,有望在云服务和互联网应用领域取得更大市场份额。而华为昇腾则凭借全栈自研和端边云协同优势,在政企市场和科研领域更具竞争力。 阅读详情

相关推荐

stm32 + freertos + c++混合编程方法

其他一些资料上面,c++配置成--cpp11或者-cpp 都是把工程配置成c++。三、添加cpp文件,我们调用cpp文件里面的接口函数,不需要修改main.c后缀名。2、配置工程编译时候是--c99,是因为工程里面FreeRTOS是c语言,c++模式会报错。我们这里是默认c,编写的c++文件,单独选择--cpp编译,这在后面配置!c++是面向对象编程,对于一些项目来说,c++编程更加合适!stm32cubemax配置,这里就不写了,配置资料比较多。这里就是让cpp文件在c++下编译。最后,编程成功,点亮!

yuhu0012的博客 2630

五十三.网络(3)--区块同步getblocks消息

在节点互发了version消息后,就会发送getblocks消息,请求对方的区块以进行同步。

d3582077的专栏 189

【接地系统篇】电力系统接地技术详解:从基本原理到实际应用

接地是为电流返回电源提供的一条低阻抗通道。简单来说,就是为故障电流修建一条"安全回家"的路,防止电流通过人体或其他不应带电的部件。接地系统选择原则安全性优先:TN-S系统安全性最高,适合重要场所经济性考虑:TN-C系统成本最低,适合一般工业连续性要求:IT系统供电连续性最好,适合特殊场所灵活性选择:TN-C-S系统兼顾经济与安全,应用最广。

2301_81299416的博客 2232

Linux 服务器性能排查手册(2026):CPU、内存、磁盘IO、网络四大瓶颈定位

iptables 四表五链模型、firewalld zone 信任级别、云安全组与主机防火墙的关系与优先级,避坑改了防火墙把自己挡在服务器外面的翻车事故。

2502_91473995的博客 340

Windows10系统添加虚拟网卡(Microsoft Loopback Adapter)的方法

1、按下win + R键,在其中输入:hdwwiz,然后 (enter) 2、点击下一步即可 3、其次选择【网络适配器】,然后点击【下一步】。 4、在厂商处选择Microsoft,网络适配器处选择【Microsoft Loopback Adapter】选项 ,点击【下一步】。 5、通过上面几个步骤的设置后,一块虚拟网卡的安装设置就算是完成了。 ...

一个懒鬼的博客 2万+

Cadence psspxf实战:手把手教你仿真250MHz环形VCO的电源抑制比(附Verilog代码)

本文详细介绍了使用Cadence psspxf仿真器对250MHz环形VCO的电源抑制比(PSRR)进行仿真的全流程。从环形VCO的设计原理、Verilog代码实现,到Cadence环境配置、仿真参数设置,再到结果分析与优化技巧,提供了完整的实战指南。特别适合电路设计工程师学习如何评估和优化VCO的抗电源噪声能力。

weixin_42567752的博客 415

AI 芯片片上网络 NoC 深度解析:flit、虚通道与拥塞控制如何决定 GPU/TPU/LPU 的算力利用率

AI芯片算力瓶颈不在FLOPS,而在片上网络(NoC)——数据搬运的能耗与延迟决定MFU上限。物理限制下,长线延迟不随工艺缩小,迫使NoC将全局布线拆为可流水的短链路;能量账显示,一跳传输耗能可达数十次乘加操作。拓扑选择直接影响性能:二维mesh虽布线可行,但均匀流量下每节点可用带宽按1/√N衰减,实测仅达标称值30%。虚通道、双网设计、静态调度(如Groq)等技术旨在突破此瓶颈。从总线到crossbar再到多跳NoC,本质是用延迟换可行性。未来趋势:专用通路(脉动阵列)、晶圆级集成(Cerebras)、跨

我的博客 113

基于Spring Security 6的OAuth2 系列之二 - 客户端--非代码演示授权码模式

至此,我们就使用浏览器+postman工具演示了通过授权码模式去获取Gitee的用户信息。这过程中,我们只是遵循OAuth2的流程,就能够实现授权方法。那么接下来,我们采用代码方式来实现这个流程。

代码让AI扣 1813

网安产教融合思考:如何补齐高校实战能力评价短板

不少网安专业高校都面临这样现实的难题:网安人才培养持续推进,校内已经搭建完整的教学体系,但高校培养方案可能几年修一次,企业的技术栈和攻击手法却按季度在变,学校难落地最新的技术实战教学,学生难证明实战本领,企业一边喊人才紧缺,一边感慨招不到来了就能干的应届生。网安时代,实战为王。备考平台、7天免费直播培训、免费认证考试,期待更多高校加入 CCP 人才共育生态,组织本校学子参与本轮认证,以认证带动教学,以实战对接就业,共同为行业培养 “用得上、干得好” 的实战型网络安全人才。本次报名、培训、考试全程免费,

A19911511842的博客 195

KylinOS 离线安装 MinIO【图文步骤】

在国产操作系统 KylinOS 中安装 MinIO,详细步骤...

甘蓝的专栏 1536

Python学习第1天:初识Python

Python 作为目前最流行的编程语言之一,凭借其简洁优雅的语法和强大的生态系统,成为了无数开发者的首选。本系列文章将带你从零基础入门,逐步掌握 Python 编程的核心技能。今天我们先来认识 Python,并安装好开发环境。Python(英式发音:/ˈpaɪθən/;美式发音:/ˈpaɪθɑːn/)是由荷兰人吉多·范罗苏姆(Guido von Rossum)发明的一种编程语言,是目前世界上最受欢迎和拥有最多用户的编程语言。

tigerhhzz的博客 434

台湾行情数据API接入教程

想用程序获取台股行情,很多人第一步会搜“台股资料 API 推荐”,结果发现选择不少:证交所有免费接口,Yahoo Finance 也能查,券商还有自己的 API。真正写代码时才发现,有的数据只到收盘,有的延迟 20 分钟,有的必须先开户。本文先梳理台湾行情数据的几种获取渠道,再用 Python 从零搭一个可以运行的台股数据脚本:查代码清单、取实时报价和盘口、拉历史K线、做复权、用 WebSocket 接收实时推送,最后结合台积电 ADR 和新台币汇率计算跨市场溢价。

qq_34102871的博客 316

SIMULINK开发项目实例 1000 例专栏之第847例--基于飞行控制与稳定性的场景实例:多旋翼无人机在风扰动下的稳定性分析

本文介绍了使用Simulink进行多旋翼无人机风扰动稳定性分析的完整流程。首先建立包含动力学模型、控制系统和环境模拟三大模块的仿真系统,其中动力学模型基于牛顿-欧拉方程,控制系统采用PID调节器。重点展示了MATLAB函数实现的风扰动模型和姿态控制算法,通过设置输入信号和输出显示模块完成闭环仿真。最后通过多次风速条件下的仿真测试评估控制系统的抗干扰能力和稳定性表现,为无人机控制系统设计提供了有效的仿真验证方法。

xiaoheshang_123的博客 322

【基于 WebSocket 的多用户网页五子棋】—— 数据管理模块

但行好事,莫问前程

qq_42996461的博客 243

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Qt网络编程实战指南:从底层Socket到现代异步架构的选型与避坑

本文梳理Qt网络编程的核心模块与演进路线,对比QTcpSocket与QNetworkAccessManager的使用边界,结合HTTP请求与TCP长连接的完整示例,说明信号槽、内存管理与事件循环的配合方式。重点记录连接池设计、证书校验、线程亲和性等实际开发中的关键决策点,帮助读者在C/S或跨平台项目中建立稳定的网络层基座。

2402_83344867的博客 308

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

从母钟到子钟:NTP 网络时钟系统架构与软件接口

本文从工程角度简要介绍公共场所的时间同步需求、NTP协议的定位,以及典型LED同步时钟的系统架构与硬件设计,以讯鹏科技4寸与5寸同步时钟为例。

SPZHCS的博客 178

正运动16轴脉冲网络型运动控制卡ECI1G38

16轴脉冲运动控制解决方案

weixin_57350300的博客 80

DPVS 报文黑匣子与 Crash 自动拉黑:给转发面装上“飞行记录仪“

谁打挂了我(crash dump)、他之前发了什么(慢路径环)、他还会再来(入口拉黑)。设计上我们始终坚持两条原则:记录与决策分离(黑匣子永远只说不做),以及误伤成本优先于漏放成本(三道闸门全部通过才拉黑,expire 到期自动解封)。性能上,全量快路径摘要 + 入口查表的综合开销低于 1.3%,在 FIP 网关的流量水位下不可感知。飞行记录仪的价值不在于飞机正常飞行的时候,而在于它让每一次事故都变成一次改进。对转发面来说,同样如此。

zyun360的博客 279

全球实时竞价 RTB 中 IP 定位数据应用:链路完整性与工程实践

全球实时竞价(RTB)中IP定位数据的应用,核心判断是:IP数据是RTB竞价决策的底层输入之一,但它的价值高度依赖于从IP捕获到OpenRTB序列化整条链路的完整性。大量定位误差并非源于IP库本身不准,而是发生在CDN边缘节点捕获了错误的IP、供应链各环节使用了不同版本的库、或者OpenRTB字段缺失导致买方无法判断数据可信度。对于DSP和SSP的工程团队而言,理解IP定位在RTB中的实际作用边界,比选一个更准的库更重要。

ITxiaobing2023的博客 263

HTTP、SSE、WebSocket、Socket.IO:实时通信方案深度对比与选型指南

HTTP 是基础,是整个 Web 的底座;SSE 是单向推送的轻量最优解;WebSocket 是高性能双向实时通信的底层标准;Socket.IO 是一套降低开发门槛、抹平环境差异的上层框架。技术选型永远不是“哪个技术更酷”,而是匹配业务的实时性、交互方向、网络环境、团队维护成本。简单需求优先轻方案,复杂双向实时再上 WebSocket;如果追求快速落地、兼容各种奇葩网络,Socket.IO 是很好的选择。

changshuaihua001的博客 357

Linux网络编程:TCP多线程远程命令执行与线程池改造

前面已经实现了 TCP Echo Server,并且通过多进程和多线程解决了多个客户端连接的问题。不过目前服务器的业务还是比较简单,客户端发送什么,服务器就返回什么。这次在原来的多线程服务器上继续做一些改动,实现一个简单的远程命令执行功能。这次主要学习了两个内容。第一个是多线程远程命令执行。通过 Command 类封装命令的接收、检查、执行和结果返回,并使用 set 对允许执行的命令进行限制。第二个是线程池版本的 TCP Echo Server。通过和std::bind。

2501_93388101的博客 374

HART转Modbus TCP利用月度维护窗口减少中药产线停机时长

中药制药洁净车间原用HART仪表因仅传输4-20mA信号,诊断信息无法上传,导致GMP审计难、运维频繁进出洁净区。项目采用捷米特JM-TCP-HART协议转换网关,将HART数字信号转为ModbusTCP以太网数据,实现仪表状态、标定记录等信息远程采集与追溯。改造不改动原有控制逻辑,无需停机,保障生产连续性,满足洁净区安全与合规要求,验证了协议转换在存量设备升级中的高效可行性。

weixin_66215183的博客 228

亚远景-欧盟 NIS2 与 CRA 双法规生效,车载出口企业网络安全与过程合规建设要点

亚远景结合法规要求与车载行业特性,梳理双法规对整车与零部件出口企业的核心影响,说明如何以 ISO/SAE 21434 为核心、以 ASPICE 为过程底座,搭建满足欧盟要求的网络安全与过程合规体系。

yayuanjingkeji的博客 203

23 网络性能与 QoS:带宽、时延、吞吐计算与保障机制

带宽是上限、不是实际速度;时延由传输、传播、处理、排队四段组成。一道题让你算端到端时延和吞吐,关键是先找到瓶颈在哪一跳。QoS 靠分类、标记、队列、调度四步保障,配一张瓶颈定位+容量规划图,再跟 3 道真题。

weixin_46316564的博客 310

Agent 安全实战:间接提示注入的四个攻击面与防御体系

当 Agent 从 "生成内容" 走向 "执行动作",安全边界就从内容合规变成了权限越界。本文拆解间接提示注入在网页抓取、工具返回值、MCP 连接器、长期记忆四个位置的真实攻击路径,对照 Claude、GPT、Gemini 在工具调用权限模型上的设计差异,给出可直接落地的五层防御体系。

阡陌数智,专注大模型网关与 LLM 工程落地 269

python如何编通讯程序

通讯程序需要处理IP地址和端口。IP地址用于标识网络上的设备,端口用于标识设备上的服务。编写通讯程序时,需要选择合适的端口号并确保它不与其他服务冲突。此外

2601_96798011的博客 180

聊天室项目入口网关子服务的实现

上,客户端连接建立后发送首帧身份识别信息,网关反序列化出登录会话 ID 并到 Redis 中查证,查不到则直接关闭连接,查到则把该连接登记进长连接管理(维护用户 ID 与连接的映射),此后由网关按子服务返回的目标用户 ID 找到对应连接并推送通知——好友申请、申请处理结果、好友删除、会话建立与新消息五类通知皆由此发出。服务启动时先构造 Redis 客户端(承载登录会话与在线状态),再以服务根目录为监控范围创建服务发现客户端,把文件存储、语音识别、消息存储、好友管理、用户管理、消息转发。

2501_92042392的博客 119
上一篇: Netty源码分析---ThreadPerTaskExecutor与线程创建详解
下一篇: Netty源码分析---位运算详解
不早睡不改名@
博客等级 码龄5年 536粉丝 306原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值