단일 50GB 파일에서 Rsync 트리거 Linux OOM 킬러


66

server_A에 단일 50GB 파일이 있으며 server_B에 복사하고 있습니다. 난 달린다

server_A$ rsync --partial --progress --inplace --append-verify 50GB_file root@server_B:50GB_file

Server_B에는 2GB 스왑이있는 32GB RAM이 있습니다. 대부분 유휴 상태이며 많은 여유 RAM이 있어야합니다. 디스크 공간이 충분합니다. 약 32GB에서 원격 측이 연결을 닫았 기 때문에 전송이 중단됩니다.

Server_B가 이제 네트워크를 끊었습니다. 데이터 센터에 재부팅을 요청합니다. 커널 로그가 다운되기 전에 커널 로그를 보면 스왑이 0 바이트이고 프로세스 목록에 메모리가 거의 사용되지 않는 것으로 나타났습니다 (rsync 프로세스는 600KB의 RAM을 사용하여 나열 됨). 그러나 oom_killer는 거칠고 로그의 마지막 것은 metalog의 커널 리더 프로세스를 죽이는 것입니다.

이것은 커널 3.2.59, 32 비트입니다 (아무 프로세스도 4GB 이상 매핑 할 수 없음).

마치 오래 실행되는 데몬보다 Linux가 캐싱에 더 많은 우선 순위를 부여한 것처럼 보입니다. 무엇을 제공합니까 ?? 다시 발생하는 것을 어떻게 막을 수 있습니까?

다음은 oom_killer의 출력입니다.

