从零实现一个服务网格:Sidecar与流量管理

前言

你有没有想过:在Kubernetes中,Istio是怎么做到无侵入地实现服务发现、负载均衡、熔断降级、灰度发布的?

服务网格(Service Mesh)通过注入Sidecar代理,劫持所有服务间流量,在不修改业务代码的情况下实现流量治理。

今天我们用C语言从零实现一个服务网格:

· Sidecar代理(透明代理)

· 服务发现和负载均衡

· 熔断器(Circuit Breaker)

· 重试和超时控制

· 灰度发布(金丝雀发布)

· 流量镜像


一、服务网格核心原理

  1. 架构图

```

┌─────────────────────────────────────────────────────────────┐

│ Kubernetes Pod │

│ ┌─────────────┐ ┌─────────────┐ │

│ │ 服务容器 │◄───────►│ Sidecar │ │

│ │ (业务代码) │ local │ (代理) │ │

│ └─────────────┘ └──────┬──────┘ │

│ │ │

└─────────────────────────────────┼──────────────────────────┘

┌─────────────────┐

│ 控制平面 │

│ (Pilot/配置) │

└─────────────────┘

```

  1. 核心功能

功能 说明

透明代理 劫持进出流量,业务无感知

服务发现 从注册中心获取服务列表

负载均衡 轮询/随机/加权/一致性哈希

熔断 故障隔离,防止级联故障

重试 失败自动重试

灰度发布 按比例分流到新版本

流量镜像 复制流量到测试环境


二、完整代码实现

  1. 基础数据结构

```c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <pthread.h>

#include <time.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <errno.h>

#include <signal.h>

#include <fcntl.h>

#include <sys/epoll.h>

#define MAX_SERVICES 100

#define MAX_INSTANCES 100

#define MAX_CONNECTIONS 10000

#define BUFFER_SIZE 65536

// 服务实例

typedef struct service_instance {

char service_name64;

char host32;

int port;

int weight;

int healthy;

int consecutive_errors;

time_t last_heartbeat;

struct service_instance *next;

} service_instance_t;

// 服务列表

typedef struct service_list {

char name64;

service_instance_t *instances;

int instance_count;

int current_index;

pthread_mutex_t mutex;

struct service_list *next;

} service_list_t;

// 熔断器状态

typedef enum {

CIRCUIT_CLOSED, // 正常

CIRCUIT_OPEN, // 熔断打开

CIRCUIT_HALF_OPEN // 半开(探测)

} circuit_state_t;

// 熔断器

typedef struct circuit_breaker {

char service_name64;

circuit_state_t state;

int failure_threshold; // 失败阈值

int success_threshold; // 成功阈值(半开→关闭)

int timeout_ms; // 超时时间

int failures; // 当前失败计数

int successes; // 当前成功计数(半开状态)

time_t last_failure_time;

time_t open_time;

pthread_mutex_t mutex;

struct circuit_breaker *next;

} circuit_breaker_t;

// Sidecar配置

typedef struct sidecar_config {

char service_name64;

char listen_host32;

int listen_port;

char control_plane_host32;

int control_plane_port;

int enable_circuit_breaker;

int enable_retry;

int max_retries;

int retry_delay_ms;

int connect_timeout_ms;

int read_timeout_ms;

} sidecar_config_t;

// Sidecar实例

typedef struct sidecar {

sidecar_config_t config;

service_list_t *services;

circuit_breaker_t *breakers;

int epoll_fd;

int running;

pthread_mutex_t mutex;

} sidecar_t;

```

  1. 配置管理

