- nodejs ( rest server )
- socket.io
- mysql
- mongodb ( 사용 예정 )
- rabbit mq ( 사용 예정 )
- spring boot ( 사용 예정 - file server )
- docker
- pm2
- nginx
- jenkins
- redis (pub/sub), replica, sentinel(failover 처리)
- router : api request 처리 ( 지금은 채팅관련 api만 있으므로 chat.js만 만들어놈 )
- util : 공통 모듈 처리
- view : 화면 처리
- server.js : 소켓관련 로직 처리
create DATABASE chatDb default character set utf8 collate utf8_general_ci;
- 현재 채팅중인 방 리스트 ( 방이 만들어질때 insert되고 방이 없어질때 delete 된다. )
create table chatRoom (
id int not null auto_increment,
title varchar(50) not null,
join_member_count int not null,
created datetime default current_timestamp,
primary key(id)
);
- 현재 채팅방에 있는 맴버 리스트 ( 맴버가 방에 참여할때 insert되고 방에서 나갈때 delete 된다. )
create table chatMember (
id int not null auto_increment,
nickname varchar(50) not null,
room_id int not null,
socket_id varchar(50),
join_time datetime default current_timestamp,
primary key(id),
foreign key(room_id) references chatRoom(id)
);
- 채팅방에서 채팅을 치면 이력이 남는다. -> 해당 방이 삭제되면 같이 delete 됨.
create table chatMsg (
id int not null auto_increment,
room_id int not null,
user_id int not null,
content varchar(100) not null,
chat_time datetime default current_timestamp,
primary key(id),
foreign key(room_id) references chatRoom(id),
foreign key(user_id) references chatMember(id)
);
- http://server url:port/chat
- 같은 채팅방에 있는 유저들끼리 대화 가능
- 채팅방 생성
- 채팅방 참여
- 같은방에서 채팅
- 채팅방 리스트 조회
- 채팅방에서 채팅중인 유저 조회
- 서버 여러대 확장을 고려해 redis-pub/sub을 통한 서버간 message broadcast 처리
- Mq( rabbitMq, kafka )를 통해 분산처리 ( db 앞단에서 트래픽 관리 )
- 참여자 프로필 이미지 설정 ( 채팅방 참여 전 이미지 받음 )
- 채팅방 이미지 업로드 기능 4 로그 데이터 mongodb로 관리 ( 채팅방 create/delete, 채팅방에 참여자 in/out, 채팅 기록 )
- 현재는 채팅방에서 참가자 조회할때 매번 db select하는데.. -> SessionStroage와 같은 캐시를 써서 매번 디비 안타케 처리
- winston으로 로그 관리
- npm install pm2 -g
- pm2 start start.config.js ( developement으로 실행) production으로 실행하고 싶으면 pm2 start start.config.js --evn production
- https://pm2.keymetrics.io/docs/usage/environment/
- // start.config.js
module.exports = {
apps : [
{
name: "chattingServer",
script: "./server.js",
watch: true,
out_file: "/dev/null",
error_file: "/dev/null",
env: {
"PORT": 3000,
"NODE_ENV": "development"
},
env_production: {
"NODE_ENV": "production"
}
}
]
}
- https://pm2.keymetrics.io/docs/usage/cluster-mode/
- pm2 cluster mode를 사용하면 cluster로 묶인 서버들은 pm2를 통해 load balancing이 된다. 각 서버들은 같은 port를 공유한다.
- // start.config.cluster.json
{
"apps": [
{
"name": "chatting cluster",
"script": "./server.js",
"instances": 2, // cpu core 갯수, 0으로 설정하면 pc의 최대 core 갯수
"exec_mode": "cluster",
"env": {
"NODE_ENV": "production",
"PORT": "3000"
}
}
]
}
- socket.io 만으로 처리가능. ( 해당 roomId에 있는 유저들에게 메시지를 보낸다. socket.io의 to 함수를 사용하면 특정 socket.id 또는 특정 room에 있는 소켓들에게 메시지 전송 가능 )
- socket.io 만으로는 처리 불가. 각 서버는 메모리에 다른 프로세스로 떠있기 때문에 프로세스 사이의 데이터 공유 못함. -> redis pub/sub을 통해 가능하다.
- 대략 flow는 다음과 같다.
- 각 서버들은 redis의 특정 채널을 subscribe를 하고 Client의 요청이 들어오면 요청을 받은 서버는 해당 요청을 redis로 publish를 날려서 다른 서버들이 메시지를 받을 수 있게 한다.