1. 健康檢查
npm install @nestjs/terminus
// health/health.controller.ts
import { Controller, Get } from '@nestjs/common';
import {
HealthCheck,
HealthCheckService,
TypeOrmHealthIndicator,
MemoryHealthIndicator,
DiskHealthIndicator,
HttpHealthIndicator,
} from '@nestjs/terminus';
@Controller('health')
export class HealthController {
constructor(
private health: HealthCheckService,
private db: TypeOrmHealthIndicator,
private memory: MemoryHealthIndicator,
private disk: DiskHealthIndicator,
private http: HttpHealthIndicator,
) {}
@Get()
@HealthCheck()
check() {
return this.health.check([
// Database
() => this.db.pingCheck('database'),
// Memory: heap < 300MB
() => this.memory.checkHeap('memory_heap', 300 * 1024 * 1024),
// Disk: < 90% used
() => this.disk.checkStorage('disk', {
thresholdPercent: 0.9,
path: '/',
}),
]);
}
@Get('ready')
@HealthCheck()
readiness() {
return this.health.check([
() => this.db.pingCheck('database'),
]);
}
@Get('live')
@HealthCheck()
liveness() {
return this.health.check([
() => this.memory.checkHeap('memory', 500 * 1024 * 1024),
]);
}
}
2. 結構化日誌記錄
npm install winston nest-winston
// main.ts
import { WinstonModule, utilities } from 'nest-winston';
import * as winston from 'winston';
const app = await NestFactory.create(AppModule, {
logger: WinstonModule.createLogger({
transports: [
// Console (development)
new winston.transports.Console({
format: winston.format.combine(
winston.format.timestamp(),
utilities.format.nestLike('NestApp'),
),
}),
// File (production)
new winston.transports.File({
filename: 'logs/error.log',
level: 'error',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json(),
),
maxsize: 10 * 1024 * 1024, // 10MB
maxFiles: 5,
}),
new winston.transports.File({
filename: 'logs/combined.log',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json(),
),
}),
],
}),
});
3. 普羅米修斯指標
npm install prom-client @willsoto/nestjs-prometheus
// app.module.ts
import { PrometheusModule } from '@willsoto/nestjs-prometheus';
@Module({
imports: [
PrometheusModule.register({
path: '/metrics',
defaultMetrics: { enabled: true },
}),
],
})
export class AppModule {}
// Custom metrics
import { Counter, Histogram } from 'prom-client';
import { InjectMetric, makeCounterProvider, makeHistogramProvider } from '@willsoto/nestjs-prometheus';
// Đăng ký trong module
@Module({
providers: [
makeCounterProvider({
name: 'http_requests_total',
help: 'Total HTTP requests',
labelNames: ['method', 'path', 'status'],
}),
makeHistogramProvider({
name: 'http_request_duration_seconds',
help: 'HTTP request duration',
labelNames: ['method', 'path'],
buckets: [0.01, 0.05, 0.1, 0.5, 1, 5],
}),
],
})
export class MetricsModule {}
// Interceptor thu thập metrics
@Injectable()
export class MetricsInterceptor implements NestInterceptor {
constructor(
@InjectMetric('http_requests_total') private counter: Counter,
@InjectMetric('http_request_duration_seconds') private histogram: Histogram,
) {}
intercept(context: ExecutionContext, next: CallHandler) {
const req = context.switchToHttp().getRequest();
const { method, route } = req;
const path = route?.path || req.url;
const timer = this.histogram.startTimer({ method, path });
return next.handle().pipe(
tap(() => {
const status = context.switchToHttp().getResponse().statusCode;
this.counter.inc({ method, path, status });
timer();
}),
);
}
}
4.Nginx反向代理
# nginx/default.conf
upstream nestapp {
server app:3000;
}
server {
listen 80;
server_name api.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
# Gzip
gzip on;
gzip_types application/json text/plain;
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
location / {
limit_req zone=api burst=20 nodelay;
proxy_pass http://nestapp;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
# Health check (không rate limit)
location /health {
proxy_pass http://nestapp;
access_log off;
}
# Metrics (restrict access)
location /metrics {
allow 10.0.0.0/8;
deny all;
proxy_pass http://nestapp;
}
}
5. PM2集群模式
// ecosystem.config.js
module.exports = {
apps: [{
name: 'nestapp',
script: 'dist/main.js',
instances: 'max', // Số CPU cores
exec_mode: 'cluster',
max_memory_restart: '500M',
env_production: {
NODE_ENV: 'production',
PORT: 3000,
},
// Graceful shutdown
kill_timeout: 5000,
listen_timeout: 10000,
// Logging
error_file: './logs/pm2-error.log',
out_file: './logs/pm2-out.log',
merge_logs: true,
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
}],
};
// main.ts — Graceful shutdown
app.enableShutdownHooks();
// Trong service
@Injectable()
export class AppService implements OnModuleDestroy {
async onModuleDestroy() {
// Đóng connections
await this.dataSource.destroy();
await this.redisClient.quit();
this.logger.log('Graceful shutdown completed');
}
}
6. 監控堆疊(Docker Compose)
# docker-compose.monitoring.yml
services:
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana:latest
ports:
- "3001:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana
volumes:
grafana-data:
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'nestapp'
static_configs:
- targets: ['app:3000']
metrics_path: /metrics
7. 生產檢查表
| 類別 | 詳情 |
|---|---|
| 安全性 | 頭盔、CORS、速率限制、輸入驗證 |
| 效能 | 壓縮、快取、連接池 |
| 可靠性 | 健康檢查、正常關閉、重試邏輯 |
| 可觀察性 | 結構化日誌記錄、指標、追蹤 |
| 持續整合/持續交付 | 自動化測試、Docker 建置、部署管道 |
| 基礎設施 | 反向代理、SSL、負載平衡 |
8. 系列總結
透過 20 節課程,您已經掌握了 NestJS 從基礎到生產的全部內容:
- 第 1 部分:TypeScript、控制器、路由——核心基礎
- 第2部分:DI、模組、資料庫、驗證-建構資料層
- 第三部分:身份驗證、授權、安全性——應用程式安全
- 第 4 部分:WebSockets、GraphQL、快取、調度——進階功能
- 第五部分:微服務、測試、Docker、生產-實際部署
祝您使用 NestJS 成功!