Sep 23 02:04:16 [kernel] [1772321.850644] clamd invoked oom-killer: gfp_mask=0x84d0, order=0, oom_adj=0, oom_score_adj=0
Sep 23 02:04:16 [kernel] [1772321.850649] Pid: 21832, comm: clamd Tainted: G         C   3.2.59 #21
Sep 23 02:04:16 [kernel] [1772321.850651] Call Trace:
Sep 23 02:04:16 [kernel] [1772321.850659]  [<c01739ac>] ? dump_header+0x4d/0x160
Sep 23 02:04:16 [kernel] [1772321.850662]  [<c0173bf3>] ? oom_kill_process+0x2e/0x20e
Sep 23 02:04:16 [kernel] [1772321.850665]  [<c0173ff8>] ? out_of_memory+0x225/0x283
Sep 23 02:04:16 [kernel] [1772321.850668]  [<c0176438>] ? __alloc_pages_nodemask+0x446/0x4f4
Sep 23 02:04:16 [kernel] [1772321.850672]  [<c0126525>] ? pte_alloc_one+0x14/0x2f
Sep 23 02:04:16 [kernel] [1772321.850675]  [<c0185578>] ? __pte_alloc+0x16/0xc0
Sep 23 02:04:16 [kernel] [1772321.850678]  [<c0189e74>] ? vma_merge+0x18d/0x1cc
Sep 23 02:04:16 [kernel] [1772321.850681]  [<c01856fa>] ? handle_mm_fault+0xd8/0x15d
Sep 23 02:04:16 [kernel] [1772321.850685]  [<c012305a>] ? do_page_fault+0x20e/0x361
Sep 23 02:04:16 [kernel] [1772321.850688]  [<c018a9c4>] ? sys_mmap_pgoff+0xa2/0xc9
Sep 23 02:04:16 [kernel] [1772321.850690]  [<c0122e4c>] ? vmalloc_fault+0x237/0x237
Sep 23 02:04:16 [kernel] [1772321.850694]  [<c08ba7e6>] ? error_code+0x5a/0x60
Sep 23 02:04:16 [kernel] [1772321.850697]  [<c08b0000>] ? cpuid4_cache_lookup_regs+0x372/0x3b2
Sep 23 02:04:16 [kernel] [1772321.850700]  [<c0122e4c>] ? vmalloc_fault+0x237/0x237
Sep 23 02:04:16 [kernel] [1772321.850701] Mem-Info:
Sep 23 02:04:16 [kernel] [1772321.850703] DMA per-cpu:
Sep 23 02:04:16 [kernel] [1772321.850704] CPU    0: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850706] CPU    1: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850707] CPU    2: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850709] CPU    3: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850711] CPU    4: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850713] CPU    5: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850714] CPU    6: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850716] CPU    7: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850718] Normal per-cpu:
Sep 23 02:04:16 [kernel] [1772321.850719] CPU    0: hi:  186, btch:  31 usd:  70
Sep 23 02:04:16 [kernel] [1772321.850721] CPU    1: hi:  186, btch:  31 usd: 116
Sep 23 02:04:16 [kernel] [1772321.850723] CPU    2: hi:  186, btch:  31 usd: 131
Sep 23 02:04:16 [kernel] [1772321.850724] CPU    3: hi:  186, btch:  31 usd:  76
Sep 23 02:04:16 [kernel] [1772321.850726] CPU    4: hi:  186, btch:  31 usd:  29
Sep 23 02:04:16 [kernel] [1772321.850728] CPU    5: hi:  186, btch:  31 usd:  61
Sep 23 02:04:16 [kernel] [1772321.850731] CPU    7: hi:  186, btch:  31 usd:  17
Sep 23 02:04:16 [kernel] [1772321.850733] HighMem per-cpu:
Sep 23 02:04:16 [kernel] [1772321.850734] CPU    0: hi:  186, btch:  31 usd:   2
Sep 23 02:04:16 [kernel] [1772321.850736] CPU    1: hi:  186, btch:  31 usd:  69
Sep 23 02:04:16 [kernel] [1772321.850738] CPU    2: hi:  186, btch:  31 usd:  25
Sep 23 02:04:16 [kernel] [1772321.850739] CPU    3: hi:  186, btch:  31 usd:  27
Sep 23 02:04:16 [kernel] [1772321.850741] CPU    4: hi:  186, btch:  31 usd:   7
Sep 23 02:04:16 [kernel] [1772321.850743] CPU    5: hi:  186, btch:  31 usd: 188
Sep 23 02:04:16 [kernel] [1772321.850744] CPU    6: hi:  186, btch:  31 usd:  25
Sep 23 02:04:16 [kernel] [1772321.850746] CPU    7: hi:  186, btch:  31 usd: 158
Sep 23 02:04:16 [kernel] [1772321.850750] active_anon:117913 inactive_anon:9942 isolated_anon:0
Sep 23 02:04:16 [kernel] [1772321.850751]  active_file:106466 inactive_file:7784521 isolated_file:0
Sep 23 02:04:16 [kernel] [1772321.850752]  unevictable:40 dirty:0 writeback:61 unstable:0
Sep 23 02:04:16 [kernel] [1772321.850753]  free:143494 slab_reclaimable:128312 slab_unreclaimable:4089
Sep 23 02:04:16 [kernel] [1772321.850754]  mapped:6706 shmem:308 pagetables:915 bounce:0
Sep 23 02:04:16 [kernel] [1772321.850759] DMA free:3624kB min:140kB low:172kB high:208kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolate
d(file):0kB present:15808kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:240kB slab_unreclaimable:0kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB writeback_tm
p:0kB pages_scanned:0 all_unreclaimable? yes
Sep 23 02:04:16 [kernel] [1772321.850763] lowmem_reserve[]: 0 869 32487 32487
Sep 23 02:04:16 [kernel] [1772321.850770] Normal free:8056kB min:8048kB low:10060kB high:12072kB active_anon:0kB inactive_anon:0kB active_file:248kB inactive_file:388kB unevictable:0kB isolated(anon)
:0kB isolated(file):0kB present:890008kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:513008kB slab_unreclaimable:16356kB kernel_stack:1888kB pagetables:3660kB unstable:0
kB bounce:0kB writeback_tmp:0kB pages_scanned:1015 all_unreclaimable? yes
Sep 23 02:04:16 [kernel] [1772321.850774] lowmem_reserve[]: 0 0 252949 252949
Sep 23 02:04:16 [kernel] [1772321.850785] lowmem_reserve[]: 0 0 0 0
Sep 23 02:04:16 [kernel] [1772321.850788] DMA: 0*4kB 7*8kB 3*16kB 6*32kB 4*64kB 6*128kB 5*256kB 2*512kB 0*1024kB 0*2048kB 0*4096kB = 3624kB
Sep 23 02:04:16 [kernel] [1772321.850795] Normal: 830*4kB 80*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 1*4096kB = 8056kB
Sep 23 02:04:16 [kernel] [1772321.850802] HighMem: 13*4kB 14*8kB 2*16kB 2*32kB 0*64kB 0*128kB 2*256kB 2*512kB 3*1024kB 0*2048kB 136*4096kB = 561924kB
Sep 23 02:04:16 [kernel] [1772321.850809] 7891360 total pagecache pages
Sep 23 02:04:16 [kernel] [1772321.850811] 0 pages in swap cache
Sep 23 02:04:16 [kernel] [1772321.850812] Swap cache stats: add 0, delete 0, find 0/0
Sep 23 02:04:16 [kernel] [1772321.850814] Free swap  = 1959892kB
Sep 23 02:04:16 [kernel] [1772321.850815] Total swap = 1959892kB
Sep 23 02:04:16 [kernel] [1772321.949081] 8650736 pages RAM
Sep 23 02:04:16 [kernel] [1772321.949084] 8422402 pages HighMem
Sep 23 02:04:16 [kernel] [1772321.949085] 349626 pages reserved
Sep 23 02:04:16 [kernel] [1772321.949086] 7885006 pages shared
Sep 23 02:04:16 [kernel] [1772321.949087] 316864 pages non-shared
Sep 23 02:04:16 [kernel] [1772321.949089] [ pid ]   uid  tgid total_vm      rss cpu oom_adj oom_score_adj name
            (rest of process list omitted)
