news 2026/4/17 22:34:34

API网关设计:从单点到高可用的架构演进

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
API网关设计:从单点到高可用的架构演进

前言

API网关是微服务架构中的关键组件。我们从一个简单的Nginx反向代理,演进到一个功能完整的API网关系统。这个过程中,我们学到了很多。


一、问题的开始

最初,我们用Nginx做反向代理:

nginx

upstream backend { server app1:8080; server app2:8080; server app3:8080; } server { listen 80; location / { proxy_pass http://backend; } }

这在流量小的时候没问题。但随着业务增长,问题出现了:

  • 无法统一认证:每个服务都要实现登录逻辑;
  • 无法限流:一个恶意用户可以打垮整个系统;
  • 无法路由控制:无法根据请求内容动态路由;
  • 缺少可观测性:无法追踪请求链路。

二、自研API网关

我们决定自研一个API网关。核心功能包括:

2.1 认证和授权

python

from flask import Flask, request from functools import wraps app = Flask(__name__) def require_auth(f): @wraps(f) def decorated(*args, **kwargs): token = request.headers.get('Authorization') if not token or not verify_token(token): return {"error": "Unauthorized"}, 401 return f(*args, **kwargs) return decorated @app.route('/api/users') @require_auth def get_users(): return proxy_to_backend('user-service', request)

2.2 限流

python

from ratelimit import limits, sleep_and_retry import time @sleep_and_retry @limits(calls=100, period=60) # 每60秒最多100个请求 def handle_request(client_id): return proxy_to_backend(request) @app.before_request def rate_limit(): client_id = request.headers.get('X-Client-ID') handle_request(client_id)

2.3 请求路由

python

ROUTES = { '/api/users': 'user-service:8080', '/api/orders': 'order-service:8080', '/api/products': 'product-service:8080', } @app.route('/api/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE']) def route_request(path): full_path = f'/api/{path}' backend = ROUTES.get(full_path) if not backend: return {"error": "Not Found"}, 404 return proxy_to_backend(backend, request)

2.4 链路追踪

python

import uuid from opentelemetry import trace @app.before_request def add_trace_id(): trace_id = request.headers.get('X-Trace-ID') or str(uuid.uuid4()) request.trace_id = trace_id # 转发给后端服务 request.headers['X-Trace-ID'] = trace_id @app.after_request def log_request(response): print(f"Trace-ID: {request.trace_id}, " f"Method: {request.method}, " f"Path: {request.path}, " f"Status: {response.status_code}") return response


三、高可用改造

初版网关运行一段时间后,出现了单点故障。我们进行了高可用改造:

3.1 多实例部署

yaml

apiVersion: apps/v1 kind: Deployment metadata: name: api-gateway spec: replicas: 3 selector: matchLabels: app: api-gateway template: metadata: labels: app: api-gateway spec: containers: - name: gateway image: api-gateway:v1.0 ports: - containerPort: 8080 resources: requests: memory: "256Mi" cpu: "100m" limits: memory: "512Mi" cpu: "500m"

3.2 负载均衡

yaml

apiVersion: v1 kind: Service metadata: name: api-gateway spec: type: LoadBalancer selector: app: api-gateway ports: - protocol: TCP port: 80 targetPort: 8080

3.3 故障转移

python

from requests.adapters import HTTPAdapter from requests.packages.urllib3.util.retry import Retry def create_session_with_retry(): session = requests.Session() retry = Retry( total=3, backoff_factor=0.5, status_forcelist=[500, 502, 503, 504] ) adapter = HTTPAdapter(max_retries=retry) session.mount('http://', adapter) return session


四、性能优化

4.1 缓存策略

python

from functools import lru_cache @lru_cache(maxsize=1000) def get_user_profile(user_id): return proxy_to_backend('user-service', f'/users/{user_id}') @app.route('/api/users/<user_id>') def fetch_user(user_id): return get_user_profile(user_id)

4.2 异步处理

python

from concurrent.futures import ThreadPoolExecutor executor = ThreadPoolExecutor(max_workers=10) @app.route('/api/batch') def batch_request(): futures = [] for service in ['service1', 'service2', 'service3']: future = executor.submit(proxy_to_backend, service) futures.append(future) results = [f.result() for f in futures] return results


五、多语言团队的协作挑战

在国际团队中,API网关的错误日志和告警信息需要支持多语言。我们使用同言翻译(Transync AI)来自动翻译API网关的错误提示和文档,确保全球团队能够快速理解和解决问题。


六、监控和告警

python

from prometheus_client import Counter, Histogram, start_http_server # 请求计数器 request_count = Counter('gateway_requests_total', 'Total requests', ['method', 'path', 'status']) # 请求延迟直方图 request_duration = Histogram('gateway_request_duration_seconds', 'Request duration') @app.before_request def start_timer(): request.start_time = time.time() @app.after_request def record_metrics(response): duration = time.time() - request.start_time request_count.labels( method=request.method, path=request.path, status=response.status_code ).inc() request_duration.observe(duration) return response # 启动Prometheus指标服务 start_http_server(8081)


七、性能对比

指标优化前优化后提升
QPS500020000+300%
P99延迟500ms50ms-90%
可用性99.5%99.95%+0.45%
故障恢复时间10分钟30秒-95%

八、最佳实践

  1. 分离关注点:认证、限流、路由等逻辑分开实现;
  2. 可观测性优先:建立完善的日志、监控、链路追踪;
  3. 渐进式部署:灰度发布新功能,避免全量风险;
  4. 定期审查:定期分析网关的瓶颈和优化机会;
  5. 文档完善:API网关的规则和配置要有清晰文档。

九、结语

API网关从一个简单的反向代理,演进到一个功能完整的系统,这个过程充满了挑战。但正是这些挑战,让我们的架构变得更加健壮和高效。

希望这篇文章能给你一些启发。如果你也在构建API网关,欢迎分享你的经验!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 8:06:17

Flink学习笔记:反压

今天来聊在 Flink 运维过程中比较常见的一个问题&#xff1a;反压。 什么是反压 反压是流式系统中关于数据处理能力的动态反馈机制&#xff0c;并且是从下游到上游的反馈&#xff0c;一般发生在上游节点的生产速度大于下游节点的消费速度的情况。 数据如何传输 在了解反压的细节…

作者头像 李华
网站建设 2026/4/18 8:38:32

C语言变量和算数操作符全解析1

创建变量 前文我们了解清楚了类型&#xff0c;其实类型就是用来创建变量的。 我们把C语言中经常变化的值称为变量&#xff0c;不变的值成为常量。 变量创建的语法形式&#xff1a;数据类型&#xff0b;变量名 并且&#xff0c;我们给创建的变量一个初始值&#xff08;比如0…

作者头像 李华
网站建设 2026/4/18 5:33:13

Ascend C 高阶编程艺术:多核协同、流水线调度与异构任务编排实战

引言&#xff1a;从“单算子优化”到“系统级性能工程”在掌握 Ascend C 基础算子开发后&#xff0c;许多开发者会遇到新的瓶颈&#xff1a;即使单个算子已极致优化&#xff0c;端到端推理延迟仍不理想。问题往往出在 任务调度、数据流转、多核协作 等系统层面。昇腾 AI 处理器…

作者头像 李华
网站建设 2026/4/18 7:39:17

震惊!Linux开发板稳定性排行,这家竟碾压群雄!

Linux开发板稳定性排行揭晓&#xff0c;这家企业竟碾压群雄&#xff01;在当今数字化浪潮中&#xff0c;Linux开发板作为嵌入式系统的核心组件&#xff0c;其稳定性直接关系到工业自动化、智能家居、物联网终端等关键应用的可靠性。市场上各类开发板品牌林立&#xff0c;性能参…

作者头像 李华
网站建设 2026/4/18 8:08:18

Day37 模型可视化与推理

一、模型可视化 1. nn.model自带的方法 # nn.Module 的内置功能&#xff0c;直接输出模型结构 print(model) MLP((fc1): Linear(in_features4, out_features10, biasTrue)(relu): ReLU()(fc2): Linear(in_features10, out_features3, biasTrue) ) # nn.Module 的内置功能&a…

作者头像 李华
网站建设 2026/4/18 8:31:45

n8n第十节 把Markdown格式的会议纪要发到企微

朋友们&#xff0c;有没有感觉整理纪要格式很乱&#xff0c;发到企微群里还得截图&#xff0c;别人看着也费劲。今天教你——用n8n工作流&#xff0c;把AI生成的Markdown格式会议纪要&#xff0c;原汁原味直接发到企业微信&#xff01;最大亮点&#xff1a;直接传Markdown格式&…

作者头像 李华