2021-01-29-TIL
2021-01-29-TIL
Java Docker MySQL
Java 애플리케이션과 MySQL을 각각 컨테이너로 띄우고 연결하는 방법을 다룬 글들이다. 애플리케이션 컨테이너에서 DB에 접속할 때는 localhost가 아니라 DB 컨테이너의 이름(같은 Docker 네트워크 안에서 DNS 이름으로 쓰인다)을 호스트로 써야 한다. 컨테이너 안의 localhost는 그 컨테이너 자신을 가리키기 때문이다. 두 컨테이너를 같은 사용자 정의 네트워크에 붙이거나 Docker Compose로 함께 띄우면 이름으로 서로를 찾을 수 있다.
https://www.linkedin.com/pulse/running-java-application-mysql-linked-docker-deepak-sureshkumar/
https://dzone.com/articles/mysql-in-java-application-docker
리스코프 치환 원칙
리스코프 치환 원칙(LSP)은 SOLID의 L로, 하위 타입의 객체는 상위 타입의 객체를 대체해도 프로그램의 올바름이 깨지지 않아야 한다는 원칙이다. 단순히 문법적으로 상속이 가능한지가 아니라, 상위 타입이 약속한 동작(사전조건, 사후조건)을 하위 타입이 지키는지가 기준이다. 자주 드는 예가 정사각형-직사각형 문제다. Square가 Rectangle을 상속하면서 너비를 바꿀 때 높이도 같이 바꾸면, 너비만 바뀔 것이라 기대한 Rectangle 사용 코드가 깨진다.
- https://jaepils.github.io/pattern/2018/07/04/liskov-substitution-principle.html
Java in Nutshell
O’Reilly의 『Java in a Nutshell』은 Java 언어와 핵심 플랫폼을 빠르게 찾아보는 레퍼런스 성격의 책이다.
https://www.amazon.com/Java-Nutshell-Desktop-Quick-Reference/dp/1492037257/ref=sr_1_1?dchild=1&keywords=Java+in+a+Nutshell&qid=1605393888&s=books&sr=1-1
Windows and containers
Microsoft 문서에 따르면 컨테이너는 호스트 OS의 커널 위에서 격리된 환경으로 실행되고, 커널이 제공하지 않는 사용자 모드 시스템 파일은 베이스 이미지로 함께 묶는다. 자체 커널을 포함한 전체 OS를 돌리는 가상 머신과 다른 점이다. 그래서 Windows 컨테이너는 Windows 계열 베이스 이미지(Windows Server Core, Nano Server 등)를 쓰고, 개발 환경에서는 Docker Desktop으로 Windows 기반과 Linux 기반 컨테이너를 모두 실행할 수 있다.
https://docs.microsoft.com/en-us/virtualization/windowscontainers/about/
Docker commands
아래는 실행 중인 컨테이너를 모두 멈추고 지운 뒤 이미지까지 강제로 지우는 정리 명령이다. docker ps -aq는 모든 컨테이너의 ID만, docker images -aq는 모든 이미지의 ID만 출력하므로 $( )로 감싸 다른 명령의 인자로 넘길 수 있다. Docker 문서에 따르면 docker system prune은 쓰지 않는 컨테이너, 네트워크, 이미지, 빌드 캐시를 지우고, --volumes를 붙여야 어떤 컨테이너도 쓰지 않는 익명 볼륨까지 지운다. 볼륨에는 DB 데이터가 들어 있을 수 있으므로 이 옵션은 신중하게 써야 한다.
https://captcha.tistory.com/49
docker stop $(docker ps -aq) ;
docker rm $(docker ps -aq);docker rmi $(docker images -aq) --force;
docker system prune --force; # 시스템 찌꺼기(DB파일까지) 완전히 삭제
docker system prune --volumes --force;
Transaction Isolation Level
논리적으로 Isolation이 되도록 구현된다.
트랜잭션 격리 수준은 동시에 실행되는 트랜잭션이 서로의 변경을 어디까지 볼 수 있는지 정한다. SQL 표준은 READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE 네 단계를 두고, 아래로 갈수록 dirty read, non-repeatable read, phantom read 같은 이상 현상을 더 많이 막는 대신 동시성이 떨어진다. MySQL 문서에 따르면 InnoDB의 기본 격리 수준은 REPEATABLE READ다. InnoDB는 모든 읽기를 잠금으로 막는 대신 MVCC(언두 로그로 과거 버전을 보여 주는 방식)로 일관된 읽기를 제공하는데, 위 메모의 “논리적으로” 격리된다는 말이 이 방식을 가리킨다.
http://www.yes24.com/Product/Goods/6104230
mysqld를 root로 실행할 때의 오류
컨테이너를 다시 시작했더니 아래처럼 mysqld가 root로 실행되는 것을 거부하고 종료됐다. MySQL 문서는 보안상 mysqld를 Unix root 사용자로 실행하지 말고 일반 사용자(보통 mysql)로 실행하라고 하며, --user 옵션이나 옵션 파일의 [mysqld] 섹션에 user=로 지정하는 방법을 안내한다. 로그 중간의 lower_case_table_names=2 경고는 데이터 디렉터리가 대소문자를 구분하지 않는 파일 시스템(macOS 호스트 볼륨)에 있어서 나온 것이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
$ docker start -i mysql-5.7
[Entrypoint] MySQL Docker Image 5.7.33-1.1.19
[Entrypoint] Starting MySQL 5.7.33-1.1.19
2021-01-29T02:23:31.259731Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2021-01-29T02:23:31.264986Z 0 [Note] mysqld (mysqld 5.7.33) starting as process 1 ...
2021-01-29T02:23:31.268758Z 0 [Warning] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
2021-01-29T02:23:31.268777Z 0 [ERROR] Fatal error: Please read "Security" section of the manual to find out how to run mysqld as root!
2021-01-29T02:23:31.268805Z 0 [ERROR] Aborting
2021-01-29T02:23:31.268820Z 0 [Note] Binlog end
2021-01-29T02:23:31.270376Z 0 [Note] mysqld: Shutdown complete
https://developpaper.com/please-readsecurity-to-find-out-how-to-run-mysqld-as-root/
NoSQL
- 채팅서비스를 관계형DB로 구현하면 하루에 1억건에 달하는 채탱메시지를 저장하고, 빠르게 반응하지 못한다.
채팅처럼 쓰기가 매우 많고 조회 패턴이 단순한(대화방별 최근 메시지) 데이터는 조인이나 트랜잭션보다 수평 확장과 쓰기 처리량이 중요하다. 그래서 여러 노드로 데이터를 나눠 담기 쉬운 NoSQL 저장소가 자주 후보에 오른다. 대신 스키마 변경, 복잡한 조회, 강한 일관성 같은 관계형 DB의 장점을 일부 포기하게 된다.
mysql bulk insert
여러 행을 넣을 때는 행마다 INSERT를 보내기보다 INSERT INTO t VALUES (...), (...), (...)처럼 한 문장에 여러 VALUES 목록을 담는다. MySQL 문서는 같은 클라이언트에서 많은 행을 넣을 때 이 방식이 단일 행 INSERT를 여러 번 보내는 것보다 상당히 빠르다고 설명한다. 네트워크 왕복과 문장 파싱 횟수가 줄기 때문이다.
기술지원으로 먹고산다
Docker rename
컨테이너 이름은 docker run --name으로 처음부터 정하거나, 이미 만든 컨테이너는 docker rename 기존이름 새이름으로 바꾼다. 이름을 지정하지 않으면 Docker가 임의의 이름을 붙인다.
https://www.tecmint.com/name-docker-containers/
Docker change port
포트 매핑(-p 호스트포트:컨테이너포트)은 컨테이너를 만들 때 정해지고, 이미 있는 컨테이너에는 명령 하나로 추가하거나 바꿀 수 없다. 링크된 답변들이 제시하는 방법은 현재 컨테이너를 docker commit으로 이미지로 만든 뒤 새 포트 매핑으로 다시 docker run하는 것이다. 데이터가 볼륨에 있다면 컨테이너를 새로 만들고 같은 볼륨을 붙이는 편이 깔끔하다.
https://stackoverflow.com/questions/19335444/how-do-i-assign-a-port-mapping-to-an-existing-docker-container
Docker Architecture
Docker는 클라이언트-서버 구조다. 사용자가 치는 docker CLI(클라이언트)는 REST API로 Docker 데몬(dockerd)에 요청을 보내고, 데몬이 이미지 빌드, 컨테이너 실행, 네트워크와 볼륨 관리를 맡는다. 이미지는 Docker Hub 같은 레지스트리에서 받아 오고 올린다.
- https://judekim.tistory.com/15
PowerToys
PowerToyz
Microsoft PowerToys는 Windows 고급 사용자를 위한 유틸리티 모음이다. 창 배치(FancyZones), 일괄 이름 변경 같은 도구를 제공한다.
비동기 카페 예제
아래 gist는 주문을 받는 쪽과 음료를 만드는 쪽을 분리한 비동기 카페 예제로, Swift의 delegate 패턴과 OperationQueue로 작성되어 있다. 주문 접수와 제조가 서로 기다리지 않고 진행되는 구조를 보는 데 참고할 수 있다.
https://gist.github.com/godrm/c32f3827fe4986f559e32a860f08f525
댓글
아직 댓글이 없습니다