일단 확인 결과 CPU 사용량은 논리적코어 6개를 가짐
echo Runtime.getRuntime().availableProcessors() | docker run -i --rm openjdk:12.0.2 jshell -q
Jan 01, 2021 8:32:18 AM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
jshell> Runtime.getRuntime().availableProcessors()$1 ==> 6
jshell>
CPU 사용량 준수 확인 : SE 12
--cpus 키워드로 도커 컨테이너의 cpu 사용량을 설정 해보고 확인
컨테이너의 제한량을 준수하고 있는 상태를 확인
echo Runtime.getRuntime().availableProcessors() | docker run -i --rm --cpus 3 openjdk:12.0.2 jshell -q
Jan 01, 2021 8:37:29 AM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
jshell> Runtime.getRuntime().availableProcessors()$1 ==> 3
--cpu-shares 키워드로 호스트 과부하 시에 cpu 사용량을 제한 해보고 확인, default 는 1024, 즉 cpu 1개 이다.
호스트 과부하시 cpu 사용량은 2개로 제한되며 , 과부하가 없다면 2개 이상의 cpu 를 가져갈 수 있다.
echo Runtime.getRuntime().availableProcessors() | docker run -i --rm --cpu-shares 2048 openjdk:12.0.2 jshell -q
Jan 01, 2021 8:40:57 AM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
jshell> Runtime.getRuntime().availableProcessors()$1 ==> 2
jshell>
Memory 사용량 준수 확인 : SE 12
docker 는 메모리 할당 제한이 없을 경우 Host 의 메모리 1/4 을 컨테이너에 할당 시킨다.
- 현재 나의 Docker 메모리 할당량은 하나의 컨테이너 당 12G 이다.
JVM 은 메모리 할당 제한이 없을 경우 Host 의 메모리 1/4 을 MaxHeap 에 할당시킨다.
즉 OpenJdk 12 의 JVM 할당량은 Docker 컨테이너의 메모리에서 1/4 한 값이 된다.
docker run -it --rm openjdk:12.0.2 java -XX:+PrintFlagsFinal -version | findstr MaxHeapSize
size_t MaxHeapSize = 3338665984 {product} {ergonomic}
이를 증명하기 위해서 -m=?M 도커 옵션으로 컨테이너 메모리 사용량을 제한하고 JVM 메모리 할당량을 확인해본다.
- 1G 의 1/4 , 약 256M 정도가 할당되었다.
docker run -it --rm -m=1024M openjdk:12.0.2 java -XX:+PrintFlagsFinal -version | findstr MaxHeapSize
size_t MaxHeapSize = 268435456 {product} {ergonomic}
JVM 의 메모리 사용량을 설정하는 Xmx?m 키워드로 800M 로 JVM 메모리 할당량을 올려본다.
- JVM 기본 메모리 할당량과 관계없이 설정한 800M 의 MapHeapSize 를 가진다.
docker run -it --rm -m=1024M openjdk:12.0.2 java -Xmx800m -XX:+PrintFlagsFinal -version | findstr MaxHeapSize
size_t MaxHeapSize = 838860800 {product} {command line}
정말 준수하고 있을까?
- Docker 메모리 할당량은 1G 이므로 JVM 메모리 할당량은 256M 이다.
- 100M 짜리 배열을 선언하여 확인하면 문제가 없으나 500M 짜리 배열을 선언하면 OutOfMemoryError가 터진다.
echo new byte[100000000] | docker run -i --rm -m=1024M openjdk:12.0.2 jshell -q
Jan 01, 2021 11:11:47 AM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
jshell> new
...> byte[100000000]$1 ==>
///
echo new byte[500000000] | docker run -i --rm -m=1024M openjdk:12.0.2 jshell -q
Jan 01, 2021 11:14:23 AM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
jshell> new
...> byte[500000000]| Exception java.lang.OutOfMemoryError: Java heap space
| at (#1:1)
CPU 준수 확인 : SE 9
- 도커 컨테이너 CPU 사용량을 3개로 제한 ( --cpus 3 ) 해보고 실행
- jshell 로 사용가능한 CPU를 확인
- 3개로 나와야할 결과 값이 HOST 의 CPU 자원 전체로 확인 됨
- 즉 SE 9 는 도커 컨테이너의 CPU 자원 사용량을 무시한다.
echo 'Runtime.getRuntime().availableProcessors()' | docker run -i --rm --cpus 3 openjdk:9-jdk jshell -q
Jan 01, 2021 11:22:15 AM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
jshell> Runtime.getRuntime().availableProcessors()
$1 ==> 6
// 제한시켜도 SE 9 은 CPU 사용량 제한을 무시함
echo 'Runtime.getRuntime().availableProcessors()' | docker run -i --rm --cpu-shares 2048 openjdk:9-jdk jshell -q
Jan 01, 2021 11:25:52 AM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
jshell> Runtime.getRuntime().availableProcessors()
$1 ==> 6
메모리 준수 확인 : SE 9
- 도커 컨테이너의 메모리 할당량을 1G 로 제한 ( -m=?M )
- -it 로 터미널 커맨드사용
- -XX:+PrintFlagsFinal -version | findstr MaxHeapSize 로 JVM 메모리 사용량 확인
- 컨테이너하나당 할당된 12G 메모리 기준으로 JVM 메모리를 할당시켰음
- 즉, SE 9 는 도커 컨테이너의 메모리 할당량 제한을 무시한다.
docker run --rm -it -m=1024M openjdk:9-jdk java -XX:+PrintFlagsFinal -version | findstr MaxHeapSize
size_t MaxHeapSize = 3338665984 {product} {ergonomic}
메모리 할당 테스트를 SE 9 에서 실행하면 어떻게 될까.
- 100M 배열은 여전히 문제가 없다, 할당한 메모리가 1G 즉 JVM 할당 메모리는 256M 이므로 이는 문제가 없다.
- 500M 배열은 문제가 있다. Java 가 생각한 메모리 사용량은 12G 의 1/4 이니 작동하는게 정상이므로 배열 할당을 시도한다.
- JVM 메모리가 1G 를 초과하게 되면 Docker 컨테이너에 설정한 메모리를 넘어가 Docker 는 즉각 컨테이너를 종료시킨다.
- 이로인해 이유를 알 수 없게 종료된다.
echo 'new byte[100_000_000]' | docker run -i --rm -m=1024M openjdk:9-jdk jshell -q
Jan 01, 2021 11:35:04 AM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
jshell> new byte[100_000_000]
$1 ==> byte[100000000]
//500M
echo 'new byte[500_000_000]' | docker run -i --rm -m=1024M openjdk:9-jdk jshell -q
Jan 01, 2021 11:42:37 AM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
jshell> new byte[500_000_000]
| State engine terminated.
| Restore definitions with: /reload -restore
$1 ==>
결론
- docker 와 Java 로 심각한 작업 수행시 SE 10 스펙 이상의 이미지를 사용하는게 좋다.
'Docker 작업' 카테고리의 다른 글
Docker Tool Box 윈도우 공유 폴더 마운트 (0) | 2021.01.24 |
---|---|
도커 툴박스 포트 포워딩 (0) | 2021.01.23 |
Docker Compose 를 이용한 Fat.jar 들의 실행 (0) | 2021.01.02 |
OpenJDK 12.0.2 기반 Fat.jar 도커이미지 빌딩 (0) | 2021.01.01 |
Docker CPU 메모리 할당량, 최대 제한량 확인 (0) | 2021.01.01 |