```c

// 加载配置

sidecar_t *sidecar_create(const char *config_file) {

sidecar_t *sc = malloc(sizeof(sidecar_t));

memset(sc, 0, sizeof(sidecar_t));

// 默认配置

strcpy(sc->config.service_name, "my-service");

strcpy(sc->config.listen_host, "0.0.0.0");

sc->config.listen_port = 8080;

strcpy(sc->config.control_plane_host, "127.0.0.1");

sc->config.control_plane_port = 9090;

sc->config.enable_circuit_breaker = 1;

sc->config.enable_retry = 1;

sc->config.max_retries = 3;

sc->config.retry_delay_ms = 100;

sc->config.connect_timeout_ms = 1000;

sc->config.read_timeout_ms = 3000;

sc->services = NULL;

sc->breakers = NULL;

sc->running = 1;

pthread_mutex_init(&sc->mutex, NULL);

// 创建epoll

sc->epoll_fd = epoll_create(MAX_CONNECTIONS);

printf("Sidecar启动: %s on %s:%d\n",

sc->config.service_name, sc->config.listen_host, sc->config.listen_port);

return sc;

}

// 从控制平面更新服务列表

void sidecar_update_services(sidecar_t *sc, const char *service_name,

char **hosts, int *ports, int *weights, int count) {

pthread_mutex_lock(&sc->mutex);

service_list_t *sl = sc->services;

while (sl) {

if (strcmp(sl->name, service_name) == 0) break;

sl = sl->next;

}

if (!sl) {

sl = malloc(sizeof(service_list_t));

strcpy(sl->name, service_name);

sl->instances = NULL;

sl->instance_count = 0;

sl->current_index = 0;

pthread_mutex_init(&sl->mutex, NULL);

sl->next = sc->services;

sc->services = sl;

}

pthread_mutex_lock(&sl->mutex);

// 清除旧实例

service_instance_t *inst = sl->instances;

while (inst) {

service_instance_t *next = inst->next;

free(inst);

inst = next;

}

sl->instances = NULL;

sl->instance_count = 0;

// 添加新实例

for (int i = 0; i < count; i++) {

service_instance_t *new_inst = malloc(sizeof(service_instance_t));

strcpy(new_inst->service_name, service_name);

strcpy(new_inst->host, hostsi);

new_inst->port = portsi;

new_inst->weight = weights ? weightsi : 100;

new_inst->healthy = 1;

new_inst->consecutive_errors = 0;

new_inst->last_heartbeat = time(NULL);

new_inst->next = sl->instances;

sl->instances = new_inst;

sl->instance_count++;

}

pthread_mutex_unlock(&sl->mutex);

pthread_mutex_unlock(&sc->mutex);

printf("更新服务 %s: %d个实例\n", service_name, count);

}

```

  1. 负载均衡

```c

// 负载均衡算法

typedef enum {

LB_ROUND_ROBIN,

LB_RANDOM,

LB_WEIGHTED,

LB_LEAST_CONN,

LB_CONSISTENT_HASH

} lb_algorithm_t;

// 选择实例(轮询)

service_instance_t *lb_round_robin(service_list_t *sl) {

pthread_mutex_lock(&sl->mutex);

service_instance_t *healthy_instances100;

int count = 0;

service_instance_t *inst = sl->instances;

while (inst) {

if (inst->healthy) {

healthy_instancescount++ = inst;

}

inst = inst->next;

}

if (count == 0) {

pthread_mutex_unlock(&sl->mutex);

return NULL;

}

int idx = sl->current_index % count;

sl->current_index++;

service_instance_t *selected = healthy_instancesidx;

pthread_mutex_unlock(&sl->mutex);

return selected;

}

// 选择实例(加权随机)

service_instance_t *lb_weighted(service_list_t *sl) {

pthread_mutex_lock(&sl->mutex);

int total_weight = 0;

service_instance_t *inst = sl->instances;

while (inst) {

if (inst->healthy) {

total_weight += inst->weight;

}

inst = inst->next;

}

if (total_weight == 0) {

pthread_mutex_unlock(&sl->mutex);

return NULL;

}

int r = rand() % total_weight;

inst = sl->instances;

while (inst) {

if (inst->healthy) {

r -= inst->weight;

if (r < 0) {

pthread_mutex_unlock(&sl->mutex);

return inst;

}

}

inst = inst->next;

}

pthread_mutex_unlock(&sl->mutex);

return NULL;

}

// 选择实例(一致性哈希)

service_instance_t *lb_consistent_hash(service_list_t *sl, const char *key) {

// 简化版:使用key的哈希值选择

uint32_t hash = 5381;

const char *p = key;

while (*p) {

hash = ((hash << 5) + hash) + *p++;

}

pthread_mutex_lock(&sl->mutex);

service_instance_t *healthy_instances100;

int count = 0;

service_instance_t *inst = sl->instances;

while (inst) {

if (inst->healthy) {

healthy_instancescount++ = inst;

}

inst = inst->next;

}

if (count == 0) {

pthread_mutex_unlock(&sl->mutex);

return NULL;

}

int idx = hash % count;

service_instance_t *selected = healthy_instancesidx;

pthread_mutex_unlock(&sl->mutex);

return selected;

}

```

  1. 熔断器

