안녕하세요. Readiness Probe 관련해 궁금한 부분이 생겨 질문드립니다. 강의에서 Rolling Update 중, 대상 그룹의 신규 Pod 대상이 Active 상태로 진입하기 전에 기존 Pod 대상이 Draining 상태로 전환되어 통신이 불가능한 상황에 Readiness Probe 설정으로 이를 개선할 수 있다고 하셨습니다. 하지만 위와 같은 상황에서 ALB 대상 그룹에서 new Pod(1)이 Initial 상태이고 old Pod(1)이 draining 상태인 경우, 통신이 불가능하다고 생각했습니다. (15초와 27초 사이) 따라서 이 문제는 Readiness Probe만으로 해결된다기보다는 Readiness Probe, Pod Graceful Shutdown, Termination Grace Period 세 가지 설정을 같이 사용할 때 개선될 수 있는 것으로 이해했습니다. 제가 제대로 이해한 것이 맞는지 궁금합니다. 또한 찾아보니 Readiness Gate를 사용하면 Pod가 ALB 대상 그룹에서 healthy인지 확인 후에 기존 Pod를 종료할 수 있다고 하는데, 이러한 설정도 실무에서 자주 사용하는지 궁금합니다. 감사합니다.
동시성 이슈에 발생할 수 있는 상황에서, A 변수에 대해 읽기 작업만 수행하는 코드(가시성 문제가 있을 수 있는 코드)에서는 volatile을 고려해볼 수 있고, A 변수에 대해 읽기 + 쓰기 작업도 있는 경우에는 synchronized와 atomic을 고려해볼 수 있겠네요. 제가 이해한 게 맞을까요?
강사님이 제공해주신 sprint 는 모두 들었고, helm 도 들었습니다. 아울러 자체적으로 IAM, Keycloak 등도 추가로 공부했습니다. 이제 강사님이 추가로 제공해줄 강의 sprint6 을 편하게 들으면서 더 깊게 하면 되겠구나 생각하고 있었는데 sprint6 계획이 없으시다고 하니 많이 애석합니다. 강사님 혹시 sprint6 에서 어떤걸 주제로 하시려 했는지요? (지난번 얼핏 타노스를 언급하시긴 했는데...) 알려주시면 저 혼자라도 공부하고 싶어서 여쭤 봅니다. 괜찮으시면 부탁드리겠습니다.
저는 Docker Desktop Kubernetes 환경에서 실습을 진행 중입니다. 강의 영상과 동일하게 Deployment와 NodePort 타입 Service를 생성했는데, 브라우저에서 localhost:30000으로 접속하면, ERR_CONNECTION_REFUSED가 발생하면서 접속이 되지 않습니다. 현재 제 실습 진행 상태입니다 ! (1) Pod는 정상 실행 중입니다. kubectl get pod 결과 3개 Pod 모두 Running 상태였습니다. (2) Spring Boot 애플리케이션도 컨테이너 내부에서 정상 실행 중입니다. kubectl logs 확인 시 Tomcat이 8080 포트로 정상 실행되었습니다. (3) Pod 내부에서 직접 요청하면 정상 응답이 옵니다. kubectl exec -it <pod명> -- curl localhost:8080/ → 결과: Hello, World! (4) Service도 Pod를 정상적으로 잡고 있습니다. kubectl describe service spring-service 확인했었을 때, Endpoints에 10.244.x.x:8080 형태로 Pod 3개가 정상적으로 표시되었습니다. 그런데 NodePort 방식으로 localhost:30000 접속이 되지 않았고, 로컬 PC 포트(30000)과 서비스 포트(8080)를 포트포워딩한 뒤에는 정상 접속이 되었습니다. kubectl port-forward service/spring-service 30000:8080 이후 localhost:30000으로 접속하니까 정상적으로 Hello, World가 나왔습니다. 강의 영상에서는 별도의 포트포워딩 없이도 NodePort로 정상 접속이 가능한데, 제 환경에서는 어떤 문제 때문에 접속이 되지 않는지 궁금합니다.
도커, 쿠버네티스와 같은 가상화 기술을 처음 배우는 입장입니다! 강의 초반에 컨테이너 기반 환경에서는 Host OS를 공유한다라고 보았는데 쿠버네티스 설치 강의 영상 속 이미지를 보면 각각의 노드안에 Guest OS 들이 있는걸로 보이는데 아래 두 가지 가설?이 맞나요? - Node들은 Guest OS가 필요함 - Node 안에 생성될 Pod에 생성 될 컨테이너들이 Guest OS가 필요 없음
설명중에 @Version 필드를 낙관적 락에서 이용할 수 있어가지고~ 라고 하셧는데 실제 돌려보니 비관적락 2에도 DB 업데이트가 되었습니다. AI 에게 물어보니 @Version 어노테이션이 붙은 필드는 JPA 사용시 @Lock 어노테이션 사용여부 상관없이 업데이트가 된다고 합니다. 혹 다른 qna 에도 같은 내용이 있는지 확인은 모두 안해 보았습니다. ======================== 응, 같은 엔터티 row에 실제 UPDATE 가 나가면 @Version 필드는 증가한다고 보면 돼. 락 방식이 낙관적이든 비관적이든 핵심은 이거야. @Version private Long version; 이 필드가 있는 엔터티가 dirty checking으로 변경 감지 되고, flush/commit 때 UPDATE 대상이 되면 JPA/Hibernate가 version 값을 같이 갱신해. ========================
안녕하세요. 우선 좋은 강의 제작해주신 토비님께 항상 감사하고 있어요. 이제 배운지 1년된 왕초보입니당.. 혼자 배워보면서 개인 프로젝트를 만들고 있는데 JPA를 사용하고 있어요. 제가 궁금한 것이... N+1 관련한 문제입니다. 아 일단 프로젝트 주제는 복식부기 가계부에요. @Entity ... public class Journal extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "ledger_id", nullable = false, updatable = false) @OnDelete(action = OnDeleteAction.CASCADE) private Ledger ledger; ... @OneToMany(mappedBy = "journal", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) private List<EntryLine> entries = new ArrayList<>(2); ... public EntryLine getEntryLine(EntrySide side) { switch (side) { case CREDIT : this.entries.stream().filter(line -> line.isCredit()).findFirst() .orElseThrow(...); case DEBIT : this.entries.stream().filter(line -> line.isDebit()).findFirst() .orElseThrow(...); default : throw new ... } } ... // Service에서 저장되기 전에 호출 public void validateSavable() { ... validateJournalSave(); } private void validateJournalSave() { AccountType debit = getEntryLine(EntrySide.DEBIT).getAccountType(); AccountType credit = getEntryLine(EntrySide.CREDIT).getAccountType(); if(!this.transactionType.isValidPlacement(debit, credit)) { throw new ... } } } Journal Class에서 EntryLine List에 접근하고 있어요. 그리고 EntryLine Class는 이렇게 생겼어요. @Entity ... public class EntryLine extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "journal_id", nullable = false, updatable = false) private Journal journal; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "account_id", nullable = false) private Account account; ... // private package 접근제어자 사용 // Account는 Category를 참조중이에요. AccountType getAccountType() { return this.account.getCategory().getAccountType(); } } 거래가 저장되기 전에 Journal : validateJournalSave() 에서 this.transactionType에 따라 차변과 대변에 올바르게 위치하고 있는지 검사한 후 저장하고 있는데 이것을 생성과 수정할 때 두 곳에서 사용하고 있어요. Ledger에 5개 Category가 있고, Account는 그 Category를 참조하고 Category에서만 AccountType이 있어요. Journal이 각 EntryLine의 AccountType을 얻기 위해 Journal -> EntryLine -> Account -> Category -> getAccountType() 이렇게 흘러가네요. 이렇게 접근해도 설계상 괜찮은걸까요? Journal을 저장할때는 @Query 사용해서 Fetch Join으로 필요한 Account를 가져오고 있는 상황이에요. Journal이라는 엔티티가 비즈니스 로직 수행을 위해서 다른 엔티티의 필드까지 깊게 참조?? 가져오도록 설계하는게 옳은건지 모르겠어요.
강사님 안녕하세요 아래부터 자세한 설명 없이 코드를 쳤는데 하둡 셋업할때 필수로 입력 해야 하는건가요? export PDSH_RCMD_TYPE=ssh ssh-keygen -t rsa -P "" cat ~/.ssh/id_rsa.pub>>~/.ssh/authorized_keys
volatile 관련해서 자료를 보다 보니, 일부 자료에서는 “CPU 캐시를 우회하는 것이 아니라 happens-before 관계와 메모리 배리어를 통해 가시성과 재정렬 제한을 보장한다”고 설명하더라고요. 골드 답변의 내용과 정반대되는 내용이라 혼란스러워서 어떻게 이해하면 좋을지 질문드립니다.