前言
你有没有想过:在Kubernetes中,Istio是怎么做到无侵入地实现服务发现、负载均衡、熔断降级、灰度发布的?
服务网格(Service Mesh)通过注入Sidecar代理,劫持所有服务间流量,在不修改业务代码的情况下实现流量治理。
今天我们用C语言从零实现一个服务网格:
· Sidecar代理(透明代理)
· 服务发现和负载均衡
· 熔断器(Circuit Breaker)
· 重试和超时控制
· 灰度发布(金丝雀发布)
· 流量镜像
一、服务网格核心原理
- 架构图
```
┌─────────────────────────────────────────────────────────────┐
│ Kubernetes Pod │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 服务容器 │◄───────►│ Sidecar │ │
│ │ (业务代码) │ local │ (代理) │ │
│ └─────────────┘ └──────┬──────┘ │
│ │ │
└─────────────────────────────────┼──────────────────────────┘
│
▼
┌─────────────────┐
│ 控制平面 │
│ (Pilot/配置) │
└─────────────────┘
```
- 核心功能
功能 说明
透明代理 劫持进出流量,业务无感知
服务发现 从注册中心获取服务列表
负载均衡 轮询/随机/加权/一致性哈希
熔断 故障隔离,防止级联故障
重试 失败自动重试
灰度发布 按比例分流到新版本
流量镜像 复制流量到测试环境
二、完整代码实现
- 基础数据结构
```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;
```
- 配置管理
```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);
}
```
- 负载均衡
```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;
}
```
- 熔断器
```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);
}
```
- 代理转发
```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;
}
```
- 灰度发布
```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;
}
```
- 流量镜像
```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;
}
}
```
- 主循环
```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网关:路由与限流》
评论区分享一下你对服务网格的理解~