```c

// 创建熔断器

circuit_breaker_t *create_circuit_breaker(const char *service_name) {

circuit_breaker_t *cb = malloc(sizeof(circuit_breaker_t));

strcpy(cb->service_name, service_name);

cb->state = CIRCUIT_CLOSED;

cb->failure_threshold = 5;

cb->success_threshold = 3;

cb->timeout_ms = 5000;

cb->failures = 0;

cb->successes = 0;

cb->last_failure_time = 0;

cb->open_time = 0;

pthread_mutex_init(&cb->mutex, NULL);

return cb;

}

// 获取熔断器

circuit_breaker_t *get_circuit_breaker(sidecar_t *sc, const char *service_name) {

pthread_mutex_lock(&sc->mutex);

circuit_breaker_t *cb = sc->breakers;

while (cb) {

if (strcmp(cb->service_name, service_name) == 0) {

pthread_mutex_unlock(&sc->mutex);

return cb;

}

cb = cb->next;

}

// 创建新的熔断器

cb = create_circuit_breaker(service_name);

cb->next = sc->breakers;

sc->breakers = cb;

pthread_mutex_unlock(&sc->mutex);

return cb;

}

// 检查熔断器状态

int circuit_breaker_allow(circuit_breaker_t *cb) {

pthread_mutex_lock(&cb->mutex);

int allow = 0;

switch (cb->state) {

case CIRCUIT_CLOSED:

allow = 1;

break;

case CIRCUIT_OPEN:

// 检查是否超时,超时则进入半开状态

if (time(NULL) - cb->open_time > cb->timeout_ms / 1000) {

cb->state = CIRCUIT_HALF_OPEN;

cb->successes = 0;

allow = 1;

} else {

allow = 0;

}

break;

case CIRCUIT_HALF_OPEN:

allow = 1;

break;

}

pthread_mutex_unlock(&cb->mutex);

return allow;

}

// 记录调用结果

void circuit_breaker_record(circuit_breaker_t *cb, int success) {

pthread_mutex_lock(&cb->mutex);

switch (cb->state) {

case CIRCUIT_CLOSED:

if (success) {

cb->failures = 0;

} else {

cb->failures++;

cb->last_failure_time = time(NULL);

if (cb->failures >= cb->failure_threshold) {

cb->state = CIRCUIT_OPEN;

cb->open_time = time(NULL);

printf("熔断器打开: %s\n", cb->service_name);

}

}

break;

case CIRCUIT_HALF_OPEN:

if (success) {

cb->successes++;

if (cb->successes >= cb->success_threshold) {

cb->state = CIRCUIT_CLOSED;

cb->failures = 0;

printf("熔断器关闭: %s\n", cb->service_name);

}

} else {

cb->state = CIRCUIT_OPEN;

cb->open_time = time(NULL);

printf("熔断器重新打开: %s\n", cb->service_name);

}

break;

case CIRCUIT_OPEN:

break;

}

pthread_mutex_unlock(&cb->mutex);

}

```

  1. 代理转发

