1 OAS(OpenAPI Spec) 설계
1.1 항공편 마이크로서비스 OAS
https://github.com/implementing-microservices/ms-flights/blob/master/docs/api.yml
openapi: 3.0.0
info:
title: Flights Management Microservice API
description: |
API Spec for Fight Management System
version: 1.0.1
servers:
- url: http://api.example.com/v1
description: Production Server
paths:
/flights:
get:
summary: Look Up Flight Details with Flight No and Departure Date
description: |
Lookup flight details, such as: the unique flight_id used by the
rest of the Flights management endpoints, flight departure and
arrival airports.
Example request:
```
GET http://api.example.com/v1/flights?flight_no=AA2532&departure_date_time=2020-05-17T13:20
```
parameters:
- name: flight_no
in: query
required: true
description: Flight Number.
schema:
type : string
example: AA2532
- name: departure_date_time
in: query
required: true
description: Date and time (in ISO8601)
schema:
type : string
example: 2020-05-17T13:20
responses:
'200': # success response
description: Successful Response
content:
application/json:
schema:
type: array
items:
type: object
properties:
flight_id:
type: string
example: "edcc03a4-7f4e-40d1-898d-bf84a266f1b9"
origin_code:
type: string
example: "LAX"
destination_code:
type: string
example: "DCA"
example:
flight_id: "edcc03a4-7f4e-40d1-898d-bf84a266f1b9"
origin_code: "LAX"
destination_code: "DCA"
/flights/{flight_no}/seat_map:
get:
summary: Get a seat map for a flight
description: |
Example request:
```
GET http://api.example.com/v1/flights/AA2532/datetime/2020-05-17T13:20/seats/12C
```
parameters:
- name: flight_no
in: path
required: true
description: Unique Flight Identifier
schema:
type : string
example: "edcc03a4-7f4e-40d1-898d-bf84a266f1b9"
responses:
'200': # success response
description: Successful Response
content:
application/json:
schema:
type: object
properties:
Cabin:
type: array
items:
type: object
properties:
firstRow:
type: number
example: 8
lastRow:
type: number
example: 23
Wing:
type: object
properties:
firstRow:
type: number
example: 14
lastRow:
type: number
example: 22
CabinClass:
type: object
properties:
CabinType:
type: string
example: Economy
Column:
type: array
items:
type: object
properties:
Column:
type: string
example: A
Characteristics:
type: array
example:
- Window
items:
type: string
Row:
type: array
items:
type: object
properties:
RowNumber:
type: number
example: 8
Seat:
type: array
items:
type: object
properties:
premiumInd:
type: boolean
example: false
exitRowInd:
type: boolean
example: false
restrictedReclineInd:
type: boolean
example: false
noInfantInd:
type: boolean
example: false
Number:
type: string
example: A
Facilities:
type: array
items:
type: object
properties:
Detail:
type: object
properties:
content:
type: string
example: LegSpaceSeat
1.2 예약 마이크로서비스 OAS
https://github.com/implementing-microservices/ms-reservations/blob/master/docs/api.yml
openapi: 3.0.0
info:
title: Seat Reservation System API
description: |
API Spec for Fight Management System
version: 1.0.1
servers:
- url: http://api.example.com/v1
description: Production Server
paths:
/reservations:
get:
summary: Get Reservations for a flight
description: |
Get all reservations for a specific flight
parameters:
- name: flight_id
in: query
required: true
schema:
type: string
responses:
'200': # success response
description: Successful Response
content:
application/json:
schema:
type: array
items:
type: object
properties:
seat_no:
type: string
example: "18F"
example:
- { seat_no: "18F" }
- { seat_no: "18D" }
- { seat_no: "15A" }
- { seat_no: "15B" }
- { seat_no: "7A" }
put:
summary: Reserve or cancel a seat
description: |
Reserves a seat or removes a seat reservation
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
flight_id:
description: Flight's Unique Identifier.
type : string
example: "edcc03a4-7f4e-40d1-898d-bf84a266f1b9"
customer_id:
description: Registered Customer's Unique Identifier
type : string
example: "2e850e2f-f81d-44fd-bef8-3bb5e90791ff"
seat_num:
description: seat number
type: string
example:
flight_id: "edcc03a4-7f4e-40d1-898d-bf84a266f1b9"
customer_id: "2e850e2f-f81d-44fd-bef8-3bb5e90791ff"
seat_num: "8D"
responses:
'200':
description: |
Success.
content:
application/json:
schema:
type: object
properties:
status:
type: string
enum: ["success", "error"]
example:
"success"
'403':
description: seat(s) unavailable. Booking failed.
content:
application/json:
schema:
type: object
properties:
error:
type: string
description:
type: string
example:
error: "Could not complete reservation"
description: "Seat already reserved. Cannot double-book"
1.3 스웨거(swagger) 에디터로 렌더링 가능
항공 마이크로서비스 OAS와 예약 마이크로서비스 OAS를 스웨그 에디터에 입력하면 API 문서로 렌더링되어 출력되는 것을 확인할 수 있음
2 마이크로서비스에 특성에 맞는 백엔드 데이터 시스템 선택
마이크로서비스 간 독립적인 데이터의 필요성을 강조하기 위해 완전히 다른 백엔드 데이터 시스템을 사용 (항공편 서비스에는 MySQL을, 예약 서비스에는 레디스를 사용)
2.1 GNU make 유틸리티 설치 및 PATH 환경 변수 등록
2.2 예약 서비스의 데이터 모델을 위한 레디스(redis)
예약 시스템에서는 항공편 좌석의 예약 현황을 조회하고 아직 예약되지 않은 좌석이라면 예약할 수 있는 기능을 제공
⇒ 레디스는 이에 적합한 해시 데이터 구조를 제공
⇒ HSETNX 명령으로 신뢰할 수 있는 간단한 방법으로 중복 예약을 방지할 수 있음
소스코드 다운로드
c:\msur> git clone https://github.com/implementing-microservices/ms-reservations.git
c:\msur> cd ms-reservations
docker-compose.yaml 파일 수정
… (생략) …
ms-reservations-redis:
container_name: ms-reservations-redis
image: redis:6-alpine
restart: always
command: redis-server /usr/local/etc/redis/redis.conf --requirepass 4n_ins3cure_P4ss
### you only need to host-map this port if you have an app (DB GUI Editor?)
### on host that needs access to the Redis DB. Otherwise, keep it commented.
#ports:
# - "6379:6379"
expose:
- 6379
volumes:
- ms_reservations_redis_data:/data
# - $PWD/redis.conf:/usr/local/etc/redis/redis.conf
- ./redis.conf:/usr/local/etc/redis/redis.conf
environment:
- REDIS_REPLICATION_MODE=master
volumes:
ms_reservations_redis_data:
ms-reservations-redis 컨테이너 실행
C:\msur\ms-reservations> make start ⇐ share path … 승인해줘야 함
docker-compose -p msupandrunning up -d
Creating network "msupandrunning_default" with the default driver
Creating ms-reservations-redis ... done
Creating ms-reservations ... done
ms-reservations-redis 컨테이너에서 redis-cli 실행
C:\msur\ms-reservations> make redis
docker-compose -p msupandrunning exec ms-reservations-redis redis-cli -a 4n_ins3cure_P4ss
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379>
flight_id가 40d1-898d-bf84a266f1b9인 항공편에 여러 좌석을 예약하는 예
HSETNX key field value 명령 ⇒ 좌석의 중복 예약을 방지
[참고] https://redis.io/commands/HSETNX
field가 존재하지 않는 경우에만 key에 저장된 해시의 field를 value로 설정
key가 존재하지 않으면 해시를 포함하는 새 key를 생성 (field가 이미 있는 경우 이 작업은 효과가 없음)
127.0.0.1:6379> HSETNX flight:40d1-898d-bf84a266f1b9 12B b4cdf96e-a24a-a09a-87fb1c47567c
(integer) 1 ⇐ field가 해시의 새 field이고, value가 설정된 경우
127.0.0.1:6379> HSETNX flight:40d1-898d-bf84a266f1b9 12C e0392920-a24a-b6e3-8b4ebcbe7d5c
(integer) 1
127.0.0.1:6379> HSETNX flight:40d1-898d-bf84a266f1b9 11A f4892d9e-a24a-8ed1-2397df0ddba7
(integer) 1
127.0.0.1:6379> HSETNX flight:40d1-898d-bf84a266f1b9 3A 017d40c6-a24b-b6d7-4bb15d04a10b
(integer) 1
127.0.0.1:6379> HSETNX flight:40d1-898d-bf84a266f1b9 3B 0c27f7c8-a24b-9556-fb37c840de89
(integer) 1
127.0.0.1:6379> HSETNX flight:40d1-898d-bf84a266f1b9 22A 0c27f7c8-a24b-9556-fb37c840de89
(integer) 1
127.0.0.1:6379> HSETNX flight:40d1-898d-bf84a266f1b9 22B 24ae6f02-a24b-a149-53d7a72f10c0
(integer) 1
이미 예약된 좌석의 중복 예약을 시도
127.0.0.1:6379> HSETNX flight:40d1-898d-bf84a266f1b9 12C 083a6fc2-a24d-889b-6fc480858a38
(integer) 0 ⇐ field가 이미 해시에 있고 작업이 수행되지 않은 경우
특정 항공편에서 예약된 좌석 전체를 조회
127.0.0.1:6379> HKEYS flight:40d1-898d-bf84a266f1b9
1) "12B"
2) "12C"
3) "11A"
4) "3A"
5) "3B"
6) "22A"
7) "22B"
특정 항공편에서 예약된 좌석과 예약자(예약번호)를 조회
127.0.0.1:6379> HGETALL flight:40d1-898d-bf84a266f1b9
1) "12B"
2) "b4cdf96e-a24a-a09a-87fb1c47567c"
3) "12C"
4) "e0392920-a24a-b6e3-8b4ebcbe7d5c"
5) "11A"
6) "f4892d9e-a24a-8ed1-2397df0ddba7"
7) "3A"
8) "017d40c6-a24b-b6d7-4bb15d04a10b"
9) "3B"
10) "0c27f7c8-a24b-9556-fb37c840de89"
11) "22A"
12) "0c27f7c8-a24b-9556-fb37c840de89"
13) "22B"
14) "24ae6f02-a24b-a149-53d7a72f10c0"
컨테이너 종료
127.0.0.1:6379> exit
C:\msur\ms-reservations> make stop
docker-compose -p msupandrunning down
Stopping ms-reservations ... done
Stopping ms-reservations-redis ... done
Removing ms-reservations ... done
Removing ms-reservations-redis ... done
Removing network msupandrunning_default
디렉터리 삭제 ⇒ (여기에서는 레디스 동작을 확인하기 위해 임시로 사용) 뒤에서 예약 마이크로서비스 생성 시 다시 만들게 됨
c:\msur> del /s /f /q ms-reservations
c:\msur> rmdir /s /q ms-reservations
2.3 항공편 마이크로서비스의 데이터 모델을 위한 MySQL
항공편 마이크로서비스에서는 OAS에서 정의한 것과 같이 복잡한 JSON 객체를 이용해서 좌석 배치도를 표현 → JSON 객체를 다루기 위해서는 레디스 보다는 MySQL이 더 적합 (MySQL 5.7.8 부터 JSON 데이터 유형에 대한 강력한 기본 지원을 제공)
seat_maps, flights 테이블을 생성하고 seat_maps 테이블에 JSON 형식의 데이터를 추가하고 조회하는 예
CREATE TABLE `seat_maps` (
`flight_no` varchar(10) NOT NULL,
`seat_map` json NULL,
`origin_code` varchar(10) NULL,
`destination_code` varchar(10) NULL,
PRIMARY KEY(`flight_no`)
);
CREATE TABLE `flights` (
`flight_id` varchar(36) NOT NULL,
`flight_no` varchar(10) NULL,
`flight_date` datetime(0) NULL,
PRIMARY KEY (`flight_id`),
INDEX `idx_flight_date`(`flight_no`, `flight_date`),
FOREIGN KEY(flight_no)
REFERENCES seat_maps(flight_no)
);
INSERT INTO `seat_maps`(`flight_no`, `seat_map`, `origin_code`, `destination_code`)
VALUES ('AA2532', '{"Cabin":[{"Row":[{"Seat":[{"Number":"A","Facilities":[{"Detail":{"content":"LegSpaceSeat"}}], "exitRowInd":false,"premiumInd":false,"noInfantInd":false,"restrictedReclineInd":false}],"RowNumber":8}],"Wing":{"lastRow":22,"firstRow":14},"Column":[{"Column":"A","Characteristics":["Window"]}],"lastRow":23,"firstRow":8,"CabinClass":{"CabinType":"Economy"}}]}', 'LAX', 'DCA');
select seat_map->>"$.Cabin[0].firstRow" from seat_maps;
댓글