Microservice Design 2일차 - Microservice에서의 database와 Loadbalancer, APIGateway

0

microservice

목록 보기
2/6

Microservice 실전 사례

Microservice for database

microservice마다 database를 두어 시스템을 처리하는 편이 좋지만, 이는 성능의 문제가 있고 데이터베이스 통합에 있어서 문제가 발생한다.

----------------            ----------------
|A microservice|            |B microservice|
----------------            ----------------
        |                           |
        |                           |
    ----------                  ----------
    |Database|                  |Database|
    ----------                  ----------

가령 A microservice가 B microservice의 data를 요구하게 될 때, query를 보내야하고 이는 네트워크 지연이 발생하게 된다. 또한, join을 할 때 정합성 문제가 발생하는 문제가 있을 수 있다.

----------------                 ----------------
|A microservice|<--A data query--|B microservice|
---------------- (성능, 정합성 문제) ----------------
        |                               |
        |                               |
    ----------                      ----------
    |Database|                      |Database|
    ----------                      ----------

따라서, 일시적인 데이터 불일치가 허용되는 경우는, cache와 데이터 베이스 공유를 하는 것이 괜찮은 방법일 수 있다. 즉, 최종적인 데이터베이스 일관성만 지켜지면 되는 경우를 말한다.

      Frontend
        |
        |
    3. SEND review to Frontend
        |
        |
----------------                ----------------
|A microservice|                |B microservice|
----------------                ----------------
        |                               |
    1. READ review              2. ADD review  
        |                               |
    ----------------------------------------
    |               Database               |
    ----------------------------------------

단, 이렇게 같은 데이터 베이스를 쓰거나, 다른 microservice의 데이터베이스를 복제, 캐싱하는 시스템의 경우는 다음의 법칙이 지켜져야한다.

  1. 오직 데이터베이스에 쓰고, 수정, 삭제하는 것은 특정 microservice 하나만 가능하며, 다른 이들은 read만 가능하다.
  2. eventual consistency(최종 단계 일관성)이 보장되는 경우

이 경우는 리뷰시스템의 경우에 해당하는데, 제품에 대한 리뷰를 확인할 때 최근에 쓰여지거나, 변경된 리뷰가 반영되지 않아도 공통된 데이터베이스를 통해서 리뷰를 가져와 렌더링해도 문제가 되지 않는다. 어차피 이는 데이터 일관성이 지켜지기 때문이다.

그러나, 최종 단계의 일관성이 '엄격히' 지켜져야 하는 경우에 database에 대해서 공유하는 것이 금지된다. 더 정확히는 데이터를 중복해서 저장이 불가능하다.

가령, 은행의 돈과 같은 경우는 다른데, 공통된 데이터 베이스를 쓸 경우 transaction 순서에 따라 결과가 달라 질 수 있다. 즉, 데이터베이스의 일관성은 지켜지지만 눈에 보이는 결과는 달라질 수 있다는 것이다.

가령, 입금을 중에, 자동 이체 정산이 되는 경우 결과가 내가 생각한 것보다 적게 나올 수 있다. 반면에, 어느 날은 입금 중에 자동 이체 정산이 되는 경우, 내가 입금한 결과가 더 먼저 반영되어 자동 이체한 결과가 사용자에게 안보일 수 있다. 이는 비일관적인 결과로인해 user에게 혼란을 야기시킬 수 있다.

따라서, 한 번에 하나의 transaction만 처리하도록 microservice 나에 개별 database를 주도록 해야한다. 이렇게 디자인하면 microservice 내에서만 데이터 일관성을 지키면 되므로, 엄격하게 데이터가 관리되어 사용자의 혼동을 주지 않을 수 있다.

                ----------------  --------------
                |C microservice|--|App Database|
                ----------------  --------------
                 /
                /
             입급 query
             /
           /
          v
