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

一个测试OOM killer的程序未触发OOM所带来的问题

概述

我们知道,由于MMU实现了虚拟地址到物理地址的转换,所以我们在申请虚拟地址时往往可以申请一大块内存,这实际上是对资源的有效利用,毕竟只有内存真正被投入使用时(如memset)才会实际分配物理内存,虚拟内存需要物理内存作为支撑,当分配了太多虚拟内存,导致物理内存不够时,就发生了Out Of Memory。

介绍下overcommit-memory机制

Linux 内核支持以下内存过度承诺处理模式:

vm.overcommit_memory = 0
启发式内存过度承诺处理。显而易见的地址空间过度承诺会被拒绝。适用于典型系统。它确保严重的过度承诺会失败,同时允许过度承诺减少交换使用量。在此模式下,root 用户可以分配略多一些内存。这是默认设置。(太明显的overcommit会被拒绝,比如malloc一次性申请的内存大小就超过了系统总内存,会上报给应用程序申请失败

vm.overcommit_memory = 1
总是过度承诺。适用于某些科学应用程序。经典示例是使用稀疏数组的代码,并依赖几乎完全由零页面组成的虚拟内存。(malloc申请内存可以被申请到,但是内存耗光会触发oom killer

vm.overcommit_memory = 2
不过度承诺。系统的总地址空间承诺不得超过交换空间加上可配置数量(默认为物理内存的 50%)。根据您使用的数量,在大多数情况下,这意味着进程在访问页面时不会被杀死,但在内存分配时会适当地收到错误信息。(通过overcommit_ratio,overcommit_kbytes可以修改这个比率,来限制可以申请的内存)

适用于希望保证其内存分配将来可用而无需初始化每个页面的应用程序。
内存过度承诺策略通过 sysctl 的 vm.overcommit_memory 来设置。

过度承诺数量可以通过 vm.overcommit_ratio(百分比)或 vm.overcommit_kbytes(绝对值)来设置。

当前的过度承诺限制和已承诺的数量可以通过 /proc/meminfo 中的 CommitLimit 和 Committed_AS 查看。

接下来举个例子:
当vm.overcommit_memory = 2时;

//系统默认情况如下:
# freetotal        used        free      shared  buff/cache   available
Mem:         196732       33028      141076          60       22628      156752
Swap:             0           0           0cat /proc/meminfo | grep ommit
CommitLimit:       98364 kB
Committed_AS:       5832 kB# cat /proc/sys/vm/overcommit_ratio
50
# cat /proc/sys/vm/overcommit_memory
0
# cat /proc/sys/vm/overcommit_kbytes
0
//cat test_50M.c 申请50M空间的测试程序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>int main()
{long *p = NULL;while(1) {p = (long *)malloc(0x3200000);if(!p){printf("p is null\n");return 0;}memset(p, 0x55, 0x3200000);printf("50M success\n");usleep(10000);}return 0;
}
//执行,结果发现,申请第二个50M的时候申请失败
./test_50M
50M success
p is null/ # echo 30 > /proc/sys/vm/overcommit_ratio
/ # cat /proc/meminfo | grep ommit
CommitLimit:       59016 kB
Committed_AS:       5432 kB
//上述操作可以看到过度承诺的内存限制变化了,变小了/ # echo 70 > /proc/sys/vm/overcommit_ratio
/ # cat /proc/meminfo | grep ommit
CommitLimit:      137712 kB
Committed_AS:       5408 kB
/ # ./test_50M
50M success
50M success
p is null
//上述操作可以看到申请第二个50M的时候申请成功了,第三个失败了

介绍下panic_on_oom

该选项用于启用或禁用内存耗尽时的系统紧急处理功能。

  • 若设置为 0,内核将终止某些恶意进程,称为 oom_killer。通常情况下,oom_killer 能够终止恶意进程,系统将能够继续运行。
  • 若设置为 1,当内存耗尽发生时,内核会发生紧急情况。然而,如果一个进程受到内存策略/内存掩码的限制,并且这些节点出现内存耗尽状态,oom-killer 可能会终止一个进程。在这种情况下不会发生紧急情况。因为其他节点的内存可能是空闲的。这意味着系统整体状态可能还未达到灾难性程度。
  • 若设置为 2,即使在上述情况下也会强制发生内核紧急情况。即使在内存控制组下发生内存耗尽,整个系统也会发生紧急情况。

系统默认值为 0。

1 和 2 是用于集群容错的故障切换。请根据您的故障切换策略选择其中一种。
panic_on_oom=2+kdump 可以提供非常强大的工具来调查内存耗尽的原因。您可以获得快照。

介绍下oom_kill_allocating_task

该选项用于启用或禁用在内存耗尽情况下终止触发OOM的任务。

  • 若设置为零,OOM killer 将扫描整个任务列表,并根据启发式选择一个任务进行终止。通常情况下,它会选择一个占用大量内存的恶意任务,在被终止时释放大量内存。
  • 若设置为非零值,OOM killer 将直接终止触发内存耗尽条件的任务。这避免了昂贵的任务列表扫描操作。

如果选择了 panic_on_oom,它将优先于 oom_kill_allocating_task 中使用的任何值。

默认值为 0。

总结panic_on_oom和oom_kill_allocating_task关系

当系统发生OOM的时候,根据panic_on_oom配置,走系统奔溃还是杀进程
panic_on_oom=0:杀进程,此时根据oom_kill_allocating_task的配置选择进程赴死

  • oom_kill_allocating_task=0,扫描所有进程,根据算法对进程打分,分高者赴死,此时可以通过oom_score_adj选项控制进程oom_score,手动干预算法。
    早期选项(已失效):文件在/proc//oom_adj。范围是[-17 ~ 15],数值越大表示越容易被oom
    killer杀死。如果进程的oom_adj配置为-17,表示进程禁止被OOM killer杀死。
    现在选项:文件在/proc//oom_score_adj。范围是[-1000 ~ 1000],数值越大表示越容易被oom
    killer杀死。oom_score_adj=-1000,表示完全禁止进程被oom杀死。
  • oom_kill_allocating_task非0,直接杀死触发OOM的进程;

如果panic_on_oom的配置不为0,那么oom_kill_allocating_task的配置就没什么用了;

======================================================================
说了这么多我们还没有进入正题,接下来我们说下标题的问题

问题描述

测试给了一段下面的代码,说为什么没有报OOM killer

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>int main()
{long *p = NULL;while(1) {p = (long *)malloc(0x3200000);usleep(10000);}return 0;
}

分析如下,我们发现内存并没有被真正的使用,印证了文章开头的一句话”只有内存真正被投入使用时(如memset)才会实际分配物理内存

/ # freetotal        used        free      shared  buff/cache   available
Mem:         196732       33084      143756          60       19892      156700
Swap:             0           0           0
/ #
/ # ./test &
/ # freetotal        used        free      shared  buff/cache   available
Mem:         196732       33676      143156          60       19900      156108
Swap:             0           0           0

修改代码为

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>int main()
{long *p = NULL;while(1) {p = (long *)malloc(0x3200000);memset(p, 0x55, 0x3200000);usleep(10000);}return 0;
}

执行如下,出现了Segmentation fault,有经验的工程师就会知道可能是malloc失败,p=NULL了,memset操作空指针了,导致的Segmentation fault (core dumped)。

./test
Segmentation fault (core dumped)

在这里再转移下注意力,linux内核的core dumped如何生成和分析的,可以参考如下帖子
https://zhuanlan.zhihu.com/p/582051703
https://zhuanlan.zhihu.com/p/661430797

我们再改下代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>int main()
{long *p = NULL;while(1) {p = (long *)malloc(0x3200000);if(!p){printf("p is null\n");return 0;}memset(p, 0x55, 0x3200000);usleep(10000);}return 0;
}执行结果是分配内存失败,并没有触发OOM Killer
```c
# ./test
p is null
/ # freetotal        used        free      shared  buff/cache   available
Mem:         196732       33668      155988          72        7076      156828
Swap:             0           0           0
# 介绍min_free_kbytes 
min_free_kbytes 是 Linux 内核参数,用于强制系统保持一定数量的空闲内存(以千字节为单位)。系统会根据这个数值为系统中每个低内存区域计算一个水印值(watermark)。每个低内存区域会根据其大小比例获得一定数量的保留空闲页。一定量的内存是需要用于满足 PF_MEMALLOC 分配需求的;如果将 min_free_kbytes 设置得低于 1024KB,系统可能会出现隐性问题,并在高负载下容易发生死锁。而将 min_free_kbytes 设置得过高可能会导致系统立即发生 Out Of Memory(OOM)情况。因此,在调整 min_free_kbytes 参数时,需要谨慎设置,避免设置过低导致系统问题,同时也要注意不要设置得过高导致系统内存不足。根据系统的实际情况和需求来合理配置这个参数,以确保系统的稳定性和性能表现。```c# cat /proc/sys/vm/min_free_kbytes
1771

我们按照1M内存分配,改下代码,执行发现可以触发oom killer

/ # ./test
[ 2991.645179] [King]: out_of_memory, oom_killer_disabled:0
[ 2991.650513] CPU: 1 PID: 1618 Comm: test Tainted: G           O      4.19.125 #1
[ 2991.657822] Hardware name: axera,ax620e (DT)
[ 2991.662091] Call trace:
[ 2991.664547]  dump_backtrace+0x0/0x120
[ 2991.668212]  show_stack+0x14/0x20
[ 2991.671529]  dump_stack+0x98/0xbc
[ 2991.674845]  out_of_memory+0x3c/0x350
[ 2991.678509]  __alloc_pages_nodemask+0x7cc/0x928
[ 2991.683043]  __handle_mm_fault+0x5d4/0x1058
[ 2991.687227]  handle_mm_fault+0x70/0xb8
[ 2991.690979]  do_page_fault+0x178/0x488
[ 2991.694729]  do_translation_fault+0x44/0x4c
[ 2991.698913]  do_mem_abort+0x3c/0xc8
[ 2991.702402]  el0_da+0x20/0x24
[ 2991.705448] test invoked oom-killer: gfp_mask=0x6200ca(GFP_HIGHUSER_MOVABLE), nodemask=(null), order=0, oom_score_adj=0
[ 2991.716299] CPU: 1 PID: 1618 Comm: test Tainted: G           O      4.19.125 #1
[ 2991.723619] Hardware name: axera,ax620e (DT)
[ 2991.727899] Call trace:
[ 2991.730369]  dump_backtrace+0x0/0x120
[ 2991.734048]  show_stack+0x14/0x20
[ 2991.737380]  dump_stack+0x98/0xbc
[ 2991.740708]  dump_header.isra.0+0x54/0x1f0
[ 2991.744815]  oom_kill_process+0xa8/0x484
[ 2991.748751]  out_of_memory+0x328/0x350
[ 2991.752511]  __alloc_pages_nodemask+0x7cc/0x928
[ 2991.757057]  __handle_mm_fault+0x5d4/0x1058
[ 2991.761251]  handle_mm_fault+0x70/0xb8
[ 2991.765014]  do_page_fault+0x178/0x488
[ 2991.768775]  do_translation_fault+0x44/0x4c
[ 2991.772970]  do_mem_abort+0x3c/0xc8
[ 2991.776471]  el0_da+0x20/0x24
[ 2991.779487] Mem-Info:
[ 2991.781777] active_anon:39528 inactive_anon:9 isolated_anon:0
[ 2991.781777]  active_file:32 inactive_file:48 isolated_file:0
[ 2991.781777]  unevictable:0 dirty:2 writeback:0 unstable:0
[ 2991.781777]  slab_reclaimable:1076 slab_unreclaimable:4176
[ 2991.781777]  mapped:19 shmem:18 pagetables:135 bounce:0
[ 2991.781777]  free:467 free_pcp:53 free_cma:0
[ 2991.813537] Node 0 active_anon:158112kB inactive_anon:36kB active_file:140kB inactive_file:212kB unevictable:0kB isolated(anon):0kB isolated(file):0kB mapped:148kB dirty:8kB writeback:0kB shmem:72kB shmem_thp: 0kB shmem_pmdmapped: 0kB anon_thp: 0kB writeback_tmp:0kB unstable:0kB all_unreclaimable? no
[ 2991.840178] Normal free:1868kB min:1768kB low:2208kB high:2648kB active_anon:158108kB inactive_anon:36kB active_file:224kB inactive_file:212kB unevictable:0kB writepending:8kB present:229108kB managed:196732kB mlocked:0kB kernel_stack:1344kB pagetables:540kB bounce:0kB free_pcp:148kB local_pcp:0kB free_cma:0kB
[ 2991.867702] lowmem_reserve[]: 0 0
[ 2991.871038] Normal: 82*4kB (UMEH) 39*8kB (UMEH) 12*16kB (UMEH) 11*32kB (UMEH) 3*64kB (MH) 2*128kB (H) 1*256kB (H) 0*512kB 0*1024kB 0*2048kB 0*4096kB = 1888kB
[ 2991.885166] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[ 2991.893615] 100 total pagecache pages
[ 2991.897320] 57277 pages RAM
[ 2991.900125] 0 pages HighMem/MovableOnly
[ 2991.904011] 8094 pages reserved
[ 2991.907212] 0 pages hwpoisoned
[ 2991.910407] Tasks state (memory values in pages):
[ 2991.915195] [  pid  ]   uid  tgid total_vm      rss pgtables_bytes swapents oom_score_adj name
[ 2991.923891] [   1345]     0  1345      930       42    40960        0             0 syslogd
[ 2991.932308] [   1349]     0  1349      930       50    40960        0             0 klogd
[ 2991.941037] [   1369]     0  1369      631       31    45056        0             0 tee-supplicant
[ 2991.950091] [   1390]     0  1390      930       39    45056        0             0 crond
[ 2991.958355] [   1398]     0  1398     1721      139    53248        0         -1000 sshd
[ 2991.966529] [   1403]     0  1403      930       27    40960        0             0 telnetd
[ 2991.974959] [   1405]     0  1405      930       27    45056        0             0 ifplugd
[ 2991.983384] [   1443]     0  1443      506       32    40960        0             0 axsyslogd
[ 2991.992003] [   1447]     0  1447      506       31    40960        0             0 axklogd
[ 2992.001507] [   1449]     0  1449      930       41    40960        0             0 sh
[ 2992.009459] [   1569]     0  1569      930       30    40960        0             0 getty
[ 2992.017646] [   1618]     0  1618    39533    39059   352256        0             0 test
[ 2992.025752] Out of memory: Kill process 1618 (test) score 795 or sacrifice child
[ 2992.033157] Killed process 1618 (test) total-vm:158132kB, anon-rss:156232kB, file-rss:4kB, shmem-rss:0kB
[ 2992.065409] oom_reaper: reaped process 1618 (test), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB

总结,当前内存剩余余量小于min_free_kbytes时就会触发OOM Killer,我们通过malloc 1M内存(相对小颗粒度)可以把内存耗到1771KB以下;

相关文章:

一个测试OOM killer的程序未触发OOM所带来的问题

概述 我们知道&#xff0c;由于MMU实现了虚拟地址到物理地址的转换&#xff0c;所以我们在申请虚拟地址时往往可以申请一大块内存&#xff0c;这实际上是对资源的有效利用&#xff0c;毕竟只有内存真正被投入使用时&#xff08;如memset&#xff09;才会实际分配物理内存&…...

SanctuaryAI推出Phoenix: 专为工作而设计的人形通用机器人

文章目录 1. Company2. Main2.1 关于凤凰™ (Phoenix)2.2 关于碳™(Carbon)2.3 商业化部署2.4 关于 Sanctuary Corporation 3. My thoughtsReference彩蛋&#xff1a;将手机变为桌面小机器人 唯一入选《时代》杂志 2023 年最佳发明的通用机器人。 称机器人自主做家务的速度和灵…...

李沐动手学习深度学习——4.2练习

1. 在所有其他参数保持不变的情况下&#xff0c;更改超参数num_hiddens的值&#xff0c;并查看此超参数的变化对结果有何影响。确定此超参数的最佳值。 通过改变隐藏层的数量&#xff0c;导致就是函数拟合复杂度下降&#xff0c;隐藏层过多可能导致过拟合&#xff0c;而过少导…...

CYQ.Data 支持 DaMeng 达梦数据库

DaMeng 达梦数据库介绍: 达梦数据库(DMDB)是中国自主研发的关系型数据库管理系统,由达梦科技股份有限公司开发。 达梦数据库提供了企业级的数据库解决方案,广泛应用于金融、电信、政府、制造等行业领域。 达梦数据库具有以下特点和优势: 高性能:具备高性能的并发处理…...

计网面试题整理上

1. 计算机网络的各层协议及作用&#xff1f; 计算机网络体系可以大致分为一下三种&#xff0c;OSI七层模型、TCP/IP四层模型和五层模型。 OSI七层模型&#xff1a;大而全&#xff0c;但是比较复杂、而且是先有了理论模型&#xff0c;没有实际应用。TCP/IP四层模型&#xff1a…...

code: 500 ] This subject is anonymous - it does not have any identifying

项目场景&#xff1a; 相关背景&#xff1a; 使用idea 开发java 项目&#xff0c;前端页面请求 页面中相关的接口时&#xff0c;idea 控制台有报错信息出现&#xff0c;前端请求失败。 问题描述 问题&#xff1a; 使用idea 开发java 项目&#xff0c;前端页面请求 页面中相…...

FC-AE-1553 协议

FC-AE-1553 协议 MIL-STD-1553B总线协议总线结构字格式消息传输方式 FC协议FC协议栈拓扑结构服务类型帧/序列/交换FC帧格式 FC-AE-1553网络构成帧类型命令帧状态帧数据帧 Information UnitsNC1NC2NC3-4NC5-7NT1-7 传输模式1. NC-NT2. NT-NC3. NT-NT4. 无数据字的模式命令5. 带数…...

代码随想录算法训练营day38|理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯

理论基础 代码随想录 视频&#xff1a;从此再也不怕动态规划了&#xff0c;动态规划解题方法论大曝光 &#xff01;| 理论基础 |力扣刷题总结| 动态规划入门_哔哩哔哩_bilibili 动态规划&#xff1a;如果某一问题有很多重叠子问题&#xff0c;使用动态规划是最有效的。所以动态…...

夫妻一方名下股权到底归谁?

生效判决摘要&#xff1a;1.夫妻一方在婚姻关系存续期间投资的收益&#xff0c;为夫妻的共同财产&#xff0c;归夫妻共同所有&#xff0c;但是并不能据此否定股权本身可能成为夫妻共同财产。婚姻关系存续期间登记在配偶一方名下的股权能否成为夫妻共同财产&#xff0c;可由司法…...

git根据文件改动将文件自动添加到缓冲区

你需要修改以下脚本中的 use_cca: false 部分 #!/bin/bash# 获取所有已修改但未暂存的文件 files$(git diff --name-only)for file in $files; do# 检查文件中是否存在"use_cca: false"if grep -q "use_cca: false" "$file"; thenecho "Ad…...

SystemVerilog Constants、Processes

SystemVerilog提供了三种类型的精化时间常数&#xff1a; •参数&#xff1a;与最初的Verilog标准相同&#xff0c;可以以相同的方式使用。 •localparameter&#xff1a;与参数类似&#xff0c;但不能被上层覆盖模块。 •specparam&#xff1a;用于指定延迟和定时值&#x…...

交易平台开发:构建安全/高效/用户友好的在线交易生态圈

在数字化浪潮的推动下&#xff0c;农产品现货大宗商品撮合交易平台已成为连接全球买家与卖家的核心枢纽。随着电子商务的飞速发展&#xff0c;一个安全、高效、用户友好的交易平台对于促进交易、提升用户体验和增加用户黏性至关重要。本文将深入探讨交易平台开发的关键要素&…...

Linux系统之部署复古游戏平台

Linux系统之部署复古游戏平台 前言一、项目介绍1.1 项目简介1.2 项目特点1.3 游戏平台介绍二、本次实践介绍二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 安装Docker环境3.2 检查Docker服务状态3.3 检查Docker版本3.4 检查docker compose 版本四、构建…...

开源计算机视觉库opencv-python详解

开源计算机视觉库opencv-python详解 OpenCV-Python的核心功能&#xff1a;安装OpenCV-Python&#xff1a;使用OpenCV-Python的基本步骤&#xff1a;OpenCV-Python的高级应用&#xff1a;注意事项&#xff1a;OpenCV-Python的高级应用示例&#xff1a;1. 人脸识别2. 目标跟踪3. …...

Vue开发实例(十)Tabs标签页打开、关闭与路由之间的关系

创建标签页 一、创建标签页二、点击菜单展示新标签页1、将标签数据作为全局使用2、菜单点击增加标签页3、处理重复标签4、关闭标签页 三、点击标签页操作问题1&#xff1a;点击标签页选中菜单进行高亮展示问题2&#xff1a;点击标签页路由也要跳转 四、解决bug 先展示最终效果 …...

基于51单片机的智能火灾报警系统

基于51单片机的智能火灾报警系统 摘要&#xff1a; 本文提出了一种基于51单片机的智能火灾报警系统。该系统采用烟雾传感器和温度传感器来检测火灾的发生&#xff0c;并通过单片机进行数据处理和报警控制。此外&#xff0c;该系统还具有无线通信功能&#xff0c;可以实时将火灾…...

【数据结构】堆的TopK问题

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解堆的TopK问题&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 一. 前言二. TopK三. 代码 一. 前言 TOP-K问题&#xff1a;即求数据结合中前K个最大的元…...

Vue后台管理系统笔记-01

npm&#xff08;Node Package Manager&#xff09;和 yarn 是两个常用的包管理工具&#xff0c;用于在 Node.js 项目中安装、管理和更新依赖项。它们有以下几个区别&#xff1a; 性能和速度&#xff1a;在包的安装和下载方面&#xff0c;yarn 通常比 npm 更快速。yarn 使用了并…...

飞天使-学以致用-devops知识点3-安装jenkins

文章目录 构建带maven环境的jenkins 镜像安装jenkinsjenkins yaml 文件安装插件jenkins 配置k8s创建用户凭证 构建带maven环境的jenkins 镜像 # 构建带 maven 环境的 jenkins 镜像 docker build -t 192.168.113.122:8858/library/jenkins-maven:jdk-11 .# 登录 harbor docker …...

08、MongoDB -- MongoDB 的 集合关联($lookup 和 DBRef 实现集合关联)

目录 MongoDB 的 集合关联演示前提&#xff1a;登录单机模式的 mongodb 服务器命令登录【test】数据库的 mongodb 客户端命令登录【admin】数据库的 mongodb 客户端命令 SQL 术语 与 Mongodb 的对应关系使用 $lookup 实现集合关联语法格式添加测试数据1、查询出订单数量大于6&a…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

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

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

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...

OD 算法题 B卷【正整数到Excel编号之间的转换】

文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的&#xff1a;a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...

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 …...

Linux基础开发工具——vim工具

文章目录 vim工具什么是vimvim的多模式和使用vim的基础模式vim的三种基础模式三种模式的初步了解 常用模式的详细讲解插入模式命令模式模式转化光标的移动文本的编辑 底行模式替换模式视图模式总结 使用vim的小技巧vim的配置(了解) vim工具 本文章仍然是继续讲解Linux系统下的…...