Skip to content

微服务网关:Hono 作为轻量级 API Gateway

路由转发、认证、限流、日志

在微服务架构中,API 网关(API Gateway) 是系统的统一入口,负责请求路由、身份验证、限流、监控等横切关注点。传统网关如 Nginx、Kong、Traefik 功能强大但配置复杂,而 Hono 凭借其轻量、高性能、TypeScript 友好和边缘兼容性,成为构建轻量级 API 网关的理想选择

本文将展示如何使用 Hono 实现一个功能完整的微服务网关,支持:

  • 动态路由转发(Reverse Proxy)
  • 身份认证(JWT / API Key)
  • 请求限流(Rate Limiting)
  • 请求日志与监控
  • 错误处理与熔断

一、为什么选择 Hono 作为 API 网关?

特性优势
极低延迟路由匹配 < 0.1ms,适合高频请求
轻量 (~2KB)无依赖,内存占用小
TypeScript 原生支持类型安全,开发体验佳
边缘兼容可部署在 Cloudflare Workers、Deno、Bun
中间件生态支持 JWT、CORS、压缩、限流等
可编程性强使用 JS/TS 编写网关逻辑,灵活可控

适用场景:中小型微服务、Serverless 架构、边缘网关、内部服务网格入口。

二、架构设计

+------------------+
|     Client       |
+--------+---------+
         |
         v
+--------+---------+     +------------------+
|   Hono Gateway   | --> |  Service A       |
| (API Gateway)    |     | http://svc-a:3001 |
+--------+---------+     +------------------+
         |
         +-------------> |  Service B       |
                         | http://svc-b:3002 |
                         +------------------+
         |
         +-------------> |  Auth Service     |
                         | http://auth:3000  |
                         +------------------+
  • 所有请求先经过 Hono 网关;
  • 网关负责认证、路由、限流、日志;
  • 合法请求被转发到对应微服务。

三、核心功能实现

1. 初始化项目
bash
npm create hono@latest my-gateway
cd my-gateway
npm install @hono/jwt @hono/ratelimit @hono/zod-validator

2. 路由转发(Reverse Proxy)
ts
// middleware/proxy.ts
import { Hono } from 'hono'

export const createProxy = (target: string) => {
  return async (c, next) => {
    const path = c.req.path // 如 /api/users/*
    const url = new URL(c.req.url)
    const proxyUrl = `${target}${path}${url.search}`

    const req = new Request(proxyUrl, {
      method: c.req.method,
      headers: c.req.headers,
      body: c.req.method !== 'GET' && c.req.method !== 'HEAD' ? c.req.raw.body : null
    })

    // 移除 Host 头,避免目标服务拒绝
    req.headers.delete('host')

    try {
      const res = await fetch(req)
      return res
    } catch (error) {
      return c.json({ error: 'Service unreachable' }, 502)
    }
  }
}
3. 服务路由配置
ts
// config/services.ts
export const SERVICES = {
  'users': { target: 'http://localhost:3001', prefix: '/api/users' },
  'orders': { target: 'http://localhost:3002', prefix: '/api/orders' },
  'products': { target: 'http://localhost:3003', prefix: '/api/products' }
}
4. 认证中间件(JWT / API Key)
ts
// middleware/auth.ts
import { bearerAuth } from '@hono/bearer-auth'
import { jwt } from '@hono/jwt'

const API_KEYS = new Set(['sk-live-12345', 'sk-test-67890'])

export const authMiddleware = (c, next) => {
  const auth = c.req.header('Authorization')

  // 方式1:API Key
  if (auth?.startsWith('Bearer sk-')) {
    const token = auth.split(' ')[1]
    if (API_KEYS.has(token)) {
      return next()
    }
  }

  // 方式2:JWT
  if (auth?.startsWith('Bearer ey')) {
    const jwtMiddleware = jwt({ 
      secret: 'your-super-secret-jwt-key' 
    })
    return jwtMiddleware(c, next)
  }

  return c.json({ error: 'Unauthorized' }, 401)
}
5. 限流中间件
ts
// middleware/ratelimit.ts
import { Ratelimit } from '@hono/ratelimit'
import { kv } from '@hono/kv-storage' // 可替换为 Redis、D1 等