----------------                 ----------------
|A microservice|<----출금 query---|B microservice|
----------------                 ----------------
        |                               |
        |                               |
  ----------------            -----------------------
  |Money Database|            |Subscription Database|
  ----------------            -----------------------

Loadbalancer와 APIGateway

사용자들은 mobile, web 등의 여러 장치를 통해 우리의 microservice에 접근한다고 하자.

이때, 사용자라고 한다면 일반적인 고객들도 있지만, b2b로서 고객사도 해당이 될 수 있다.

----------          --------------
|Company1|          |user service|
----------          --------------

                    --------------
                    |Noti service|
                    --------------
----------      
|Company2|          --------------
----------          |data service|
                    --------------

                    ----------------------
                    |subscription service|
                    ----------------------
----------          
|Company3|          -------------
----------          |pay service|
                    -------------

문제는 고객사들의 요구사항들은 다양하며, 여러 가지 format이 있을 수 있다.

  1. graphQL
  2. REST API
  3. gRPC
  4. Socket
  5. SSH

각 고객사들이 이러한 방법으로 데이터를 요청할 수 있고, 요청한 데이터의 format도 다를 수 있다.

  1. xml
  2. json
  3. text
  4. file
  5. csv

이 모든 것들을 각 Microservice가 지원해야하는 것이다. 가령, user정보를 가져오기 위해서 다음의 요구 사항이 있을 수 있다.

  1. company1은 REST + JSON 요구
  2. company2는 SSH + file 요구
  3. company3는 socket + xml 요구

이 모든 요구사항을 지키기 위해서 user service는 다음과 같이 3가지 모든 기능을 제공해야하는 것이다.

----------              --------------
|Company1|--REST(json)--|            |
----------              |            |
        ----SSH(file)---|user service|
        |               |            |
        |   Socket(XML)-|            |
        |   |           --------------
        |   |
        |   |       --------------
        |   |       |Noti service|
        |   |       --------------
----------  |   
|Company2|  |       --------------
----------  |       |data service|
            |       --------------
            |
            |       ----------------------
            |       |subscription service|
            |       ----------------------
----------  |       
|Company3|---       -------------
----------          |pay service|
                    -------------

문제는 이것이 다른 microservice에도 똑같이 적용될 수 밖에 없다는 것이다.

또한, 이러한 연결 관계는 client와 microservice code가 강하게 결합되는 문제를 야기한다. 즉, REST로 /api/user라는 endpoint를 client가 사용해야하면, 해당 endpoint를 제공하는 microservice는 API를 함부로 바꾸지 못하게된다. 이는 client와 microservice 간의 강한 결합력 때문에 발생한 문제이다.

부수적인 기능에 있어서도 문제가 생기는데, 통신에 있어서 데이터를 안전하게 보장하는 TLS라던지 traffic을 제어하는 기능, 로그인 세션 유지 기능들과 같은 부수적인 기능들이 각 microservice에 tight하게 연결될 수 밖에 없다.

마지막으로 전체적인 디버깅이 어려워진다는 문제가 생긴다. 어떤 요청이 들어오고 어떻게 응답이 왔는 지 중앙화된 방식이 아니라, 분산된 각 microservice에서 각자 모니터링, 로깅을 해야하는 문제가 발생하는 것이다.

문제들을 정리하면 다음과 같다.
1. client의 다양한 통신, 데이터 요구사항
2. client와 microservice간의 강한 결합 문제
3. 안전하고 견고한 서비스 제공을 위한 기능 제공의 문제(TLS, auth session etc)
4. 로깅, 모니터링의 어려움

이러한 문제들을 해결해주는 것이 바로 api-gateway이다.

api-gateway는 다양한 의미를 가지는데, 일반적으로 특정 통신 API(REST, gRPC, Socket, SSH 등)을 지원하지 않는 component의 proxy가 되어 일관된 인터페이스를 통해서 지원하지 않는 통신 API를 지원할 수 있도록 기능을 제공해주는 장치이다.