Sep 23 02:04:16 [kernel] [1772321.949656] [14579]     0 14579      579      171   5       0             0 rsync
Sep 23 02:04:16 [kernel] [1772321.949662] [14580]     0 14580      677      215   5       0             0 rsync
Sep 23 02:04:16 [kernel] [1772321.949669] [21832]   113 21832    42469    37403   0       0             0 clamd
Sep 23 02:04:16 [kernel] [1772321.949674] Out of memory: Kill process 21832 (clamd) score 4 or sacrifice child
Sep 23 02:04:16 [kernel] [1772321.949679] Killed process 21832 (clamd) total-vm:169876kB, anon-rss:146900kB, file-rss:2712kB

루트 사용자가 아닌 사용자로 rsync 명령을 반복 한 후 '맨 위'출력이 있습니다.

top - 03:05:55 up  8:43,  2 users,  load average: 0.04, 0.08, 0.09
Tasks: 224 total,   1 running, 223 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0% us,  0.0% sy,  0.0% ni, 99.9% id,  0.0% wa,  0.0% hi,  0.0% si
Mem:  33204440k total, 32688600k used,   515840k free,   108124k buffers
Swap:  1959892k total,        0k used,  1959892k free, 31648080k cached

sysctl vm 매개 변수는 다음과 같습니다.

# sysctl -a | grep '^vm'
vm.overcommit_memory = 0
vm.panic_on_oom = 0
vm.oom_kill_allocating_task = 0
vm.oom_dump_tasks = 1
vm.overcommit_ratio = 50
vm.page-cluster = 3
vm.dirty_background_ratio = 1
vm.dirty_background_bytes = 0
vm.dirty_ratio = 0
vm.dirty_bytes = 15728640
vm.dirty_writeback_centisecs = 500
vm.dirty_expire_centisecs = 3000
vm.nr_pdflush_threads = 0
vm.swappiness = 60
vm.lowmem_reserve_ratio = 256   32      32
vm.drop_caches = 0
vm.min_free_kbytes = 8192
vm.percpu_pagelist_fraction = 0
vm.max_map_count = 65530
vm.laptop_mode = 0
vm.block_dump = 0
vm.vfs_cache_pressure = 100
vm.legacy_va_layout = 0
vm.stat_interval = 1
vm.mmap_min_addr = 4096
vm.vdso_enabled = 2
vm.highmem_is_dirtyable = 0
vm.scan_unevictable_pages = 0

2
커널 충돌 메시지를 읽는 데는 전문가가 없지만 B에서 32GB의 코어를 사용하고 있다는 표시는 없습니다. 해당 가정을 계속 진행하기 전에 현재 상태인지 확인할 수 있습니까? 32GB 코어의 메모리 소진 상자와 4GB의 메모리 소진 상자에는 큰 차이가 있기 때문입니다.
MadHatter

최고 출력으로 업데이트되었습니다. 루트가 아닌 사용자와 동일한 rsync 명령을 실행 한 후입니다. 1GB를 제외한 거의 모든 것이 현재 캐시에 사용됩니다.
dataless

감사. 내가 말했듯이, 나는 전문가가 아니지만 점검 할 가치가있는 것처럼 보였다.
MadHatter

또한 커널이 스와핑을 허용하는지 (즉, 스와핑이 해제되어 있지 않은지) 확인해야합니다 (그리고 더 큰 디스크 공간을 할당해야합니다 (16Gb 또는 32Gb)). 인터넷상의 이상한 사람들은 스와핑을 끄는 것을 권장합니다.
Olivier Dulac

@OlivierDulac 무슨 설정을 말하는거야? 스왑 지원이 컴파일되었거나 스왑을 마운트 할 수없고 '스왑'이 60으로 설정되었습니다. 스왑 크기에 관해서는 32 비트 커널에서 문제가 더 악화되지 않습니까? 대답은 커널 데이터 구조가 우리를 죽인 것으로 보입니다. 우리는 32GB의 사용자 프로세스를 실행하지 않고 성능을 위해 디스크 캐시에 많은 양의 램을 원합니다.
데이터가 없음

답변:


178

oom-killer 출력을 읽고 거기서 배울 수있는 것을 보자.

OOM 킬러 로그를 분석 할 때 트리거 원인을 확인하는 것이 중요합니다. 로그의 첫 줄은 몇 가지 단서를 제공합니다.

[커널] [1772321.850644] clamd가 oom-killer를 호출했습니다. gfp_mask = 0x84d0, order = 0

order=0얼마나 많은 메모리가 요청되고 있는지 알려줍니다. 커널의 메모리 관리는 2의 거듭 제곱으로 만 페이지 번호를 관리 할 수 ​​있으므로 clamd는 2 0 페이지의 메모리 또는 4KB를 요청했습니다 .

GFP_MASK (사용 가능한 페이지 마스크 가져 오기)의 가장 낮은 두 비트 는 할당 자에게 메모리를 가져올 영역을 알려주는 소위 영역 마스크를 구성합니다 .