```c

// 转发请求到目标服务

int forward_request(sidecar_t *sc, const char *service_name,

const char *data, int data_len,

char *response, int *response_len,

const char *client_id) {

// 1. 获取服务列表

service_list_t *sl = sc->services;

while (sl) {

if (strcmp(sl->name, service_name) == 0) break;

sl = sl->next;

}

if (!sl) {

strcpy(response, "Service not found");

*response_len = strlen(response);

return -1;

}

// 2. 检查熔断器

circuit_breaker_t *cb = NULL;

if (sc->config.enable_circuit_breaker) {

cb = get_circuit_breaker(sc, service_name);

if (!circuit_breaker_allow(cb)) {

strcpy(response, "Circuit breaker open");

*response_len = strlen(response);

return -1;

}

}

// 3. 负载均衡选择实例

service_instance_t *inst = lb_round_robin(sl);

if (!inst) {

strcpy(response, "No healthy instances");

*response_len = strlen(response);

return -1;

}

// 4. 建立连接并转发

int target_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);

// 设置超时

struct timeval tv;

tv.tv_sec = sc->config.connect_timeout_ms / 1000;

tv.tv_usec = (sc->config.connect_timeout_ms % 1000) * 1000;

setsockopt(target_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

setsockopt(target_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));

int ret = connect(target_fd, (struct sockaddr*)&addr, sizeof(addr));

if (ret < 0) {

close(target_fd);

if (cb) circuit_breaker_record(cb, 0);

strcpy(response, "Connect failed");

*response_len = strlen(response);

return -1;

}

// 发送请求

send(target_fd, data, data_len, 0);

// 接收响应(支持重试)

int success = 0;

int retries = sc->config.enable_retry ? sc->config.max_retries : 1;

for (int i = 0; i < retries; i++) {

if (i > 0) {

usleep(sc->config.retry_delay_ms * 1000);

}

int n = recv(target_fd, response, BUFFER_SIZE - 1, 0);

if (n > 0) {

*response_len = n;

responsen = '\0';

success = 1;

break;

}

}

close(target_fd);

// 记录熔断器状态

if (cb) circuit_breaker_record(cb, success);

return success ? 0 : -1;

}

```

  1. 灰度发布

```c

// 灰度规则

typedef struct canary_rule {

char service_name64;

char version16;

int weight; // 流量比例 0-100

char header_name64; // 按header路由

char header_value64;

struct canary_rule *next;

} canary_rule_t;

typedef struct canary_config {

canary_rule_t *rules;

pthread_mutex_t mutex;

} canary_config_t;

// 根据灰度规则选择版本

service_instance_t *select_canary_instance(service_list_t *sl, canary_config_t *canary,

const char *client_id, const char *headers) {

pthread_mutex_lock(&canary->mutex);

canary_rule_t *rule = canary->rules;

while (rule) {

if (strcmp(rule->service_name, sl->name) == 0) {

// 检查header匹配

if (rule->header_name0 && rule->header_value0) {

char *header_start = strstr(headers, rule->header_name);

if (header_start) {

char *value_start = strchr(header_start, ':');

if (value_start) {

value_start++;

while (*value_start == ' ') value_start++;

if (strncmp(value_start, rule->header_value, strlen(rule->header_value)) == 0) {

// header匹配,使用该版本

service_instance_t *inst = sl->instances;

while (inst) {

if (strstr(inst->host, rule->version)) {

pthread_mutex_unlock(&canary->mutex);

return inst;

}

inst = inst->next;

}

}

}

}

}

// 按权重分流

if (rule->weight > 0) {

if ((rand() % 100) < rule->weight) {

service_instance_t *inst = sl->instances;

while (inst) {

if (strstr(inst->host, rule->version)) {

pthread_mutex_unlock(&canary->mutex);

return inst;

}

inst = inst->next;

}

}

}

}

rule = rule->next;

}

pthread_mutex_unlock(&canary->mutex);

// 默认版本(稳定版)

service_instance_t *inst = sl->instances;

while (inst) {

if (strstr(inst->host, "stable")) {

return inst;

}

inst = inst->next;

}

return sl->instances;

}

```

  1. 流量镜像

```c

// 流量镜像配置

typedef struct mirror_config {

char service_name64;

char mirror_target64;

int mirror_port;

int mirror_rate; // 镜像比例 0-100

struct mirror_config *next;

} mirror_config_t;

// 镜像请求

void mirror_request(const char *service_name, const char *data, int data_len,

mirror_config_t *mirrors) {

mirror_config_t *m = mirrors;

while (m) {

if (strcmp(m->service_name, service_name) == 0) {

if ((rand() % 100) < m->mirror_rate) {

// 异步发送到镜像目标(不阻塞主流程)

int fd = socket(AF_INET, SOCK_STREAM, 0);

struct sockaddr_in addr;

addr.sin_family = AF_INET;

addr.sin_port = htons(m->mirror_port);

inet_pton(AF_INET, m->mirror_target, &addr.sin_addr);

if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) {

// 添加镜像标识

char mirror_dataBUFFER_SIZE;

snprintf(mirror_data, sizeof(mirror_data),

"X-Mirror: true\r\n%s", data);

send(fd, mirror_data, strlen(mirror_data), 0);

}

close(fd);

}

}

m = m->next;

}

}

```

  1. 主循环

