Code States/TIL

[0508] 마이크로서비스 - API 디자인과 프로세스 간 통신

ki1111m2 2023. 5. 8. 13:29
  • 프로세스 간의 통신
    • 서비스와 서비스가 서로 통신하기 위해서는 인터페이스가 존재해야 하고, 인터페이스가 요구하는 방식대로 커뮤니케이션 해야 함
    • API(Application Programing Interface): HTTP 위에서 작동하는 메서드와 엔드포인트로 구성된 인터페이스를 이용한 통신
  • 동기/비동기
    • 동기적 방법
      • 요청을 보내는 즉시 수신자로부터 응답이 오길 기대
      • 클라이언트-서버 아키텍처의 REST(HTTP)가 대표적
      • HTTP 프로토콜은 기본적으로 TCP/UDP 연결을 만들고, 이 위에서 요청에 따라 즉시 응답이 오는 형태로 구현되어 있음 → 즉 동기적인 응답을 제공함
    • 비동기적 방법
      • 요청을 일단 보내놓고 수신자가 받을 때까지 보관했다가 처리
      • 수신자가 받기 전에 누군가는 메시지를 보관해놓아야 함 → 메시지 브로커(메시지 큐)
      • 문자 메세지, 구독 서비스, 푸시 알림 등 단방향 알림 → 비동기
  • 일대일 및 일대다 통신
    • HTTP에서 요청/응답으로 이루어진 한 번의 트랜잭션에서 서버는 여러 클라이언트에게 동시에 응답을 전달하지 않음
    • 서버가 여러 클라이언트를 상대할 수는 있지만, 동시에 여러 클라이언트를 상대하는 1:n 커뮤니케이션이 아닌 여러번의 1:1 커뮤니케이션
  • 프로세스 간의 직접/간접 연결
    • 클라이언트/서버 아키텍처에서 메시지 브로커가 두 프로세스 사이에 위치해서 오고 가는 메시지 자체를 관리하는 형태의 연결 방식도 있음
    • 이 경우 비동기적인 처리는 물론이고, 둘 중 하나의 프로세스가 실행 중이 아니더라도 서로 메시지를 주고받을 수도 있음

대표적인 데이터 교환 포맷 JSON


  • Javascript Object Notation
  • 데이터 교환을 위해 만들어진 객체 형태의 포맷
  • 전송 가능한 조건(transferable condition)
    • 수신자(reciever)와 발신자(sender)가 같은 프로그램을 사용함
    • 문자열처럼 범용적으로 읽을 수 있어야 함
  • 객체는 타입 변환을 이용해 String으로 변환할 경우, 객체 내용을 포함하지 않음
    • JavaScript에서 메소드(message.toString)나 형변환(String(message))을 시도하면, object로 리턴함
  • 이를 해결하기 위해 객체를 JSON 형태로 변환하거나, JSON을 객체의 형태로 변환해야 함
    • JSON.stringify : Object type을 JSON으로 변환함(직렬화)
    • JSON.parse : JSON을 Object type으로 변환함(역직렬화)

동기식 요청/응답 통신 REST


  • REST
    • HTTP로 소통하는 프로세스 간 통신 규약
  • REST API
    • 웹에서 사용되는 데이터나 자원(Resource)을 HTTP URI로 표현하고, HTTP 프로토콜을 통해 요청과 응답을 정의하는 방식
  • 장점
    • 포스트맨, curl 등의 도구를 사용해 간편하게 테스트 가능함
    • 요청/응답 통신을 직접 지원함
    • 시스템 아키텍처가 단순함
  • 단점
    • 요청/응답만 지원함
    • 메시지를 주고받기 위해서는 클라이언트와 서버 프로세스가 둘 다 실행중이어야만 함
    • 요청 한 번으로 여러 리소스를 조회하기 어려움
    • 메서드만으로는 한 번의 요청을 통해 이루어지는 다양한 작업들을 대표하기 어려움

메시지 브로커를 이용한 비동기식 통신


  • 메시지 브로커가 필요한 이유
    • 분산 애플리케이션은 프로세스 간의 느슨한 결합(loosely coupled)을 제공하는 것이 가장 큰 장점
    • 강하게 결합된 시스템에서 단점은 서로 연결되어 있는 시스템 중 한 곳에서 장애가 발생했을 때 그 장애가 연결된 다른 시스템들에 영향이 간다는 것
  • 주요 용어
    • 생산자(producer): 메시지를 보내는 사람
    • 소비자(consumer) 메시지를 받는 사람
    • 발행(publish): 메시지를 보내는 것
    • 소비(consume): 메시지를 받는 것
  • 특징
    • 프로그램 간의 직접 연결 없음
      • less dependency, fault tolerant
      • 소비자 프로세스가 죽어있어도 생산자는 메시지를 보낼 수 있음
      • 생산자 프로세스가 죽어있어도 소비자는 메시지를 수신할 수 있음
    • 메시지 브로커에 있는 메시지는 소비자(수신자)가 꺼낼 때까지 안전하게 보관됨
      • durabilit
      • 프로세스가 죽어있어도 메시지는 소비하기 전까지는 사라지지 않음
      • 프로그램 간 통신은 시간과 독립적임
    • 통신이 이벤트에 의해 구동될 수 있음
      • 큐의 상태에 따라 프로그램을 제어할 수 있음
    • 확장에 용이함
      • 메시지 브로커는 여러 큐를 만들거나 수평적으로 확장하여 메시지 부하 증가를 처리할 수 있음
  • 단점
    • 프로세스 간의 직접 연결에 비해 아키텍처가 복잡함
  • 선택의 기준
    • 프로그래밍 언어 지원 여부
    • 메시징 표준 지원 여부
    • 메시지 순서 보장 여부
    • 전달 보장 여부: 어떤 종류의 전달을 보장하는가?
    • 영속성: 브로커가 고장나도 문제가 없도록 메시지가 디스크에 저장되는가?
    • 내구성: 소비자가 메시지 브로커에 다시 접속할 경우, 접속이 중단된 시간에 전달된 메시지를 받을 수 있는가?
    • 확장성
    • 지연 시간