从零实现一个API网关:Kong的核心设计
前言你有没有想过在微服务架构中几十个服务对外暴露的入口是怎么统一管理的怎么做鉴权、限流、路由转发、日志监控API网关是微服务架构的统一入口。今天我们用C语言从零实现一个API网关的核心功能· 路由转发路径匹配/域名匹配· 负载均衡轮询/随机/加权· 限流器令牌桶/漏桶· 认证鉴权API Key/JWT· 请求/响应转换· 日志记录与监控· 插件化架构---一、API网关核心原理1. 架构图┌─────────────────────────────────────────────────────────────┐│ 客户端 │└─────────────────────────────────────────────────────────────┘│▼┌─────────────────────────────────────────────────────────────┐│ API网关 ││ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ││ │ 路由 │→│ 限流 │→│ 鉴权 │→│ 转发 │ ││ │ 匹配 │ │ 检查 │ │ 认证 │ │ 请求 │ ││ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │└─────────────────────────────────────────────────────────────┘│ │ │▼ ▼ ▼┌─────────┐ ┌─────────┐ ┌─────────┐│ 服务A │ │ 服务B │ │ 服务C │└─────────┘ └─────────┘ └─────────┘2. 核心功能功能 说明路由 根据路径/Host/Header转发到不同服务限流 令牌桶/漏桶防止流量突增鉴权 API Key、JWT认证负载均衡 轮询、随机、加权插件 可扩展架构---二、完整代码实现1. 基础数据结构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 host[32];int port;int weight;int healthy;int connection_count;time_t last_check;struct service_instance *next;} service_instance_t;// 服务typedef struct service {char name[64];service_instance_t *instances;int instance_count;int lb_algorithm; // 0: round-robin, 1: random, 2: weightedint current_index;pthread_mutex_t mutex;struct service *next;} service_t;// 路由typedef struct route {char path[128];char host[64];char service_name[64];int strip_path;char rewrite_path[128];int priority;struct route *next;} route_t;// 限流器typedef struct rate_limiter {char key[128];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 key[64];char consumer[64];int enabled;struct api_key *next;} api_key_t;// 插件上下文typedef struct plugin_context {char name[64];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 method[16];char uri[1024];char path[1024];char query[512];char version[16];char headers[MAX_HEADERS][512];int header_count;char body[BUFFER_SIZE];int body_len;char client_ip[32];char host[256];} http_request_t;// HTTP响应typedef struct http_response {int status_code;char headers[MAX_HEADERS][512];int header_count;char body[BUFFER_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_threads[10];} api_gateway_t;2. 路由管理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_path[0] \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);}3. 负载均衡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-Robinint 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: { // Randomint 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: { // Weightedint 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;}4. 限流器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;}5. 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_req[BUFFER_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_start[0] ? 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 buffer[BUFFER_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;}buffer[n] \0;// 解析响应简化resp-status_code 200;strcpy(resp-body, buffer);resp-body_len n;return 0;}6. 测试代码cvoid 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次请求, rate5/s):\n);int allowed 0;for (int i 0; i 10; i) {if (rate_limiter_allow(rl)) allowed;printf( 请求%d: %s\n, i1, 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;}---三、编译和运行bashgcc -o api_gateway api_gateway.c -lpthread./api_gateway---四、Kong vs 本实现特性 本实现 Kong路由 ✅ 基础 ✅ 高级负载均衡 ✅ ✅限流 ✅ 令牌桶 ✅ 多种认证 ❌ ✅ 多种插件系统 ❌ ✅ Lua数据库配置 ❌ ✅Admin API ❌ ✅---五、总结通过这篇文章你学会了· API网关的核心功能路由、负载均衡、限流· 路由匹配和服务发现· 负载均衡算法轮询、随机、加权· 令牌桶限流器· HTTP请求转发API网关是微服务架构的统一入口。掌握它你就理解了Kong、Spring Cloud Gateway的底层设计。下一篇预告《从零实现一个分布式配置中心Apollo的核心设计》---评论区分享一下你对API网关的理解