Flag            value      Description
                0x00u      0 implicitly means allocate from ZONE_NORMAL
__GFP_DMA       0x01u      Allocate from ZONE_DMA if possible
__GFP_HIGHMEM   0x02u      Allocate from ZONE_HIGHMEM if possible

메모리 영역 은 호환성 이유로 주로 만들어진 개념입니다. 단순화 된보기에는 x86 커널에 대한 세 가지 영역이 있습니다.

Memory range   Zone       Purpose 

0-16 MB        DMA        Hardware compatibility (devices)
16 - 896 MB    NORMAL     space directly addressable by the Kernel, userland 
> 896 MB       HIGHMEM    userland, space addressable by the Kernel via kmap() calls

귀하의 경우 zonemask는 0입니다. 이는 clamd가에서 메모리를 요청 함을 의미 ZONE_NORMAL합니다.

다른 깃발들은

/*
 * Action modifiers - doesn't change the zoning
 *
 * __GFP_REPEAT: Try hard to allocate the memory, but the allocation attempt
 * _might_ fail.  This depends upon the particular VM implementation.
 *
 * __GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller
 * cannot handle allocation failures.
 *
 * __GFP_NORETRY: The VM implementation must not retry indefinitely.
 */
#define __GFP_WAIT      0x10u   /* Can wait and reschedule? */
#define __GFP_HIGH      0x20u   /* Should access emergency pools? */
#define __GFP_IO        0x40u   /* Can start physical IO? */
#define __GFP_FS        0x80u   /* Can call down to low-level FS? */
#define __GFP_COLD      0x100u  /* Cache-cold page required */
#define __GFP_NOWARN    0x200u  /* Suppress page allocation failure warning */
#define __GFP_REPEAT    0x400u  /* Retry the allocation.  Might fail */
#define __GFP_NOFAIL    0x800u  /* Retry for ever.  Cannot fail */
#define __GFP_NORETRY   0x1000u /* Do not retry.  Might fail */
#define __GFP_NO_GROW   0x2000u /* Slab internal usage */
#define __GFP_COMP      0x4000u /* Add compound page metadata */
#define __GFP_ZERO      0x8000u /* Return zeroed page on success */
#define __GFP_NOMEMALLOC 0x10000u /* Don't use emergency reserves */
#define __GFP_NORECLAIM  0x20000u /* No realy zone reclaim during allocation */

에 따라 리눅스 MM 문서 , 그래서 당신의 requst가에 대한 플래그를 가지고 GFP_ZERO, GFP_REPEAT, GFP_FS, GFP_IOGFP_WAIT따라서 특히 까다 롭고없는 것.

무슨 일이야 ZONE_NORMAL? 일부 일반 통계는 OOM 출력에서 ​​추가로 찾을 수 있습니다.

[커널] [1772321.850770] 일반 무료 : 8056kB 최소 : 8048kB 낮음 : 10060kB 높음 : 12072kB active_anon : 0kB 비활성 _anon : 0kB active_file : 248kB 비활성 _ ​​파일 : 388kB 분리 할 수 ​​없음 : 0kB 격리 됨 ​​(anon) : 0kB 격리 됨 ​​(파일) : 0kB 절연 :

여기에서 눈에 띄는 점 free은 8K min이하 low입니다. 이것은 호스트의 메모리 관리자가 다소 어려움을 겪고 있으며 kswapd는 아래 그래프 의 노란색 단계와 같이 이미 페이지를 스왑 아웃해야 함을 의미합니다 . 리눅스 메모리 관리자 그래프

영역의 메모리 조각화에 대한 자세한 내용은 다음과 같습니다.

[커널] [1772321.850795] 일반 : 830 * 4kB 80 * 8kB 0 * 16kB 0 * 32kB 0 * 64kB 0 * 128kB 0 * 256kB 0 * 512kB 0 * 1024kB 0 * 2048kB 1 * 4096kB = 8056kB

기본적으로 4MB의 단일 연속 페이지가 있고 나머지는 주로 4KB 페이지로 크게 나뉘어 있음을 나타냅니다.

다시 요약하자 :

  • 당신의 (a 유저 랜드 프로세스가 clamd메모리를 받고) ZONE_NORMAL보통에서 수행 할 것이다 권한이없는 메모리 할당 반면,ZONE_HIMEM
  • 이 단계에서 메모리 관리자는 요청 된 4K 페이지를 제공 할 수 있었지만 ZONE_NORMAL
  • 로 시스템 kswapd의 규칙은 해야 사전에 어떤 페이징 활동을 봐 왔지만, 아무것도, 심지어 메모리의 압력, 스왑되지되는 ZONE_NORMAL명백한 이유없이,
  • 위의 어느 것도 왜 oom-killer호출되었는지에 대한 확실한 이유는 없습니다.

이 모든 것은 다소 이상해 보이지만 최소한 John O'Gorman의 "Linux Virtual Memory Manager 이해"서적의 2.5 절에 설명 된 내용과 관련이 있습니다 .