export const rateLimit = Ratelimit({
  limit: 100, // 每分钟最多 100 次
  duration: '1 min',
  async store(key) {
    // 使用 KV 存储计数
    const client = kv()
    return {
      async increment() {
        const value = (await client.get<number>(key)) || 0
        await client.set(key, value + 1, { expirationTtl: 60 })
        return { current: value + 1, limit: 100 }
      }
    }
  },
  key: (c) => c.req.header('x-forwarded-for') || c.req.ip // 按 IP 限流
})
6. 日志中间件
ts
// middleware/logger.ts
export const logger = async (c, next) => {
  const start = Date.now()
  const method = c.req.method
  const path = c.req.path
  const ip = c.req.header('x-forwarded-for') || c.req.ip

  await next()

  const status = c.res.status
  const ms = Date.now() - start

  console.log(`[${new Date().toISOString()}] ${method} ${path} ${status} ${ms}ms ${ip}`)

  // 可选:发送到日志服务(如 Logflare、Datadog)
  // await fetch('https://logs.example.com', { method: 'POST', body: JSON.stringify(log) })
}

四、主网关应用

ts
// app.ts
import { Hono } from 'hono'
import { SERVICES } from './config/services'
import { createProxy } from './middleware/proxy'
import { authMiddleware } from './middleware/auth'
import { rateLimit } from './middleware/ratelimit'
import { logger } from './middleware/logger'

const app = new Hono()

// 全局中间件
app.use('*', logger)
app.use('/api/*', rateLimit)
app.use('/api/*', authMiddleware)

// 动态路由转发
Object.entries(SERVICES).forEach(([name, config]) => {
  app.on(['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], `${config.prefix}/*`, createProxy(config.target))
})

// 健康检查
app.get('/health', (c) => c.json({ status: 'ok', timestamp: Date.now() }))

// 404 处理
app.notFound((c) => c.json({ error: 'Not Found' }, 404))

// 错误处理
app.onError((err, c) => {
  console.error(err)
  return c.json({ error: 'Internal Server Error' }, 500)
})

export default app

五、部署选项

平台优势
Cloudflare Workers全球边缘,低延迟
Bun高性能,适合自托管
Deno安全、无依赖
Node.js + PM2传统服务器部署
Docker容器化,K8s 集成
Dockerfile 示例
Dockerfile
FROM oven/bun:1.1

WORKDIR /app
COPY . .
RUN bun install

EXPOSE 3000
CMD ["bun", "app.ts"]

六、高级功能(可选)

1. 熔断与降级
ts
import { CircuitBreaker } from 'some-circuit-breaker-lib'

const cb = new CircuitBreaker({ threshold: 5, timeout: 30 })

app.use('/api/users/*', async (c, next) => {
  try {
    await cb.call(() => next())
  } catch (err) {
    return c.json({ error: 'Service temporarily unavailable' }, 503)
  }
})
2. 请求改写(Rewrite)
ts
app.post('/api/legacy/order', async (c) => {
  const body = await c.req.json()
  const newBody = { order: body } // 适配新格式
  const req = new Request('http://orders/create', {
    method: 'POST',
    body: JSON.stringify(newBody)
  })
  return fetch(req)
})
3. 响应缓存
ts
app.get('/api/products', async (c) => {
  const cache = await caches.default
  const key = c.req.url
  const cached = await cache.match(key)

  if (cached) return cached

  const res = await fetch('http://products:3003/list')
  const response = res.clone()

  c.executionCtx.waitUntil(cache.put(key, response))
  return res
})

七、性能优化建议

  1. 启用 Gzip 压缩

    ts
    import { compress } from '@hono/compress'
    app.use('*', compress())
  2. 使用连接池(Node.js 环境)

  3. 避免阻塞操作

  4. 监控 CPU/内存使用

八、总结

功能Hono 实现方式
路由转发fetch() + 自定义 proxy 中间件
认证@hono/jwt, bearerAuth, 自定义 key 验证
限流@hono/ratelimit + KV/Redis
日志自定义 logger 中间件
监控集成 Prometheus / Datadog
熔断第三方库或自定义逻辑

Hono 不只是一个 Web 框架,它是一个可编程的边缘网关平台
通过几行 TypeScript 代码,你就能构建一个轻量、高性能、可扩展的 API 网关,完美适配微服务、Serverless 和边缘计算架构。

立即尝试将 Hono 引入你的架构,打造下一代智能网关!