api-gateway-configuration

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

API Gateway Configuration

API网关配置

Overview

概述

Design and configure API gateways to handle routing, authentication, rate limiting, and request/response transformation for microservice architectures.
设计并配置API网关,以处理微服务架构中的路由、认证、速率限制以及请求/响应转换。

When to Use

适用场景

  • Setting up reverse proxies for microservices
  • Centralizing API authentication
  • Implementing request/response transformation
  • Managing traffic across backend services
  • Rate limiting and quota enforcement
  • API versioning and routing
  • 为微服务设置反向代理
  • 集中管理API认证
  • 实现请求/响应转换
  • 管理后端服务的流量
  • 速率限制与配额执行
  • API版本控制与路由

Instructions

配置指南

1. Kong Configuration

1. Kong配置

yaml
undefined
yaml
undefined

kong.yml - Kong Gateway configuration

kong.yml - Kong Gateway configuration

_format_version: "2.1" _transform: true
services:
  • name: user-service url: http://user-service:3000 routes:
    • name: user-routes paths:
      • /api/users
      • /api/profile plugins:
    • name: rate-limiting config: minute: 100 policy: local
    • name: jwt config: secret: your-secret-key key_claim_name: "sub"
    • name: cors config: origins: - "http://localhost:3000" - "https://example.com" methods: - GET - POST - PUT - DELETE allow_headers: - Content-Type - Authorization
  • name: product-service url: http://product-service:3001 routes:
    • name: product-routes paths:
      • /api/products plugins:
    • name: rate-limiting config: minute: 500
    • name: request-transformer config: add: headers: - "X-Service-Name:product-service"
  • name: order-service url: http://order-service:3002 routes:
    • name: order-routes paths:
      • /api/orders plugins:
    • name: jwt
    • name: request-size-limiting config: allowed_payload_size: 5
consumers:
  • username: mobile-app custom_id: mobile-app-001 acls:
    • group: api-users
plugins:
  • name: prometheus config: latency_metrics: true upstream_addr_header: X-Upstream-Addr
undefined
_format_version: "2.1" _transform: true
services:
  • name: user-service url: http://user-service:3000 routes:
    • name: user-routes paths:
      • /api/users
      • /api/profile plugins:
    • name: rate-limiting config: minute: 100 policy: local
    • name: jwt config: secret: your-secret-key key_claim_name: "sub"
    • name: cors config: origins: - "http://localhost:3000" - "https://example.com" methods: - GET - POST - PUT - DELETE allow_headers: - Content-Type - Authorization
  • name: product-service url: http://product-service:3001 routes:
    • name: product-routes paths:
      • /api/products plugins:
    • name: rate-limiting config: minute: 500
    • name: request-transformer config: add: headers: - "X-Service-Name:product-service"
  • name: order-service url: http://order-service:3002 routes:
    • name: order-routes paths:
      • /api/orders plugins:
    • name: jwt
    • name: request-size-limiting config: allowed_payload_size: 5
consumers:
  • username: mobile-app custom_id: mobile-app-001 acls:
    • group: api-users
plugins:
  • name: prometheus config: latency_metrics: true upstream_addr_header: X-Upstream-Addr
undefined

2. Nginx Configuration

2. Nginx配置

nginx
undefined
nginx
undefined

nginx.conf - API Gateway configuration

nginx.conf - API Gateway configuration

upstream user_service { server user-service:3000; keepalive 32; }
upstream product_service { server product-service:3001; keepalive 32; }
upstream order_service { server order-service:3002; keepalive 32; }
upstream user_service { server user-service:3000; keepalive 32; }
upstream product_service { server product-service:3001; keepalive 32; }
upstream order_service { server order-service:3002; keepalive 32; }

Rate limiting

Rate limiting

limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s; limit_req_zone $http_x_api_key zone=user_limit:10m rate=100r/s;
server { listen 80; server_name api.example.com;
# Enable gzip compression
gzip on;
gzip_types application/json;
gzip_min_length 1000;

# User Service Routes
location /api/users {
    limit_req zone=api_limit burst=20 nodelay;

    # Authentication check
    access_by_lua_block {
        local token = ngx.var.http_authorization
        if not token then
            return ngx.HTTP_UNAUTHORIZED
        end
    }

    proxy_pass http://user_service;
    proxy_http_version 1.1;
    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;

    # Request timeout
    proxy_connect_timeout 10s;
    proxy_send_timeout 30s;
    proxy_read_timeout 30s;
}

# Product Service Routes
location /api/products {
    limit_req zone=api_limit burst=50 nodelay;

    proxy_pass http://product_service;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # Caching
    proxy_cache api_cache;
    proxy_cache_valid 200 1m;
    proxy_cache_key "$scheme$request_method$host$request_uri";
}

# Order Service Routes (requires auth)
location /api/orders {
    limit_req zone=user_limit burst=10 nodelay;

    auth_request /auth;
    auth_request_set $auth_user $upstream_http_x_user_id;

    proxy_pass http://order_service;
    proxy_http_version 1.1;
    proxy_set_header X-User-ID $auth_user;
}

# Health check endpoint
location /health {
    access_log off;
    return 200 "healthy\n";
    add_header Content-Type text/plain;
}

# Metrics endpoint
location /metrics {
    stub_status on;
    access_log off;
}
}
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s; limit_req_zone $http_x_api_key zone=user_limit:10m rate=100r/s;
server { listen 80; server_name api.example.com;
# Enable gzip compression
gzip on;
gzip_types application/json;
gzip_min_length 1000;

# User Service Routes
location /api/users {
    limit_req zone=api_limit burst=20 nodelay;

    # Authentication check
    access_by_lua_block {
        local token = ngx.var.http_authorization
        if not token then
            return ngx.HTTP_UNAUTHORIZED
        end
    }

    proxy_pass http://user_service;
    proxy_http_version 1.1;
    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;

    # Request timeout
    proxy_connect_timeout 10s;
    proxy_send_timeout 30s;
    proxy_read_timeout 30s;
}

# Product Service Routes
location /api/products {
    limit_req zone=api_limit burst=50 nodelay;

    proxy_pass http://product_service;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # Caching
    proxy_cache api_cache;
    proxy_cache_valid 200 1m;
    proxy_cache_key "$scheme$request_method$host$request_uri";
}

# Order Service Routes (requires auth)
location /api/orders {
    limit_req zone=user_limit burst=10 nodelay;

    auth_request /auth;
    auth_request_set $auth_user $upstream_http_x_user_id;

    proxy_pass http://order_service;
    proxy_http_version 1.1;
    proxy_set_header X-User-ID $auth_user;
}

# Health check endpoint
location /health {
    access_log off;
    return 200 "healthy\n";
    add_header Content-Type text/plain;
}

# Metrics endpoint
location /metrics {
    stub_status on;
    access_log off;
}
}

Cache definition

Cache definition

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:10m max_size=1g inactive=60m;
undefined
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:10m max_size=1g inactive=60m;
undefined

3. AWS API Gateway Configuration

3. AWS API Gateway配置

yaml
undefined
yaml
undefined

AWS SAM template for API Gateway

AWS SAM template for API Gateway

AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31
Resources: ApiGateway: Type: AWS::Serverless::Api Properties: StageName: prod Auth: DefaultAuthorizer: JwtAuthorizer Authorizers: JwtAuthorizer: FunctionArn: !GetAtt AuthorizerFunction.Arn Identity: Headers: - Authorization TracingEnabled: true MethodSettings: - ResourcePath: '/' HttpMethod: '' LoggingLevel: INFO DataTraceEnabled: true MetricsEnabled: true ThrottleSettings: BurstLimit: 1000 RateLimit: 100
UserServiceFunction: Type: AWS::Serverless::Function Properties: Handler: index.handler Runtime: nodejs18.x Environment: Variables: USER_SERVICE_URL: !Sub 'https://${UserServiceAlb}.elb.amazonaws.com' Events: GetUsers: Type: Api Properties: RestApiId: !Ref ApiGateway Path: /api/users Method: GET Auth: Authorizer: JwtAuthorizer CreateUser: Type: Api Properties: RestApiId: !Ref ApiGateway Path: /api/users Method: POST Auth: Authorizer: JwtAuthorizer
ApiUsagePlan: Type: AWS::ApiGateway::UsagePlan Properties: UsagePlanName: StandardPlan ApiStages: - ApiId: !Ref ApiGateway Stage: prod Quota: Limit: 10000 Period: DAY Throttle: RateLimit: 100 BurstLimit: 1000
ApiKey: Type: AWS::ApiGateway::ApiKey Properties: Name: StandardKey Enabled: true UsagePlanId: !Ref ApiUsagePlan
undefined
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31
Resources: ApiGateway: Type: AWS::Serverless::Api Properties: StageName: prod Auth: DefaultAuthorizer: JwtAuthorizer Authorizers: JwtAuthorizer: FunctionArn: !GetAtt AuthorizerFunction.Arn Identity: Headers: - Authorization TracingEnabled: true MethodSettings: - ResourcePath: '/' HttpMethod: '' LoggingLevel: INFO DataTraceEnabled: true MetricsEnabled: true ThrottleSettings: BurstLimit: 1000 RateLimit: 100
UserServiceFunction: Type: AWS::Serverless::Function Properties: Handler: index.handler Runtime: nodejs18.x Environment: Variables: USER_SERVICE_URL: !Sub 'https://${UserServiceAlb}.elb.amazonaws.com' Events: GetUsers: Type: Api Properties: RestApiId: !Ref ApiGateway Path: /api/users Method: GET Auth: Authorizer: JwtAuthorizer CreateUser: Type: Api Properties: RestApiId: !Ref ApiGateway Path: /api/users Method: POST Auth: Authorizer: JwtAuthorizer
ApiUsagePlan: Type: AWS::ApiGateway::UsagePlan Properties: UsagePlanName: StandardPlan ApiStages: - ApiId: !Ref ApiGateway Stage: prod Quota: Limit: 10000 Period: DAY Throttle: RateLimit: 100 BurstLimit: 1000
ApiKey: Type: AWS::ApiGateway::ApiKey Properties: Name: StandardKey Enabled: true UsagePlanId: !Ref ApiUsagePlan
undefined

