학교 팀플 프로젝트에서 IoT 프로젝트를 해야했다
또한 조건 중에 MQTT같은 IoT 도메인에서 자주 사용하는 프로토콜을 사용하라는 조건이 있어 amqp 프로토콜을 사용하는 RabbitMQ를 사용해보기로 하였다.
하지만 자료가 적고 재대로된 자료를 찾기 어려워서 글로 남겨보려 한다.
우선 RabbitMQ가 무엇인지 부터 알아보았다.
Publisher와 Subscriber로 이루어진 프로토콜 위에서 동작하는 Message Queue이며 아래와같은 시퀀스로 동작하게된다.
1. Publisher가 Topic에 Message를 publish한다.
2. Message Queue는 해당 Message를 Topic별 queue에 집어넣는다.
3. Subscriber는 구독하고 있는 Topic의 queue에 Message가 올라오면 받아온다.
사진으로 보면 다음과 같다

원래 Rasberry Pi위에 올려두려 했지만 프로젝트에 가벼운 딥러닝 모델이 필요했으므로 시스템의 부하를 막기 위해 AWS EC2 상에 올려두기로 하였다.
docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 --restart=unless-stopped rabbitmq:management
모니터링 페이지의 기본 Username과 Password는 둘 다 guest로 되어있다.
들어가서 Queues and Streams 메뉴로 들어가서 아래 사진과 같은 메뉴를 찾아 원하는 이름으로 queue를 생성해주자

큐를 생성해서 들어가보면 아래와 같은 화면을 볼 수 있을 것이다.

이렇게까지 준비하면 준비는 끝이다.
npm install ---save @golevelup/nestjs-rabbitmq
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq';
import { MessagingService } from './messaging.service';
@Module({
imports: [
RabbitMQModule.forRoot(RabbitMQModule, {
exchanges: [
{
name: 'image',
type: 'topic'
},
],
uri: 'amqp://guest:guest@{your_domian or ip}:5672',
channels: {
'channel-1': {
prefetchCount: 15,
default: true,
}
},
}),
],
controllers: [AppController],
providers: [AppService, MessagingService],
})
export class AppModule {}
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
import { ImageDto } from './image.dto';
@Controller()
export class AppController {
constructor(
private readonly appService: AppService,
private readonly amqpConnection: AmqpConnection
){}
private readonly filePath:string = './image.png';
// 트리거 localhost:3000 GET
@Get()
async rmqTest() {
// node.js의 File System
const fs = require('fs');
// 이미지 파일을 받아와서 Base64로 인코딩한다.
let imageFile = fs.readFileSync(this.filePath);
let encode = Buffer.from(imageFile).toString('base64');
// 인코딩한 이미지 String을 커넥션을 통해 publish한다.
this.amqpConnection.publish<ImageDto>('image', 'image-key', {image: encode});
//전송한 이미지를 지운다
fs.rm(this.filePath, (err) => {
console.log(err);
})
// 응답값이 없으면 타임아웃까지 파이썬 스크립트가 대기하므로 응답값을 리턴
return 'success';
}
}
// 이미지 String을 담을 객체
export interface ImageDto {
image: string;
}