```c

// Sidecar主循环

void sidecar_run(sidecar_t *sc) {

int server_fd = socket(AF_INET, SOCK_STREAM, 0);

int opt = 1;

setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

struct sockaddr_in addr;

addr.sin_family = AF_INET;

addr.sin_addr.s_addr = INADDR_ANY;

addr.sin_port = htons(sc->config.listen_port);

bind(server_fd, (struct sockaddr*)&addr, sizeof(addr));

listen(server_fd, 128);

// 添加到epoll

struct epoll_event ev;

ev.events = EPOLLIN;

ev.data.fd = server_fd;

epoll_ctl(sc->epoll_fd, EPOLL_CTL_ADD, server_fd, &ev);

printf("Sidecar代理运行中: %s:%d\n",

sc->config.listen_host, sc->config.listen_port);

struct epoll_event eventsMAX_CONNECTIONS;

while (sc->running) {

int nfds = epoll_wait(sc->epoll_fd, events, MAX_CONNECTIONS, 100);

for (int i = 0; i < nfds; i++) {

int fd = eventsi.data.fd;

if (fd == server_fd) {

// 新连接

int client_fd = accept(server_fd, NULL, NULL);

if (client_fd < 0) continue;

// 接收请求

char requestBUFFER_SIZE;

int n = recv(client_fd, request, sizeof(request) - 1, 0);

if (n <= 0) {

close(client_fd);

continue;

}

requestn = '\0';

// 解析服务名(从请求头或路径)

// 简化: 从路径提取 /service/xxx

char service_name64 = "default";

char *service_start = strstr(request, "/service/");

if (service_start) {

service_start += 9;

char *service_end = strchr(service_start, ' ');

if (service_end) {

int len = service_end - service_start;

if (len < 64) {

strncpy(service_name, service_start, len);

service_namelen = '\0';

}

}

}

// 转发请求

char responseBUFFER_SIZE;

int response_len = 0;

int ret = forward_request(sc, service_name,

request, n,

response, &response_len,

NULL);

if (ret == 0) {

send(client_fd, response, response_len, 0);

} else {

// 错误响应

char error_resp512;

snprintf(error_resp, sizeof(error_resp),

"HTTP/1.1 503 Service Unavailable\r\n"

"Content-Type: text/plain\r\n\r\n%s",

response);

send(client_fd, error_resp, strlen(error_resp), 0);

}

close(client_fd);

}

}

}

close(server_fd);

}

```


三、测试代码

```c

int main() {

printf("=== 服务网格 Sidecar 测试 ===\n\n");

srand(time(NULL));

// 创建Sidecar

sidecar_t *sc = sidecar_create(NULL);

// 模拟从控制平面获取服务列表

char *hosts\[\] = {"127.0.0.1", "127.0.0.1", "127.0.0.1"};

int ports\[\] = {9001, 9002, 9003};

int weights\[\] = {100, 100, 100};

sidecar_update_services(sc, "user-service", hosts, ports, weights, 3);

sidecar_update_services(sc, "order-service", hosts, ports, weights, 2);

// 启动Sidecar

printf("\n启动Sidecar代理...\n");

sidecar_run(sc);

return 0;

}

```


四、编译和运行

```bash

gcc -o sidecar sidecar.c -lpthread

./sidecar

```

输出示例:

```

=== 服务网格 Sidecar 测试 ===

Sidecar启动: my-service on 0.0.0.0:8080

更新服务 user-service: 3个实例

更新服务 order-service: 2个实例

启动Sidecar代理...

Sidecar代理运行中: 0.0.0.0:8080

```


五、总结

通过这篇文章,你学会了:

· 服务网格的核心原理(Sidecar + 控制平面)

· 透明代理实现

· 服务发现和负载均衡

· 熔断器(三种状态转换)

· 重试和超时控制

· 灰度发布(按权重/header分流)

· 流量镜像

服务网格是云原生的核心技术。掌握它,你就理解了Istio、Linkerd的底层设计。

下一篇预告:《从零实现一个API网关:路由与限流》


评论区分享一下你对服务网格的理解~