4. Traefik Configuration

4. Traefik配置

yaml
undefined
yaml
undefined

traefik.yml - Traefik API Gateway

traefik.yml - Traefik API Gateway

global: checkNewVersion: false sendAnonymousUsage: false
entryPoints: web: address: ":80" websecure: address: ":443"
api: insecure: true dashboard: true
providers: docker: endpoint: "unix:///var/run/docker.sock" exposedByDefault: false file: filename: dynamic.yml
middleware: rateLimit: rateLimit: average: 100 burst: 50
authMiddleware: basicAuth: users: - "user:$apr1$r31.....$HqJZimcKQFAMYayBlzkrA/"
routers: api-users: entrypoints: - websecure rule: "Path(
/api/users
)" service: user-service tls: certResolver: letsencrypt middlewares: - rateLimit
api-products: entrypoints: - web rule: "Path(
/api/products
)" service: product-service
services: user-service: loadBalancer: servers: - url: "http://user-service:3000" healthCheck: scheme: http path: /health interval: 10s timeout: 5s
product-service: loadBalancer: servers: - url: "http://product-service:3001"
undefined
global: checkNewVersion: false sendAnonymousUsage: false
entryPoints: web: address: ":80" websecure: address: ":443"
api: insecure: true dashboard: true
providers: docker: endpoint: "unix:///var/run/docker.sock" exposedByDefault: false file: filename: dynamic.yml
middleware: rateLimit: rateLimit: average: 100 burst: 50
authMiddleware: basicAuth: users: - "user:$apr1$r31.....$HqJZimcKQFAMYayBlzkrA/"
routers: api-users: entrypoints: - websecure rule: "Path(
/api/users
)" service: user-service tls: certResolver: letsencrypt middlewares: - rateLimit
api-products: entrypoints: - web rule: "Path(
/api/products
)" service: product-service
services: user-service: loadBalancer: servers: - url: "http://user-service:3000" healthCheck: scheme: http path: /health interval: 10s timeout: 5s
product-service: loadBalancer: servers: - url: "http://product-service:3001"
undefined

5. Node.js Gateway Implementation

5. Node.js网关实现

javascript
const express = require('express');
const httpProxy = require('express-http-proxy');
const rateLimit = require('express-rate-limit');
const jwt = require('jsonwebtoken');

const app = express();

// Rate limiting
const limiter = rateLimit({
  windowMs: 60 * 1000,
  max: 100
});

// JWT verification
const verifyJwt = (req, res, next) => {
  const token = req.headers['authorization']?.split(' ')[1];
  if (!token) return res.status(401).json({ error: 'No token' });

  try {
    jwt.verify(token, process.env.JWT_SECRET);
    next();
  } catch (err) {
    res.status(403).json({ error: 'Invalid token' });
  }
};

// Request logging
app.use((req, res, next) => {
  console.log(`${new Date().toISOString()} ${req.method} ${req.path}`);
  next();
});

app.use(limiter);

// User service proxy
app.use('/api/users', verifyJwt, httpProxy('http://user-service:3000', {
  proxyReqPathResolver: (req) => `/api/users${req.url}`,
  userResDecorator: (proxyRes, proxyResData, userReq, userRes) => {
    proxyRes.headers['X-Gateway'] = 'true';
    return proxyResData;
  }
}));

