You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:基于Apache mod_slotmem_shm的跨Worker共享内存缓存POC实现

使用Apache mod_slotmem_shm实现跨Worker进程共享内存缓存POC指南

一、mod_slotmem_shm的初始化与配置

1. 模块加载

先确认mod_slotmem_shm已安装,在Apache配置文件(httpd.conf或conf.d子目录下的配置文件)中添加加载指令:

LoadModule slotmem_shm_module modules/mod_slotmem_shm.so

注意:模块路径需匹配你的Apache安装环境,比如CentOS通常为/usr/lib64/httpd/modules/mod_slotmem_shm.so,Ubuntu为/usr/lib/apache2/modules/mod_slotmem_shm.so。

2. 共享内存段配置

用SlotMemShm指令定义共享内存区域,参数依次为内存段名称、总大小、单个slot大小、slot总数:

SlotMemShm my_shared_cache 102400 1024 100
# 解释:创建名为my_shared_cache的内存段,总容量100KB,每个slot占1KB,共100个slot

将配置放入主配置文件或虚拟主机配置块,重启Apache生效。

二、写入共享内存的代码实现(Apache模块开发方式)

mod_slotmem_shm仅支持Apache模块级调用,需编写自定义模块实现数据写入:

1. 模块核心代码

#include <httpd.h>
#include <http_config.h>
#include <http_protocol.h>
#include <ap_slotmem.h>

static ap_slotmem_instance_t *slotmem = NULL;

// 模块初始化:加载共享内存段
static int my_cache_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) {
    slotmem = ap_slotmem_create(p, "my_shared_cache", 0, 0, APR_SHM_NOSYNC);
    if (!slotmem) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "Failed to initialize shared memory segment");
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    return OK;
}

// 写入数据的请求处理器
static int write_cache_handler(request_rec *r) {
    if (!r->handler || strcmp(r->handler, "write_cache") != 0) {
        return DECLINED;
    }
    if (!slotmem) {
        ap_rprintf(r, "Shared memory not initialized");
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    // 待写入的数据(需保证长度不超过单个slot大小)
    const char *data = "Cross-worker shared data!";
    apr_size_t data_len = strlen(data) + 1; // 包含字符串终止符

    // 加锁避免多进程竞争
    apr_status_t rv = ap_slotmem_lock(slotmem);
    if (rv != APR_SUCCESS) {
        ap_rprintf(r, "Failed to lock shared memory");
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    // 获取slot 0的指针并写入数据
    void *slot_ptr;
    rv = ap_slotmem_get(slotmem, &slot_ptr, 0);
    if (rv == APR_SUCCESS) {
        memcpy(slot_ptr, data, data_len);
        ap_rprintf(r, "Data written to slot 0 successfully");
    } else {
        ap_rprintf(r, "Failed to access slot 0");
    }

    ap_slotmem_unlock(slotmem); // 解锁
    return OK;
}

// 注册模块钩子与处理器
static void register_hooks(apr_pool_t *p) {
    ap_hook_post_config(my_cache_init, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_handler(write_cache_handler, NULL, NULL, APR_HOOK_MIDDLE);
}

module AP_MODULE_DECLARE_DATA my_cache_module = {
    STANDARD20_MODULE_STUFF,
    NULL, NULL, NULL, NULL, NULL, register_hooks
};

2. 编译与配置

用apxs工具编译模块:

apxs -c -i my_cache_module.c

编译完成后,在Apache配置文件中加载自定义模块:

LoadModule my_cache_module modules/mod_my_cache.so

添加触发写入的路径配置:

<Location "/write-cache">
    SetHandler write_cache
</Location>

重启Apache后,访问http://你的服务器地址/write-cache即可完成数据写入。

三、跨Worker进程读取共享内存的方法

在上述自定义模块中添加读取处理器:

1. 读取处理器代码

// 读取数据的请求处理器
static int read_cache_handler(request_rec *r) {
    if (!r->handler || strcmp(r->handler, "read_cache") != 0) {
        return DECLINED;
    }
    if (!slotmem) {
        ap_rprintf(r, "Shared memory not initialized");
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    apr_status_t rv = ap_slotmem_lock(slotmem);
    if (rv != APR_SUCCESS) {
        ap_rprintf(r, "Failed to lock shared memory");
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    void *slot_ptr;
    rv = ap_slotmem_get(slotmem, &slot_ptr, 0);
    if (rv == APR_SUCCESS) {
        ap_rprintf(r, "Data from shared memory: %s", (char*)slot_ptr);
    } else {
        ap_rprintf(r, "Failed to read slot 0");
    }

    ap_slotmem_unlock(slotmem);
    return OK;
}

在register_hooks函数中注册该处理器:

ap_hook_handler(read_cache_handler, NULL, NULL, APR_HOOK_MIDDLE);

2. 读取路径配置

<Location "/read-cache">
    SetHandler read_cache
</Location>

重启Apache后,访问http://你的服务器地址/read-cache即可读取共享内存中的数据。

四、关键配置要点与注意事项

  • 锁机制强制要求:必须使用ap_slotmem_lock/ap_slotmem_unlock保证多进程/线程下的数据一致性,否则会出现脏读、数据损坏问题。
  • Slot大小适配:配置时需确保单个slot大小足够容纳待存储的数据,超出部分会被截断。
  • 内存段名称唯一:SlotMemShm定义的名称需全局唯一,避免与其他模块的共享内存段冲突。
  • 权限检查:Apache运行用户需拥有共享内存的读写权限,否则无法创建或访问内存段。
  • 复杂数据序列化:若存储结构体等复杂数据,需自行实现序列化/反序列化逻辑,共享内存仅存储二进制原始数据。
  • 异常清理:Apache正常停止时会自动释放共享内存,异常退出可能残留内存段,可通过ipcs查看、ipcrm命令清理。

五、POC有效性验证方法

  1. 查看当前Apache Worker进程:ps aux | grep httpd(Ubuntu为apache2)
  2. 访问/write-cache写入数据
  3. 手动杀掉当前处理请求的Worker进程,让Apache启动新Worker
  4. 访问/read-cache,若能读取到之前写入的数据,说明跨进程共享生效
  5. 用多客户端并发请求/read-cache,验证所有Worker均可读取到一致数据

内容的提问来源于stack exchange,提问作者TKS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 04:36:09