커널이 사용할 수있는 주소 공간 (ZONE_NORMAL)의 크기가 제한되어 있기 때문에 커널은 높은 메모리 개념을 지원합니다. [...] 1GiB와 4GiB 범위의 메모리에 액세스하기 위해 커널은 kmap ()을 사용하여 페이지를 고용량 메모리에서 ZONE_NORMAL로 임시 매핑합니다. [...]

즉, 1GiB의 메모리를 설명하려면 약 11MiB의 커널 메모리가 필요합니다. 따라서 16GiB에서는 176MiB의 메모리가 사용되므로 ZONE_NORMAL에 상당한 압력이 가해집니다. ZONE_NORMAL을 사용하는 다른 구조를 고려할 때까지 이것은 나쁘게 들리지 않습니다. PTE (Page Table Entry)와 같은 매우 작은 구조라도 최악의 경우 약 16MiB가 필요합니다. 이로 인해 16GiB는 x86에서 사용 가능한 실제 메모리 Linux의 실제 제한에 대해 설명합니다 .

(강조는 내 것입니다)

3.2는 2.6보다 메모리 관리에서 많은 발전을 이루었으므로 이것은 확실한 대답이 아니라 내가 먼저 추구 할 강력한 힌트입니다. mem=커널 매개 변수를 사용하거나 서버에서 DIMM의 절반을 리핑 하여 호스트의 사용 가능한 메모리를 최대 16G로 줄이십시오 .

궁극적 으로 64 비트 커널을 사용하십시오 .

야, 2015 년이야.


13
위에서 " 나는 전문가가 아닙니다 "라고 말했을 때 , 이것이 제가 읽고 싶은 내용입니다. 내가 할 수 있다면 +1000; +1입니다. 정말 좋은 답변입니다!
MadHatter

18
아름다웠다. SF에 대한 희망은 여전히 ​​있습니다.
로마

9
@dataless 예. 모든 ZONE_NORMAL이 상위 메모리 영역에 대한 메타 데이터로 채워져있는 것 같습니다. 사용자 페이지 프로세스가 메모리 페이지를 요청하는 경우 ZONE_HIGHMEM이 메모리 압력을 받고 있지 않는 한, ZONE_HIGHMEM을 요청하려고 할 가능성이 높습니다. ZONE_NORMAL에는 사용자 공간 프로세스 페이지가 없습니다.
the-wabbit

3
[키보드의 주먹을 푼다]이 wabbit에 현상금을주세요
underscore_d

3
@ the-wabbit 핫 네트워크 질문.
CodesInChaos

4

몇 가지 ...

스왑 공간에 대한 나의 경험의 규칙은 물리적 램의 최소 2 배가되어야한다는 것입니다. 이를 통해 페이지 / 스왑 데몬이 메모리를 효율적으로 재구성 할 수 있습니다.

Server_B에는 32GB의 램이 있으므로 64GB의 스왑에 맞게 구성하십시오. IMO, 서버가이 스왑 공간의 2GB의 인 방법 , 특히 서버, 너무 낮은.

스왑 파티션으로 만들 수있는 추가 파티션이없는 경우 파일을 생성하고 스왑 파티션으로 마운트하여 테스트 할 수 있습니다 [느려질 것]. https://www.maketecheasier.com/swap-partitions-on-linux/를 참조 하십시오

server_B는 충분한 디스크 공간을 가지고 있기 때문에 --inplace가 필요하지 않으며 rsync가 32GB를 사용하는 원인 일 수 있으므로 바람직하지 않을 수 있습니다. --inplace는 파일 시스템 공간이 부족하거나 특별한 성능 요구 사항이있는 경우에만 유용합니다.

내 생각에 rsync는 현재 옵션과 함께 50GB의 램 [파일 크기]을 사용하려고합니다. 일반적으로 rsync는 작업을 수행하기 위해 많은 메모리가 필요하지 않으므로 하나 이상의 옵션이 문제 일 수 있습니다. 문제없이 200GB 파일을 정기적으로 전송합니다.

옵션을 사용하지 않고 테스트를 수행하십시오. 10GB와 같은 작은 파일을 사용하면 커널 패닉을 방지 할 수 있지만 여전히 문제를 일으키는 동작을 모니터링 할 수 있습니다. rsync의 메모리 사용량을 모니터하십시오.

점차적으로 옵션을 한 번에 하나씩 다시 추가하여 어떤 옵션 [또는 옵션 조합]이 rsync가 RAM에서 피그 아웃을 시작하게하는지 확인합니다 (예 : 전송이 진행되는 동안 rsync의 램 사용량은 전송 된 파일 데이터의 양에 비례하여 증가합니다, 기타.).

rsync가 일부 in-ram 파일 이미지를 유지하도록하는 옵션이 정말로 필요한 경우 추가 스왑 공간이 필요하며 최대 파일 크기가 그에 따라 제한됩니다.

몇 가지 더 [업데이트] :

