목록전체 글 (279)
ecsimsw

대규모 업데이트IoT 서비스를 운영하는 우리 회사는 외부 IoT 플랫폼 위에서 애플리케이션단을 개발해 왔다.재작년부터 플랫폼을 독자적으로 운영하기 위한 준비를 해왔고, 최근에 배포를 마쳤다.아예 플랫폼을 사 와 직접 운영하기로 한 것이다. 신규 플랫폼 서버 로직에 문제가 있어 기기 순서가 뒤섞였던 상황그 문제를 수정, 배포하는 과정에서 서버 리소스 부족이 고객들에게 노출되었던 상황특정 앱에서 신규 플랫폼의 특정 기기 사용에 제한이 되는 상황 생각만큼 문제가 많았다.특히 회사 간 엮인 급한 이슈 거리들이 많아 밤도 많이 새웠다. 배포 후 2주일 정도 지난 지금, 여전히 바쁜 나날을 보내고 있다.그래도 커다란 이슈들은 어느 정도 잡히고 작은 이슈들만 남아 있는 상태이다. 지금까지의 업무 경험 중 가장 체력..

배경회사 IoT 플랫폼 서버를 국외에서 국내 리전으로 모두 옮기고 있다. 배포 시점 이후 페어링한 기기들은 모두 신규 국내 서버에서 관리되나, IoT 기기 특성상 기기 페어링을 유지한 채로 데이터를 다른 서버로 옮기는 것이 불가능하다. 따라서 당분간 기존의 서버와 신규 서버가 동시에 운영되어야 하는 상황이다. 이런 와중에 우리 회사의 Open api를 사용하여 서비스를 운영하는 회사에서 Api 이용이 너무 느리다는 이슈를 보고해 줬고, DB 커넥션 부족을 확인하여 문제를 풀이했던 경험을 소개한다. 원인 파악당장 확인할 수 있는 로그는 다음과 같았다. Servlet filter 사용자 요청 인입 기록/// 5초 이상의 텀 /// DB 조회 결과 로그IoT 플랫폼 서버 Api 호출IoT 플랫폼 서버 A..

배경 소개 팀에서 새로 인프라 구조, 아키텍처를 구성해야 하는 일이 있었다. 우리 팀은 Container 기반으로 서버를 운영하여, AWS ECS + Fargate를 사용하여 배포하기로 결정했다. 이때 VPC, ECR, ECS의 배포 정책이나 오토 스케일링을 모두 Terraform으로 관리하여 인프라 구성을 코드로 작성할 수 있도록 작업하였다. 이 글에선 이런 구조를 선택한 근거와 함께, 테라폼을 사용해서 얻을 수 있었던 팀 시점의 이점을 소개하려고 한다. ECS + Fargate우선 컨테이너를 사용한 배포를 전제로 하였다. 배포를 위한 파일 관리보다 컨테이너 이미지 관리가 훨씬 쉽고, 컨테이너 런타임만 있는 환경이라면 쉽게 배포하고 앱을 확인해 볼 수 있으니까. AWS의 '이 글'을 참고하여 우리 팀에..

이벤트 전달 구조 개선회사의 기기 이벤트 전달 구조를 SNS+SQS 조합으로 개선한 경험을 소개한다. 기존에는 아래 그림에서 Event producer가 Http로 각 서비스에 이벤트를 전달했는데, 기기가 늘어남에 따라 많아진 이벤트를 빠르게 처리할 수 있으면서도 유실에 안정적인, 그러면서도 서비스 확장에 유연한 아키텍처를 고민하게 되었다. 작은 팀이니만큼 러닝 커브가 적고, 인프라 비용에 큰 부담이 없었으면 좋겠다는 생각이었다. 이벤트 전달 구조 / SQS 도입 이유1. 직접 전달, 이벤트 유실과 의존 문제 Http 직접 전달은 위험하다. 수신하는 서버에 문제가 발생하는 경우, 그 시간 동안 직접 전달된 이벤트는 유실된다. 또 전송자는 수신하는 서버의 정보를 모두 알아야 하기 때문에, 수신 서비스가 늘..

OOM 발생회사 기기 수가 급격하게 늘고 있다. 100만대를 축하한게 불과 3,4개월 전이었던거 같은데 벌써 200만대를 넘었다. 기기 수가 늘어남에 따라 기기 이벤트 수가 급증했고, 기기 이벤트를 수신하여 후처리 하는 서버에서 OOM이 발생하는 문제가 생겼다. 특정 시간대에서 스파이크성 트래픽이 발생하는 것은 아니고, 서버를 실행하고 N시간 후에 OOM과 함께 서버가 다운된다. 이 글에선 해당 문제를 모니터링했던 방법과 원인, 해결 방안을 정리한다. 원인 파악메모리 누수 파악 서버의 힙 메모리와 GC 동작 기록이다. 위 보드의 노란색이 Old Gen, 아래 보드의 파란색과 녹색이 각각 Minor GC, Major GC이다. GC 동작 이후에도 Old Gen의 최저 수위가 점점 높아지는 것을 볼 수 ..
롤백에 의해 정합성이 깨지는 문제아래 update()에선 id에 해당하는 person의 이름을 수정한다. DB에서 person을 조회하고, Transaction이 종료되며 업데이트 쿼리를 수행하고, Cache를 업데이트하게 된다. @Transactional@CachePut(key = "#id", value = "person")public Person update(Long id, String newName) { var person = personRepository.findById(id).orElseThrow(); person.setName(newName); return person;} 만약 이 update를 감싼 트랜잭션이 실패하게 되면 어떻게 될까. @Transactionalpublic ..

방향오늘따라 친구들이랑 통화를 길게 했다.또 유독 삶의 방향에 대한 얘기를 많이 나눴다. 용관이랑은 우리가 당장 해야 하는 일들을,유진이랑은 개발자로서의 성장 방향과 고민을,영상이랑은 서로가 중요하게 생각하는 가치들을 나눴다. 최근에 바쁜 척하느라 나를 돌아보는 시간을 못 가졌던 것 같다.주변에서 중요하다고 하는 일들에, 나한테 중요한 일들을 놓치고 있는 기분이다. 나는 언제 행복한가. 내가 진짜 하고 싶은 건 뭐고, 어떤 삶을 원하는가. 3년 전 작성했던 내가 꿈꾸는 프로그래머로서의 삶과 지금 내가 꿈꾸는 다음 삶의 방향을 비교해 보는 것도 재밌겠다. 여행나는 여행할 때 행복하다.가끔 사진첩을 넘기며 찍었던 사진을 쭉 훑는 게 취미이다.사람은 순간의 기억으로 평생을 산다는 말에 공감한다. - 하노이..

배경 : 회원 가입이 실패되는 것이 옳을까?Picup 프로젝트에서 회원 가입이 요청되면 Member 서버에서 가입 내용을 기록하고, Storage 서버로 유저 타입과 함께 스토리지 생성을 요청한다. 기존에는 쉽게 가입을 실패시켰다. Storage 서버에서 처리에 실패하면 회원가입은 실패되었다. 외부 API 호출과 원자성, 서버 간 정합성이라는 키워드에만 집착해 기술로만 풀이하려고 했던 것 같다, 나라면 회원가입 폼을 열심히 작성했는데, 마지막 최종 제출에서 가입에 실패하면 그 서비스 안 쓸 것 같다. 가입 실패를 최소화하기 위해 외부 API 가 포함된 신규 가입 로직에서 필수적인 이벤트와 그렇지 않은 이벤트 분리를 고민했다. 그리고 각각의 이벤트 처리에서 발생할 수 있는 문제와 해결을 위한 고민을 정리..