// Product service proxy
app.use('/api/products', httpProxy('http://product-service:3001', {
  proxyReqPathResolver: (req) => `/api/products${req.url}`
}));

// Health check
app.get('/health', (req, res) => res.json({ status: 'ok' }));

app.listen(8080, () => console.log('Gateway on port 8080'));
javascript
const express = require('express');
const httpProxy = require('express-http-proxy');
const rateLimit = require('express-rate-limit');
const jwt = require('jsonwebtoken');

const app = express();

// Rate limiting
const limiter = rateLimit({
  windowMs: 60 * 1000,
  max: 100
});

// JWT verification
const verifyJwt = (req, res, next) => {
  const token = req.headers['authorization']?.split(' ')[1];
  if (!token) return res.status(401).json({ error: 'No token' });

  try {
    jwt.verify(token, process.env.JWT_SECRET);
    next();
  } catch (err) {
    res.status(403).json({ error: 'Invalid token' });
  }
};

// Request logging
app.use((req, res, next) => {
  console.log(`${new Date().toISOString()} ${req.method} ${req.path}`);
  next();
});

app.use(limiter);

// User service proxy
app.use('/api/users', verifyJwt, httpProxy('http://user-service:3000', {
  proxyReqPathResolver: (req) => `/api/users${req.url}`,
  userResDecorator: (proxyRes, proxyResData, userReq, userRes) => {
    proxyRes.headers['X-Gateway'] = 'true';
    return proxyResData;
  }
}));

// Product service proxy
app.use('/api/products', httpProxy('http://product-service:3001', {
  proxyReqPathResolver: (req) => `/api/products${req.url}`
}));

// Health check
app.get('/health', (req, res) => res.json({ status: 'ok' }));

app.listen(8080, () => console.log('Gateway on port 8080'));

Best Practices

最佳实践

✅ DO

✅ 建议做法

  • Centralize authentication at gateway level
  • Implement rate limiting globally
  • Add comprehensive logging
  • Use health checks for backends
  • Cache responses when appropriate
  • Implement circuit breakers
  • Monitor gateway metrics
  • Use HTTPS in production
  • 在网关层面集中处理认证
  • 全局实现速率限制
  • 添加全面的日志记录
  • 为后端服务配置健康检查
  • 合理缓存响应
  • 实现断路器
  • 监控网关指标
  • 生产环境使用HTTPS

❌ DON'T

❌ 避免做法

  • Expose backend service details
  • Skip request validation
  • Forget to log API usage
  • Use weak authentication
  • Over-cache dynamic data
  • Ignore backend timeouts
  • Skip security headers
  • Expose internal IPs
  • 暴露后端服务细节
  • 跳过请求验证
  • 忽略API使用日志
  • 使用弱认证方式
  • 过度缓存动态数据
  • 忽略后端超时设置
  • 跳过安全头配置
  • 暴露内部IP地址

Monitoring & Observability

监控与可观测性

javascript
// Prometheus metrics
const promClient = require('prom-client');

const httpRequestDuration = new promClient.Histogram({
  name: 'gateway_http_request_duration_seconds',
  help: 'Duration of HTTP requests in seconds',
  labelNames: ['method', 'route', 'status_code']
});

const httpRequests = new promClient.Counter({
  name: 'gateway_http_requests_total',
  help: 'Total number of HTTP requests',
  labelNames: ['method', 'route', 'status_code']
});

app.use((req, res, next) => {
  const start = Date.now();
  res.on('finish', () => {
    const duration = (Date.now() - start) / 1000;
    httpRequestDuration.labels(req.method, req.path, res.statusCode).observe(duration);
    httpRequests.labels(req.method, req.path, res.statusCode).inc();
  });
  next();
});
javascript
// Prometheus metrics
const promClient = require('prom-client');

const httpRequestDuration = new promClient.Histogram({
  name: 'gateway_http_request_duration_seconds',
  help: 'Duration of HTTP requests in seconds',
  labelNames: ['method', 'route', 'status_code']
});

const httpRequests = new promClient.Counter({
  name: 'gateway_http_requests_total',
  help: 'Total number of HTTP requests',
  labelNames: ['method', 'route', 'status_code']
});

app.use((req, res, next) => {
  const start = Date.now();
  res.on('finish', () => {
    const duration = (Date.now() - start) / 1000;
    httpRequestDuration.labels(req.method, req.path, res.statusCode).observe(duration);
    httpRequests.labels(req.method, req.path, res.statusCode).inc();
  });
  next();
});