2023-11-23-TIL
Today I Learned
Redis Error
Redis에 대한 의존도가 높지 않게 설정하려면 어떻게 해야 하는가?
캐시는 원래 느린 저장소를 덜 찌르기 위한 계층이다. AWS의 캐싱 소개도 캐시의 주요 목적을 더 느린 기본 스토리지 계층에 접근할 필요를 줄여 데이터 검색 성능을 높이는 것으로 설명한다. 캐시는 데이터의 일부를 잠시 들고 있을 뿐이고 원본은 DB에 있다. 그렇다면 Redis가 죽었을 때 서비스 전체가 같이 실패하는 것은 캐시의 역할에 비해 과한 결과다. 캐시가 실패하면 느려지더라도 원본에서 읽어 응답하는 것이 맞다.
Spring Cache를 쓴다면 출발점은 CacheErrorHandler다. Spring Javadoc은 캐시에서 값을 가져오다 실패한 경우를 예외 대신 캐시 미스로 처리할 수 있다고 설명한다. 기본 구현인 SimpleCacheErrorHandler는 예외를 그대로 던지고, LoggingCacheErrorHandler는 로그만 남기고 넘어간다.
1
2
3
4
5
6
7
8
@Configuration
@EnableCaching
public class CacheConfig implements CachingConfigurer {
@Override
public CacheErrorHandler errorHandler() {
return new LoggingCacheErrorHandler();
}
}
이렇게 하면 @Cacheable 조회가 실패해도 메서드 본문이 실행되어 DB에서 값을 가져온다. 여기에 더해 고려할 것들이 있다.
- 타임아웃: 에러를 삼켜도 응답을 오래 기다리면 결국 요청 스레드가 묶인다. Redis 클라이언트의 연결, 명령 타임아웃을 짧게 둔다.
- DB 보호: 캐시가 빠지면 모든 요청이 DB로 몰린다. DB가 그 부하를 견딜 수 있는지, 아니면 일부 기능을 막는 편이 나은지 정해 둔다.
캐시가 원본인 데이터: 세션이나 분산 락처럼 Redis에만 있는 데이터는 위 방식으로 해결되지 않는다. 이런 용도는 캐시와 분리해서 가용성을 따로 설계해야 한다.
- https://papercut.blog/235
- https://aws.amazon.com/ko/caching/#:~:text=%EC%BA%90%EC%8B%9C%EC%9D%98%20%EC%A3%BC%EC%9A%94%20%EB%AA%A9%EC%A0%81%EC%9D%80,%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4%EC%99%80%EB%8A%94%20%EB%8C%80%EC%A1%B0%EC%A0%81%EC%9E%85%EB%8B%88%EB%8B%A4.
Today I Studied
Ingress Controller
Kubernetes의 Ingress는 클러스터 바깥의 HTTP 요청을 호스트나 경로에 따라 내부 Service로 보내는 규칙이다. 그런데 Ingress 리소스만 만들어서는 아무 일도 일어나지 않는다. Kubernetes 문서는 Ingress가 동작하려면 클러스터에 인그레스 컨트롤러가 실행 중이어야 하고, 이 컨트롤러는 클러스터와 함께 자동으로 시작되지 않는다고 설명한다. 컨트롤러가 Ingress 규칙을 읽어 실제 프록시 설정으로 바꾸는 주체다. NGINX, HAProxy, Traefik, Envoy 기반 Contour처럼 구현이 여럿 있고, 클라우드마다 로드 밸런서와 연동하는 컨트롤러도 있다. 한 클러스터에 컨트롤러를 여러 개 두면 IngressClass로 어떤 컨트롤러가 어떤 Ingress를 맡을지 나눈다.
- https://kubernetes.io/ko/docs/concepts/services-networking/ingress-controllers/
DNS for Pods
Kubernetes는 Service와 Pod 정보로 클러스터 DNS를 구성하고, kubelet이 Pod의 DNS 설정을 잡아 주어 컨테이너가 IP 대신 이름으로 Service를 찾게 한다(Kubernetes 문서).
- Service:
my-svc.my-namespace.svc.cluster.local형태의 이름이 Service의 클러스터 IP로 풀린다. 헤드리스 Service는 선택된 Pod들의 IP 목록으로 풀린다. - Pod: IP의 점을 하이픈으로 바꾼
172-17-0-3.default.pod.cluster.local같은 이름을 가진다. dnsPolicy: 기본값ClusterFirst는 클러스터 DNS를 먼저 쓰고,Default는 노드의 DNS 설정을 그대로 물려받는다. 이름은Default인데 기본값이 아니라는 점이 헷갈린다.
같은 네임스페이스 안에서는 my-svc만 써도 찾을 수 있지만, 다른 네임스페이스의 Service는 my-svc.other-namespace처럼 네임스페이스까지 적어야 한다.
- https://kubernetes.io/ko/docs/concepts/services-networking/dns-pod-service/
Upstream Server
업스트림 서버는 프록시 뒤에서 실제로 요청을 처리하는 서버다. Nginx에서는 upstream 블록으로 이 서버 묶음을 정의한다. Nginx 문서에 따르면 upstream은 proxy_pass 등에서 참조하는 서버 그룹이고, 기본 분산 방식은 가중치 라운드 로빈이다. max_fails와 fail_timeout으로 실패가 몇 번 나면 그 서버를 얼마 동안 빼 둘지 정한다. 기본값은 각각 1회, 10초다.
1
2
3
4
5
6
7
8
9
10
upstream backend {
server app1.example.com weight=5;
server app2.example.com max_fails=3 fail_timeout=30s;
}
server {
location / {
proxy_pass http://backend;
}
}
- https://www.techopedia.com/definition/9866/upstream-networking
- https://academic-accelerator.com/encyclopedia/kr/upstream-server
댓글
아직 댓글이 없습니다