즉 통신의 flow를 그리면 다음과 같다.

----------                   --------------
|Company1|--               |-|user service|
---------- |               | --------------
           |               |
           |               | --------------
           |               |-|Noti service|
           |               | --------------
           |  XML,JSON,FILE|
           |  ------------ |
           |--|APIGateway|-|
           |  ------------ |
---------- |  REST,TCP,SSH |
|Company2|-|               | --------------
---------- |               |-|data service|
           |               | --------------
           |               |
           |               | ----------------------
           |               |-|subscription service|
           |               | ----------------------
---------- |               |
|Company3|-|               | -------------
----------                 |-|pay service|
                             -------------

다음과 같이 모든 client의 요청을 api-gateway가 proxy하고, 이 요청에 대해서 변환 과정을 거쳐서 microservice들에게 전달하는 것이다.

가령, user service는 유저정보를 REST로 /api/user JSON응답을 보낸다고 하자. client는 구버전인 /api/userinfo endpoint를 통해서 XML로 유저 정보를 얻고 싶어한다고 한다.

client는 REST /api/userinfo로 APIGateway에 요청을 보내고, APIGateway는 해당 요청에 대해서 REST/api/user 요청을 user service에 보낸다.

user service의 JSON 요청을 받아서 XML로 변환한 다음 응답을 client에게 전달해주는 것이다.

이처럼 api-gateway는 endpoint에 대한 인터페이스 역할을 하여 client에게 일관된 인터페이스를 제공하고 client와 microservice 간의 결합도를 낮추는 역할을 한다. 또한, microservice에서 제공하지 않는 통신 API와 포맷을 제공하여 microservice의 코드를 고치지 않고도 기능을 확장해주도록 한다.

또한, TLS나 traffic control 같은 기능도 microservice 대신에 앞 단에서 제공이 가능하며, 모든 요청과 응답이 api-gateway를 통해 이루어짐으로 로깅과 모니터링을 수월하게 해준다.

단, api-gateway와 loadbalancer를 헷갈려하는 경우가 있는데, 두 component의 공통점은 단 하나로 단일 지점으로 요청이 라우팅된다 일 뿐이다.

두 구성 요소의 가장 큰 차이는 목적에 있다.

loadbalancer는 microservice내에 동일한 기능을 하는 각 instance들에 대해서 traffic을 분산하도록 한다.

---------                           -----------
|client1|-------|                   |instance1|
---------       |  --------------   |instance2|
                |--|LoadBalancer|---|instance3|
                |  --------------   |instance4|
                |                   -----------
---------       |                   Microservice1
|client2|-------|
---------       |
                |
---------       |
|client3|-------|
---------

instance들은 microservice1에 대한 동일한 코드를 가진 process들이며 동일한 기능을 한다. Loadbalancer는 traffic을 각 설정에 맞게 이들에게 분산시켜주는 것 이외에 특별한 기능은 없다.

반면에 api-gwateway는 우리 시스템의 공개 인터페이스 역할을 하는 것이다. 그 역할은 각 서비스로 기준에 맞게 제공해주는 것이다.

  • MS는 microservice이고, LB는 loadbalancer이다.
---------                                -----
|client1|-------|                   |--LB|MS1|
---------       |  --------------   |    -----
                |--|LoadBalancer|---|
                |  --------------   |    -----
                |                   |--LB|MS2|  
                |                        -----
---------       |                   
|client2|-------|
---------       |
                |
---------       |
|client3|-------|
---------

이를 기반으로 둘을 정리하면 다음과 같다.

  • loadbalancer 특징
  1. performance 향상을 위한 traffic 분배
  2. server(instance) health check와 같은 기능
  • apigateway
  1. 일관된 API 인터페이스 제공 및 관리
  2. 로깅, 모니터링
  3. 프로토콜 및 데이터 형식 변환

0개의 댓글

Powered by GraphCDN, the GraphQL CDN