(1) 커널 스택 추적은 rsync가 mmap 영역에서 페이지 오류를 일으켰 음을 보여줍니다. 아마도 파일을 지우고있을 것입니다. mmap은 [읽기 / 쓰기와 달리] 파일이 닫힐 때까지 디스크로 플러시 될 것이라는 보장을하지 않습니다. [읽기 / 쓰기와 달리] FS 블록 캐시로 바로갑니다 [플러시 될 위치]

(2) 전송 크기가 RAM 크기에 도달하면 커널 충돌 / 패닉이 발생합니다. 분명히 rsync는 malloc 또는 mmap을 통해 많은 비 fscache 메모리를 가져옵니다. 다시 한 번 지정한 옵션으로 rsync는 50GB의 메모리를 할당하여 50GB 파일을 전송합니다.

(3) 24GB 파일을 전송하십시오. 아마도 효과가있을 것입니다. 그런 다음 mem = 16G로 커널을 부팅하고 24GB 파일 테스트를 다시 수행하십시오. 32GB가 아닌 16GB로 나옵니다. 이것은 rsync에 실제로 메모리가 필요하다는 것을 확인합니다.

(4) 스왑 추가가 터무니 없다고 말하기 전에 [스왑-파일 방법을 통해] 일부를 추가해보십시오. 스왑이 필요하지 않은 방법에 대한 모든 학문적 주장보다 훨씬 쉽게 수행하고 테스트 할 수 있습니다. 해결책이 아니더라도 무언가를 배울 수 있습니다. mem = 16G 테스트가 패닉 / 크래쉬없이 성공할 것이라고 확신합니다.

(5) rsync 스왑을 칠 가능성이 있지만 OOM이 시작되고 rsync를 종료하기 전에 top으로 볼 수 없습니다. rsync가 32GB가 될 때까지, 특히 유휴 상태 인 경우 다른 프로세스가 이미 스왑되도록 강제되었습니다. 아마도 "무료"와 "위"의 조합은 더 나은 사진을 제공 할 것입니다.

(6) rsync가 종료 된 후 mmap를 FS로 플러시하는 데 시간이 걸립니다. OOM만큼 빠르지 않으며 다른 것들을 죽이기 시작합니다 [일부는 미션 크리티컬입니다]. 즉, mmap flush와 OOM이 레이싱 중입니다. 또는 OOM에 버그가 있습니다. 그렇지 않으면 충돌이 발생하지 않습니다.

(7) 내 경험에 따르면, 일단 시스템이 "메모리 벽에 부딪 치면"Linux를 완전히 복구하는 데 시간이 오래 걸립니다. 그리고 때로는 실제로 제대로 복구되지 않으며 그것을 지우는 유일한 방법은 재부팅입니다. 예를 들어 12GB의 RAM이 있습니다. 40GB의 메모리를 사용하는 작업 (대규모 작업을 수용하기 위해 120GB의 스왑이 있음)을 실행 한 다음 종료하면 시스템이 정상적인 응답 상태로 돌아 오는 데 약 10 분이 소요됩니다 (디스크 표시등은 계속 켜져 있음). .

(8) 옵션 없이 rsync 실행하십시오 . 작동합니다. 작업 할 기본 예를 가져옵니다. 그런 다음 다시 추가하고 다시 테스트하십시오. 그런 다음 --append-verify를 대신 수행하십시오. 그런 다음 두 가지를 모두 시도하십시오. 거대한 mmap을 수행하는 rsync 옵션을 찾으십시오. 그런 다음없이 살 수 있는지 결정하십시오. --inplace가 범인이라면 디스크 공간이 충분하기 때문에 당연한 일입니다. 옵션이 필요한 경우 rsync가 수행 할 malloc / mmap을 수용 할 수있는 스왑 공간을 확보해야합니다.

두 번째 업데이트 :

위의 mem = 및 더 작은 파일 테스트를 수행하십시오.

중심 질문 : 왜 rsync가 OOM에 의해 살해됩니까? 씹는 기억은 누구입니까?

나는 시스템이 32 비트라는 것에 대해 읽었지만 잊었다. 따라서 rsync가 직접 책임을지지 않을 수도 있습니다 (malloc / mmap을 통해 -glibc는 익명 / 개인 mmap을 통해 큰 malloc을 구현합니다). rsync의 mmap 페이지 오류는 우연의 일치로 OOM을 트리거합니다. 그런 다음 OOM은 rsync가 직접 및 간접적으로 소비하는 총 메모리 (FS 캐시, 소켓 버퍼 등)를 계산하여 주요 후보로 결정합니다. 따라서 총 메모리 사용량을 모니터링하는 것이 도움이 될 수 있습니다. 파일 전송과 같은 속도로 충돌하는 것 같습니다. 분명히해서는 안됩니다.

