第六部分:构建与测试
6.1 单元测试(Unity框架)
// tests/unit/test_sds.c
#include "unity.h"
#include "sds.h"
void setUp(void) {}
void tearDown(void) {}
void test_sds_new(void) {
sds str = sdsnew("Hello");
TEST_ASSERT_NOT_NULL(str);
TEST_ASSERT_EQUAL_STRING("Hello", str);
TEST_ASSERT_EQUAL(5, sdslen(str));
sdsfree(str);
}
void test_sds_cat(void) {
sds str = sdsnew("Hello");
str = sdscat(str, " World");
TEST_ASSERT_EQUAL_STRING("Hello World", str);
TEST_ASSERT_EQUAL(11, sdslen(str));
sdsfree(str);
}
void test_sds_cpy(void) {
sds str = sdsnew("Hello");
str = sdscpy(str, "Hi");
TEST_ASSERT_EQUAL_STRING("Hi", str);
TEST_ASSERT_EQUAL(2, sdslen(str));
sdsfree(str);
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_sds_new);
RUN_TEST(test_sds_cat);
RUN_TEST(test_sds_cpy);
return UNITY_END();
}
6.2 压力测试
// tests/benchmark/bench_cache.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>
#include <hiredis/hiredis.h>
#define THREADS 4
#define REQUESTS_PER_THREAD 1000000
#define HOST "127.0.0.1"
#define PORT 6379
typedef struct {
int thread_id;
long long requests;
long long successes;
long long total_time_us;
} bench_result;
void *bench_thread(void *arg) {
bench_result *result = (bench_result *)arg;
redisContext *c = redisConnect(HOST, PORT);
if (!c || c->err) {
printf("连接失败: %s\n", c ? c->errstr : "未知错误");
return NULL;
}
struct timeval start, end;
gettimeofday(&start, NULL);
for (int i = 0; i < REQUESTS_PER_THREAD; i++) {
// SET命令
char key[32], value[64];
snprintf(key, sizeof(key), "key:%d:%d", result->thread_id, i);
snprintf(value, sizeof(value), "value:%d:%d", result->thread_id, i);
redisReply *reply = redisCommand(c, "SET %s %s", key, value);
if (reply && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "OK") == 0) {
result->successes++;
}
freeReplyObject(reply);
// GET命令
reply = redisCommand(c, "GET %s", key);
if (reply && reply->type == REDIS_REPLY_STRING) {
result->successes++;
}
freeReplyObject(reply);
result->requests += 2;
}
gettimeofday(&end, NULL);
result->total_time_us = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
redisFree(c);
return NULL;
}
int main() {
pthread_t threads[THREADS];
bench_result results[THREADS];
for (int i = 0; i < THREADS; i++) {
results[i].thread_id = i;
results[i].requests = 0;
results[i].successes = 0;
results[i].total_time_us = 0;
pthread_create(&threads[i], NULL, bench_thread, &results[i]);
}
long long total_requests = 0;
long long total_successes = 0;
long long max_time_us = 0;
for (int i = 0; i < THREADS; i++) {
pthread_join(threads[i], NULL);
total_requests += results[i].requests;
total_successes += results[i].successes;
if (results[i].total_time_us > max_time_us) {
max_time_us = results[i].total_time_us;
}
}
double qps = (double)total_requests / (max_time_us / 1000000.0);
double success_rate = (double)total_successes / total_requests * 100;
printf("========== 压测结果 ==========\n");
printf("总请求数: %lld\n", total_requests);
printf("成功数: %lld\n", total_successes);
printf("成功率: %.2f%%\n", success_rate);
printf("QPS: %.0f\n", qps);
printf("平均延迟: %.2f us\n", max_time_us / (double)total_requests);
return 0;
}
第七部分:部署与运维
7.1 Systemd服务配置
# /etc/systemd/system/ccache.service
[Unit]
Description=C-Cache High Performance Memory Cache
After=network.target
Documentation=https://github.com/ccache/ccache
[Service]
Type=simple
User=ccache
Group=ccache
ExecStart=/usr/local/bin/ccache /etc/ccache/ccache.conf
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID
Restart=on-failure
RestartSec=5s
LimitNOFILE=65536
LimitMEMLOCK=infinity
# 安全加固
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=full
ProtectHome=yes
ReadWritePaths=/var/lib/ccache /var/log/ccache
[Install]
WantedBy=multi-user.target
7.2 Docker镜像构建
# Dockerfile
FROM alpine:3.18 AS builder
RUN apk add --no-cache gcc make musl-dev linux-headers
COPY . /src
WORKDIR /src
RUN make && make install
FROM alpine:3.18
RUN apk add --no-cache libgcc
COPY --from=builder /usr/local/bin/ccache /usr/local/bin/ccache
COPY --from=builder /etc/ccache/ccache.conf /etc/ccache/ccache.conf
RUN adduser -D -h /var/lib/ccache ccache
USER ccache
EXPOSE 6379
ENTRYPOINT ["/usr/local/bin/ccache"]
CMD ["/etc/ccache/ccache.conf"]
7.3 监控指标暴露
// src/monitor/metrics.c
#include <stdio.h>
#include "dict.h"
#include "atomic.h"
/* 性能计数器 */
static atomic64_t total_commands_processed;
static atomic64_t total_net_input_bytes;
static atomic64_t total_net_output_bytes;
static atomic64_t total_expired_keys;
static atomic64_t total_evicted_keys;
/* 获取统计信息 */
sds getInfo(sds info) {
info = sdscatprintf(info,
"# Server\r\n"
"redis_version:%s\r\n"
"os:%s\r\n"
"arch_bits:%d\r\n"
"process_id:%d\r\n"
"\r\n"
"# Clients\r\n"
"connected_clients:%d\r\n"
"\r\n"
"# Memory\r\n"
"used_memory:%zu\r\n"
"used_memory_human:%s\r\n"
"\r\n"
"# Stats\r\n"
"total_commands_processed:%lld\r\n"
"instantaneous_ops_per_sec:%lld\r\n"
"total_net_input_bytes:%lld\r\n"
"total_net_output_bytes:%lld\r\n"
"expired_keys:%lld\r\n"
"evicted_keys:%lld\r\n"
"\r\n",
CCACHE_VERSION,
getOS(),
sizeof(void*) * 8,
getpid(),
server.clients_count,
zmalloc_used_memory(),
bytesToHuman(mem_str, zmalloc_used_memory()),
atomic64_read(&total_commands_processed),
getInstantaneousOpsPerSec(),
atomic64_read(&total_net_input_bytes),
atomic64_read(&total_net_output_bytes),
atomic64_read(&total_expired_keys),
atomic64_read(&total_evicted_keys)
);
return info;
}
C语言企业级开发的关键不在于写出多么精巧的代码,而在于构建一套可持续维护、可扩展、高性能的工程体系。希望本文能够帮助你跨越"会写C语言"到"能开发企业级系统"之间的鸿沟。
来源:
https://xcfsr.cn/category/cloud.html