์ ์ฒด์ ์ธ ๊ธฐ์ ๋ณต์ก๋ ์ฆ๊ฐ => ์์ ์๋น์ค๋ณด๋ค ํฐ ์๋น์ค์์ ๋ง์ด ์ฌ์ฉ!
[์์ ํ์ดํ๋ผ์ธ]
[๊ณตํต ์ค์ ]
version: "3.3"
services:
api-gateway:
build:
context: ./api-gateway
dockerfile: Dockerfile
volumes:
- ./api-gateway/src:/api-gateway/src
ports:
- 3000:3000
auth-service:
build:
context: ./services/auth
dockerfile: Dockerfile
volumes:
- ./services/auth/src:/auth-service/src
ports:
- 3001:3001
resource-service:
build:
context: ./services/resource
dockerfile: Dockerfile
volumes:
- ./services/resource/src:/resource-service/src
ports:
- 3002:3002
//app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ClientsModule, Transport } from '@nestjs/microservices';
@Module({
imports: [
ClientsModule.register([
{
name: 'AUTH_SERVICE', // ip์ฃผ์
transport: Transport.TCP, // TCP๊ฐ ๊ฐ์ฅ ๊ธฐ๋ณธ ์ฐ๊ฒฐ
options: { host: 'auth-service', port: 3001 }, // ip์ฃผ์
},
{
name: 'RESOURCE_SERVICE', // ip์ฃผ์
transport: Transport.TCP,
options: { host: 'resource-service', port: 3002 },
},
]),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
// app.controller.ts
import { Controller, Get, Inject } from '@nestjs/common';
import { AppService } from './app.service';
import { ClientProxy } from '@nestjs/microservices';
@Controller()
export class AppController {
constructor(
private readonly appService: AppService,
@Inject('AUTH_SERVICE')
private readonly clientAuthService: ClientProxy,
@Inject('RESOURCE_SERVICE')
private readonly clientResourceService: ClientProxy,
) {}
@Get('/auth/login')
login() {
return this.clientAuthService.send({ cmd: 'aaa' }, { name: '์ฒ ์' });
}
@Get('/boards')
fetchboards() {
return this.clientResourceService.send({ cmd: 'bbb' }, { age: 13 });
}
}
yarn add @nestjs/microservices
์ค์นcreateMicroservice
์ฌ์ฉ@MessagePattern
์ฌ์ฉ// main.ts
import { Transport, MicroserviceOptions } from '@nestjs/microservices';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AppModule,
{
transport: Transport.TCP, /
options: { host: 'auth-service', port: 3001 },
},
);
await app.listen();
}
bootstrap();
//app.controller.ts
import { Controller } from '@nestjs/common';
import { AppService } from './app.service';
import { MessagePattern } from '@nestjs/microservices';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@MessagePattern({ cmd: 'login' })
login(): string {
return 'login์ ์์ฒญํ์
จ์ต๋๋ค!';
}
}
๋ชจ๋ ํ์ผ์ yarn add @nestjs/graphql @nestjs/apollo graphql apollo-server-express
์ค์น
๊ฐ๊ฐ์ subgraph๋ฅผ ํ๋๋ก ์ฐ๊ฒฐํด์ฃผ๋ ์ญํ
yarn add @apollo/gateway
์ค์น
app.module.ts์ subgraph ์ ๋ณด ์ ๋ ฅ
//app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloGatewayDriver, ApolloGatewayDriverConfig } from '@nestjs/apollo';
import { IntrospectAndCompose } from '@apollo/gateway';
@Module({
imports: [
driver: ApolloGatewayDriver,
gateway: {
//์
๊ตฌ
supergraphSdl: new IntrospectAndCompose({
// ์ฐ๊ฒฐ ์ค์
subgraphs: [
// subgraph ์ ๋ณด ์
๋ ฅ
{ name: 'auth', url: 'http://auth-service:3001/graphql' },
{ name: 'resource', url: 'http://resource-service:3002/graphql' },
],
}),
},
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
๐localhost:3000์ผ๋ก ์ ์ํ๋ฉด app.module.tsํ์ผ์ ์ฃผ์๋ฅผ ํตํด ๊ฐ๊ฐ์ port๋ก ์ฐ๊ฒฐ๋จ
yarn add @apollo/federation
์ค์นyarn add @apollo/subgraph
์ค์น//main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3001);
}
bootstrap();
// app.resolver.ts
import { Resolver, Mutation } from '@nestjs/graphql';
import { AppService } from './app.service';
@Resolver()
export class AppResolver {
constructor(private readonly appService: AppService) {}
@Mutation(() => String)
login() {
return '๋ก๊ทธ์ธ ์ฑ๊ณต!';
}
}
// app.module.ts
import { Module } from '@nestjs/common';
import { AppResolver } from './app.resolver';
import { AppService } from './app.service';
import { GraphQLModule } from '@nestjs/graphql';
import {
ApolloFederationDriver,
ApolloFederationDriverConfig,
} from '@nestjs/apollo';
@Module({
imports: [
GraphQLModule.forRoot<ApolloFederationDriverConfig>({
driver: ApolloFederationDriver,
autoSchemaFile: 'scr/common/grapql/schema.gql',
}),
],
providers: [AppService, AppResolver],
})
export class AppModule {}
Nginx Reverse Proxy
1) ์๋ฐฉํฅ Proxy(Forward Proxy)
2) ์ญ๋ฐฉํฅ Proxy (Reverse Proxy)
version: "3.3"
services:
api-gateway:
image: nginx:latest
volumes:
- ./api-gateway/default.conf:/etc/nginx/conf.d/default.conf
ports:
- 80:80
auth-service:
build:
context: ./services/auth
dockerfile: Dockerfile
volumes:
- ./services/auth/src:/auth-service/src
ports:
- 3001:3001
stock-service:
build:
context: ./services/stock
dockerfile: Dockerfile
volumes:
- ./services/stock/src:/stock-service/src
ports:
- 3002:3002
server{
listen 80; # 80์ด ๊ธฐ๋ณธ ํฌํธ
# /graphql๋ก ์์ํ๋ ์ฃผ์๊ฐ ๋ค์ด์ค๋ฉด ๋๊ฒจ์ค ๋ด์ฉ(url)
location /graphql{
proxy_pass http://auth-service:3001;
}
# /stocks๋ก ์์ํ๋ ์ฃผ์๊ฐ ๋ค์ด์ค๋ฉด ๋๊ฒจ์ค ๋ด์ฉ(url)
location /stocks {
proxy_pass http://stock-service:3002;
}
}