빠른 루프에서 perl 또는 python 스크립트를 통해 / proc 또는 / proc / rsync_pid에서 모니터링 할 수있는 것 [bash 스크립트는 아마도 세계 종말 이벤트에 대해 충분히 빠르지 않을 것입니다.] 다음 몇 백 번 / 초. rsync보다 높은 우선 순위로 이것을 실행할 수 있으므로 RAM과 자체 실행 상태로 유지되므로 충돌 직전과 OOM 중에 희망 사항을 모니터링하여 OOM이 미친 이유를 알 수 있습니다.

/ proc / meminfo- "영향 지점"에서 스왑 사용에 대해보다 세밀한 정보를 얻습니다. 실제로, 얼마나 많은 RAM이 사용되는지에 대한 최종 수를 얻는 것이 더 유용 할 수 있습니다. top이이를 제공하지만 "빅뱅"직전의 우주 상태를 표시하기에는 충분히 빠르지 않을 수 있습니다 (예 : 마지막 10 밀리 초)

/ proc / rsync_pid / fd 디렉토리 심볼릭 링크를 읽으면 대상 파일에서 열린 fd를 식별 할 수 있습니다 (예 : / proc / rsync_pid / fd / 5-> target_file의 읽기 링크). 이것은 아마도 fd 번호를 얻기 위해 한 번만 수행하면된다 [고정되어야한다]

fd 번호를 알고 있으면 / proc / rsync_pid / fdinfo / fd를보십시오. 다음과 같은 텍스트 파일입니다.

위치 : <file_position>
플래그 : blah_blah
mnt_id : blah_blah

"마지막 파일 위치"가 유용 할 수 있으므로 "pos"값을 모니터링하면 도움이 될 수 있습니다. 다양한 크기와 mem = 옵션을 사용하여 여러 테스트를 수행하는 경우 마지막 파일 위치가 이러한 방법을 추적합니까? 일반적인 용의자 : 파일 위치 == 사용 가능한 RAM

그러나 가장 간단한 방법은 "rsync local_file server : remote_file"로 시작하여 작동하는지 확인하는 것입니다. "ssh server rsync file_a file_b"[먼저 50GB file_a를 만들어야합니다]를 수행하여 유사한 [그러나 더 빠른] 결과를 얻을 수 있습니다. file_a를 작성하는 간단한 방법은 scp local_system : original_file server : file_a이며 이는 그 자체로 흥미로울 수 있습니다 (예 : rsync가 충돌 할 때 작동합니까? scp가 작동하지만 rsync가 실패하면 rsync를 가리킴) scp가 실패하면이 점 NIC 드라이버와 같은 다른 것으로). ssh rsync를 수행하면 NIC가 방정식에서 빠져 나와 도움이 될 수 있습니다. 그것이 시스템을 호스로 만들면 실제로 잘못된 것입니다. 성공하면 [앞서 언급했듯이] 옵션을 하나씩 다시 추가하기 시작합니다.

요점을 다루는 것이 싫지만 파일 간 스왑을 통해 스왑을 추가하면 충돌 동작이 변경 / 지연 될 수 있으며 진단 도구로 유용 할 수 있습니다. 16GB와 같은 스왑을 추가하면 [메모리 사용량 또는 대상 파일 위치로 측정 된] 충돌이 32GB에서 46GB로 지연되면 무언가를 말합니다.

특정 프로세스는 아니지만 메모리를 씹는 잘못된 커널 드라이버 일 수 있습니다. 커널의 내부 vmalloc은 물건을 할당하고 교환 할 수 있습니다. IIRC, 모든 상황에서 접근성에 구속되지는 않습니다.

분명히 OOM은 혼란스럽고 당황하고 있습니다. 즉, 그것은 rsync를 죽이지 만 메모리가 적시에 해제 된 것을 보지 않고 다른 희생자를 찾습니다. 그들 중 일부는 아마도 시스템 작동에 중요합니다.

malloc / mmap을 제외하면 시간이 오래 걸리는 플러시되지 않은 FS 캐시로 인해 발생할 수 있습니다 (예 : 디스크 속도가 300MB / 초라고 가정하면 플러시하는 데 100 초가 걸릴 수 있음). 그 속도에서도 OOM이 너무 조급할 수 있습니다. 또는 OOM killing rsync가 FS 플러시를 충분히 빨리 시작하지 않습니다. 또는 FS 플러시가 충분히 빠르지 만 사용 가능한 풀로 페이지의 "게으른"릴리스가 있습니다. FS 캐시 동작을 제어하기 위해 설정할 수있는 / proc 옵션이 있습니다 [그들이 무엇인지 기억할 수 없습니다].

mem = 4G 또는 다른 작은 숫자로 부팅 해보십시오. 이로 인해 FS 캐시가 줄어들고 플러시 시간이 단축되어 OOM이 죽일 다른 항목을 찾지 않도록 할 수 있습니다 (예 : 플러시 시간이 100 초에서 <1 초로 감소). 또한 32 비트 시스템 등에서 4GB를 초과하는 물리적 램을 처리 할 수없는 OOM 버그를 마스크 해제 할 수 있습니다.

