前言
你有没有想过:在微服务架构中,几十个服务对外暴露的入口是怎么统一管理的?怎么做鉴权、限流、路由转发、日志监控?
API网关是微服务架构的统一入口。
今天我们用C语言从零实现一个API网关的核心功能:
· 路由转发(路径匹配/域名匹配)
· 负载均衡(轮询/随机/加权)
· 限流器(令牌桶/漏桶)
· 认证鉴权(API Key/JWT)
· 请求/响应转换
· 日志记录与监控
· 插件化架构
一、API网关核心原理
- 架构图
```
┌─────────────────────────────────────────────────────────────┐
│ 客户端 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ API网关 │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 路由 │→│ 限流 │→│ 鉴权 │→│ 转发 │ │
│ │ 匹配 │ │ 检查 │ │ 认证 │ │ 请求 │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 服务A │ │ 服务B │ │ 服务C │
└─────────┘ └─────────┘ └─────────┘
```
- 核心功能
功能 说明
路由 根据路径/Host/Header转发到不同服务
限流 令牌桶/漏桶,防止流量突增
鉴权 API Key、JWT认证
负载均衡 轮询、随机、加权
插件 可扩展架构
二、完整代码实现
- 基础数据结构
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define MAX_ROUTES 100
#define MAX_SERVICES 100
#define MAX_PLUGINS 50
#define MAX_HEADERS 32
#define BUFFER_SIZE 65536
// 服务实例
typedef struct service_instance {
char host32;
int port;
int weight;
int healthy;
int connection_count;
time_t last_check;
struct service_instance *next;
} service_instance_t;
// 服务
typedef struct service {
char name64;
service_instance_t *instances;
int instance_count;
int lb_algorithm; // 0: round-robin, 1: random, 2: weighted
int current_index;
pthread_mutex_t mutex;
struct service *next;
} service_t;
// 路由
typedef struct route {
char path128;
char host64;
char service_name64;
int strip_path;
char rewrite_path128;
int priority;
struct route *next;
} route_t;
// 限流器
typedef struct rate_limiter {
char key128;
int rate;
int burst;
int tokens;
time_t last_update;
pthread_mutex_t mutex;
struct rate_limiter *next;
} rate_limiter_t;
// API Key认证
typedef struct api_key {
char key64;
char consumer64;
int enabled;
struct api_key *next;
} api_key_t;
// 插件上下文
typedef struct plugin_context {
char name64;
void *config;
int (*init)(void *config);
int (*exec)(struct http_request *req, void *config);
void (*destroy)(void *config);
struct plugin_context *next;
} plugin_context_t;
// HTTP请求
typedef struct http_request {
char method16;
char uri1024;
char path1024;
char query512;
char version16;
char headersMAX_HEADERS512;
int header_count;
char bodyBUFFER_SIZE;
int body_len;
char client_ip32;
char host256;
} http_request_t;
// HTTP响应
typedef struct http_response {
int status_code;
char headersMAX_HEADERS512;
int header_count;
char bodyBUFFER_SIZE;
int body_len;
} http_response_t;
// API网关
typedef struct api_gateway {
route_t *routes;
service_t *services;
rate_limiter_t *limiters;
api_key_t *api_keys;
plugin_context_t *plugins;
int port;
int running;
pthread_mutex_t mutex;
pthread_t worker_threads10;
} api_gateway_t;
```
- 路由管理
```c
// 创建API网关
api_gateway_t *gateway_create(int port) {
api_gateway_t *gw = malloc(sizeof(api_gateway_t));
memset(gw, 0, sizeof(api_gateway_t));
gw->port = port;
gw->running = 1;
pthread_mutex_init(&gw->mutex, NULL);
printf("网关 启动,端口: %d\n", port);
return gw;
}
// 添加路由
void gateway_add_route(api_gateway_t *gw, const char *path, const char *host,
const char *service, int strip_path, int priority) {
pthread_mutex_lock(&gw->mutex);
route_t *r = malloc(sizeof(route_t));
strcpy(r->path, path);
strcpy(r->host, host);
strcpy(r->service_name, service);
r->strip_path = strip_path;
r->rewrite_path0 = '\0';
r->priority = priority;
r->next = gw->routes;
gw->routes = r;
pthread_mutex_unlock(&gw->mutex);
printf("路由 %s → %s (优先级: %d)\n", path, service, priority);
}
// 添加服务
void gateway_add_service(api_gateway_t *gw, const char *name, int lb_algorithm) {
pthread_mutex_lock(&gw->mutex);
service_t *s = malloc(sizeof(service_t));
strcpy(s->name, name);
s->instances = NULL;
s->instance_count = 0;
s->lb_algorithm = lb_algorithm;
s->current_index = 0;
pthread_mutex_init(&s->mutex, NULL);
s->next = gw->services;
gw->services = s;
pthread_mutex_unlock(&gw->mutex);
printf("服务 %s (LB: %d)\n", name, lb_algorithm);
}
// 添加服务实例
void gateway_add_instance(api_gateway_t *gw, const char *service_name,
const char *host, int port, int weight) {
service_t *s = gw->services;
while (s) {
if (strcmp(s->name, service_name) == 0) break;
s = s->next;
}
if (!s) return;
pthread_mutex_lock(&s->mutex);
service_instance_t *inst = malloc(sizeof(service_instance_t));
strcpy(inst->host, host);
inst->port = port;
inst->weight = weight;
inst->healthy = 1;
inst->connection_count = 0;
inst->last_check = time(NULL);
inst->next = s->instances;
s->instances = inst;
s->instance_count++;
pthread_mutex_unlock(&s->mutex);
printf("实例 %s → %s:%d (权重: %d)\n", service_name, host, port, weight);
}
```
- 负载均衡
```c
// 负载均衡选择实例
service_instance_t *lb_select(service_t *service) {
if (!service || !service->instances) return NULL;
pthread_mutex_lock(&service->mutex);
service_instance_t *selected = NULL;
int count = service->instance_count;
switch (service->lb_algorithm) {
case 0: { // Round-Robin
int idx = service->current_index % count;
service_instance_t *inst = service->instances;
for (int i = 0; i < idx && inst; i++) {
inst = inst->next;
}
if (inst && inst->healthy) selected = inst;
service->current_index++;
break;
}
case 1: { // Random
int idx = rand() % count;
service_instance_t *inst = service->instances;
for (int i = 0; i < idx && inst; i++) {
inst = inst->next;
}
if (inst && inst->healthy) selected = inst;
break;
}
case 2: { // Weighted
int total_weight = 0;
service_instance_t *inst = service->instances;
while (inst) {
if (inst->healthy) total_weight += inst->weight;
inst = inst->next;
}
if (total_weight == 0) break;
int r = rand() % total_weight;
inst = service->instances;
while (inst) {
if (inst->healthy) {
r -= inst->weight;
if (r < 0) {
selected = inst;
break;
}
}
inst = inst->next;
}
break;
}
}
if (selected) selected->connection_count++;
pthread_mutex_unlock(&service->mutex);
return selected;
}
```
- 限流器
```c
// 令牌桶限流
rate_limiter_t *gateway_get_limiter(api_gateway_t *gw, const char *key,
int rate, int burst) {
pthread_mutex_lock(&gw->mutex);
rate_limiter_t *rl = gw->limiters;
while (rl) {
if (strcmp(rl->key, key) == 0) {
pthread_mutex_unlock(&gw->mutex);
return rl;
}
rl = rl->next;
}
rl = malloc(sizeof(rate_limiter_t));
strcpy(rl->key, key);
rl->rate = rate;
rl->burst = burst;
rl->tokens = burst;
rl->last_update = time(NULL);
pthread_mutex_init(&rl->mutex, NULL);
rl->next = gw->limiters;
gw->limiters = rl;
pthread_mutex_unlock(&gw->mutex);
return rl;
}
int rate_limiter_allow(rate_limiter_t *rl) {
pthread_mutex_lock(&rl->mutex);
time_t now = time(NULL);
int elapsed = now - rl->last_update;
if (elapsed > 0) {
int new_tokens = elapsed * rl->rate;
rl->tokens = (rl->tokens + new_tokens > rl->burst) ?
rl->burst : rl->tokens + new_tokens;
rl->last_update = now;
}
int allow = (rl->tokens > 0);
if (allow) rl->tokens--;
pthread_mutex_unlock(&rl->mutex);
return allow;
}
```
- HTTP转发
```c
// 转发HTTP请求
int gateway_forward(api_gateway_t *gw, http_request_t *req, http_response_t *resp) {
// 匹配路由
route_t *route = gw->routes;
route_t *matched = NULL;
int best_priority = -1;
while (route) {
// 路径匹配
if (strncmp(req->path, route->path, strlen(route->path)) == 0) {
if (route->priority > best_priority) {
best_priority = route->priority;
matched = route;
}
}
route = route->next;
}
if (!matched) {
resp->status_code = 404;
strcpy(resp->body, "{\"error\": \"No route matched\"}");
resp->body_len = strlen(resp->body);
return 0;
}
// 查找服务
service_t *service = gw->services;
while (service) {
if (strcmp(service->name, matched->service_name) == 0) break;
service = service->next;
}
if (!service) {
resp->status_code = 503;
strcpy(resp->body, "{\"error\": \"Service not found\"}");
resp->body_len = strlen(resp->body);
return 0;
}
// 负载均衡
service_instance_t *inst = lb_select(service);
if (!inst) {
resp->status_code = 503;
strcpy(resp->body, "{\"error\": \"No healthy instances\"}");
resp->body_len = strlen(resp->body);
return 0;
}
// 构建转发请求
char forward_reqBUFFER_SIZE;
char *path_start = req->path + strlen(matched->path);
if (matched->strip_path) {
snprintf(forward_req, sizeof(forward_req), "%s %s %s\r\n",
req->method, path_start0 ? path_start : "/", req->version);
} else {
snprintf(forward_req, sizeof(forward_req), "%s %s %s\r\n",
req->method, req->path, req->version);
}
// 转发
int backend_fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(inst->port);
inet_pton(AF_INET, inst->host, &addr.sin_addr);
if (connect(backend_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
close(backend_fd);
resp->status_code = 502;
strcpy(resp->body, "{\"error\": \"Connection failed\"}");
resp->body_len = strlen(resp->body);
return 0;
}
send(backend_fd, forward_req, strlen(forward_req), 0);
// 发送headers和body...
send(backend_fd, req->body, req->body_len, 0);
// 接收响应
char bufferBUFFER_SIZE;
int n = recv(backend_fd, buffer, sizeof(buffer) - 1, 0);
close(backend_fd);
if (n <= 0) {
resp->status_code = 502;
strcpy(resp->body, "{\"error\": \"No response\"}");
resp->body_len = strlen(resp->body);
return 0;
}
buffern = '\0';
// 解析响应(简化)
resp->status_code = 200;
strcpy(resp->body, buffer);
resp->body_len = n;
return 0;
}
```
- 测试代码
```c
void test_gateway() {
printf("=== API网关测试 ===\n\n");
api_gateway_t *gw = gateway_create(8080);
// 添加服务
gateway_add_service(gw, "user-service", 0);
gateway_add_instance(gw, "user-service", "127.0.0.1", 9001, 100);
gateway_add_instance(gw, "user-service", "127.0.0.1", 9002, 100);
gateway_add_service(gw, "order-service", 2);
gateway_add_instance(gw, "order-service", "127.0.0.1", 9003, 80);
gateway_add_instance(gw, "order-service", "127.0.0.1", 9004, 120);
// 添加路由
gateway_add_route(gw, "/api/users", "", "user-service", 1, 10);
gateway_add_route(gw, "/api/orders", "", "order-service", 1, 10);
gateway_add_route(gw, "/", "", "user-service", 0, 1);
// 限流器测试
rate_limiter_t *rl = gateway_get_limiter(gw, "192.168.1.100", 5, 10);
printf("\n限流测试 (10次请求, rate=5/s):\n");
int allowed = 0;
for (int i = 0; i < 10; i++) {
if (rate_limiter_allow(rl)) allowed++;
printf(" 请求%d: %s\n", i+1, rate_limiter_allow(rl) ? "允许" : "拦截");
}
printf(" 允许: %d, 拦截: %d\n", allowed, 10-allowed);
printf("\n网关启动: http://localhost:%d\n", gw->port);
free(gw);
}
int main() {
srand(time(NULL));
test_gateway();
return 0;
}
```
三、编译和运行
```bash
gcc -o api_gateway api_gateway.c -lpthread
./api_gateway
```
四、Kong vs 本实现
特性 本实现 Kong
路由 ✅ 基础 ✅ 高级
负载均衡 ✅ ✅
限流 ✅ 令牌桶 ✅ 多种
认证 ❌ ✅ 多种
插件系统 ❌ ✅ Lua
数据库配置 ❌ ✅
Admin API ❌ ✅
五、总结
通过这篇文章,你学会了:
· API网关的核心功能(路由、负载均衡、限流)
· 路由匹配和服务发现
· 负载均衡算法(轮询、随机、加权)
· 令牌桶限流器
· HTTP请求转发
API网关是微服务架构的统一入口。掌握它,你就理解了Kong、Spring Cloud Gateway的底层设计。
下一篇预告:《从零实现一个分布式配置中心:Apollo的核心设计》
评论区分享一下你对API网关的理解~