또한 중요한 점은 루트가 아닌 것으로 실행하십시오. 루트 사용자는 리소스를 씹을 것으로 예상되지 않으므로 더 많은 허용 한계가 있습니다 (예 : 메모리의 99 % 대 루트가 아닌 사용자의 경우 95 %). 이것은 OOM이 왜 그런 상태인지 설명 할 수 있습니다. 또한, 이것은 OOM et. 알. 기억을 되 찾는 일을 할 더 많은 헤드 룸.


고 메모리 시스템에서 얼마나 많은 SWAP 공간을 참조하십시오 ? -시스템이 63GB의 스왑을 사용하는 것을 원하지 않습니다. 사용할 수 없습니다.
마틴 슈뢰더

1
swap> RAM은 VM 오버 커밋없이 실행하는 경우에만 유용하므로 커널은 할당 된 페이지가 지저분 해지고 실제 실제 페이지를 백업 할 때까지 할당 된 페이지의 스왑 공간을 예약해야합니다. 현재 관행은 오버 커밋을 허용하고 적은 양의 스왑 공간으로 실행하여 시작시에만 터치되었고 정상적인 작업에는 필요하지 않은 페이지를 페이지 아웃하는 것입니다. 대부분의 시스템에서 RAM이 많으면 스왑이 적은 overcommit = 0이 좋습니다.
Peter Cordes

그 rsync를 정말 표시 됩니다 > 32기가바이트를 사용하려고, 그래서 스왑은 그 필요합니다. 즉, rsync는이 파일에 50GB를 사용합니다. 2 배는 30 년 동안 검증 된 진정한 지표입니다. 6TB 디스크는 ~ $ 300이므로 그렇게 할 이유가 없습니다. 이 서버에서 RAM 제한을 일괄 적으로 초과하는 다른 작업은 무엇입니까?
Craig Estey 23

1
@CraigEstey 64GB의 스왑은 앞에서 언급했듯이 큰 사용자 프로세스가없고 디스크 캐시 만 원하고 로그에서 보았 듯이 충돌 당시 ZERO 스왑을 사용했기 때문에 완전히 어리 석습니다. 제로. 또한 rsync는 50GB 파일에서도 600KB의 램을 사용합니다. 초기 혼란은 아마도 리눅스가 디스크 캐시를 공격적으로 잡고 있다는 것이 었습니다. 마지막으로이 상자에 더 이상 추가하기 전에 커널이 스왑 공간을 추적하는 데 사용하는 메모리 양에 대한 숫자 나 문서를보고 싶습니다.
데이터리스

@dataless 나는 무슨 일이 일어나고 있는지, 왜 그런지를 설명하는 추가 정보를 추가했습니다. rsync malloc / mmap을 통해 메모리를 가져오고 있으며 완료되기 전에 50GB가됩니다. 업데이트 된 섹션을 참조하십시오. 그것은 내가 말하는 것을 입증 / 반증 할 수있는 테스트를 가지고 있으며 추가 된 스왑을 건너 뛰고 테스트 할 수 있습니다. BTW, 나는 40 + 년 동안 커널 / 드라이버를 봤는데 프로그래밍 - 난 - 난 그냥 당신이 그렇게 분위기를 완화하십시오하지 않는 것을 알 수 있어요 도우려고합니다.
Craig Estey

2

조개? ClamAV를 사용하는 것처럼 들리고 안티 바이러스 엔진이 열려있는 파일에서 바이러스가 있는지 검사 하여 다른 프로세스에서 연 모든 파일의 전체 내용을 메모리에로드하여 온 액세스 검색을 사용하는 것처럼 보입니다 .

보안 상태와이 전송의 필요성에 따라 전송을 수행하는 동안 ClamAV 온 액세스 검색 사용 안함을 평가해야합니다.


나는 이것이 clamav가 할 수있는 일이라는 것을 알지 못했습니다 ... 그러나 우리는 clamc에서 파이프 된 특정 파일 만 스캔하지 않습니다. 또한 32 비트이므로 clamav가 모든 시스템 메모리를 호핑 할 위험이 없습니다. (우리는 왜 32 비트가 여전히 좋은 생각이라고 생각하는지 알 수 있습니까?)
데이터가 없음

1
Linux 커널은 clamd가 메모리 할당 요청이 OOM 킬러를 호출하는 프로세스라고보고합니다. ClamAV는 거의 확실히 2 차 원인입니다 (1 차 원인은 메모리가 충분하지 않음). 온 액세스 검색이든 다른 구성이든 관계없이 모든 표시는 ClamAV를 가리 킵니다.
OO.

다음에 rsync를 시작할 때 top을 실행하고 clamd 프로세스의 상주 크기를 모니터하십시오.
OO.

clamd는 oom killer를 호출하는 첫 번째 프로세스 였지만 무게는 약 42MB (서버에서 큰 프로세스 중 하나)에 달하기 때문에 가장 먼저 죽었습니다. oom_killer는 metalog가 죽을 때까지이 후에 반복적으로 실행됩니다.
dataless
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.