Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何解决node进程间共享内存

如何解决node进程间共享内存

作者头像
用户2436820
发布于 2020-03-20 04:17:49
发布于 2020-03-20 04:17:49
2.8K00
代码可运行
举报
运行总次数:0
代码可运行

[toc]

npm i @runnersnail/cache-machine

利用rust帮助node进程间共享内存

业务场景:调用算法接口,算法5分钟后得到数据然后调用node接口返回数据,此时node接口接收数据并把数据缓存,用户端访问node无论哪个进程都可以得到被缓存的数据

将解决问题的思路和方法记录下来

遇到问题

由于部署平台对于node程序部署采用pm2(所有进程都是fork出来的,就不可能利用node那一套进程进程间通讯)

也曾经考虑自己实现一套cluster,然后利用master进程通讯。但pm2有其他优秀的功能宕机重启,cpu,内存监控等

分析问题

论坛请教有什么进程间通讯(受限于pm2)的方式,大部分的回答都是直接memcache、redis,感觉为了缓存某一轻量数据就上redis个人感觉没有太大意义,会造成资源浪费和部署麻烦。

解决问题

解决这个问题我们需要了解进程间有哪些通讯方式,才能寻找更好的解决方案。

详细了解请戳

  • 管道pipe:管道是一种半双工的通信方式,数据只能单向流动
  • 消息队列:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识
  • socket: 很常用的方式不再赘述
  • 共享存储SharedMemory: 映射一段可以被不同内存访问的地址块

为何采用shared memory帮助node共享内存

分析我们的业务场景,其实就是某一进程得到数据缓存到内存,然后其他进程可以无视跨进程读取缓存的数据块,说一shared memory是最适合的实用场景

如何使用shared memory 快速解决问题

node本身是不支持shared memeory这种底层操作的,我必须借助底层语言的能力去实现,然后通过ffi调用。为了避免自己实现原剩代码操作内存,我们需要借助一些三方成熟的包 所以我们需要完成以下三个事情

  • 选择一门系统语言
  • 寻找一个成熟的三方包共享内存
  • 寻找ffi工具快速完成
  • 这里系统语言我选择rust,如今前端火热的Deno项目采用rust编写,rust已经变的更靠近web社区
  • 选择Rust的第二个原因是它的三方包类似于npm一样容易集成,挑选shared memory模块 shared_memory-rs进行共享内存
  • 采用成熟的neon进行ffi模块编写

项目实施

使用neon脚手架搭建项目

  • neon new cache-machine ---》 创建项目
  • neon build ---》编译项目
  • node lib/index.js 运行项目

编写rust 模块

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
extern crate neon;
extern crate shared_memory;
use neon::prelude::*;
use neon::register_module;
use shared_memory::*;

use std::ffi::{CStr, CString};

/**
 * 定义缓存区块
*/
#[derive(SharedMemCast)]
struct ShmemStructCache {
    num_slaves: u32,
    message: [u8; 256],
}

static GLOBAL_LOCK_ID: usize = 0;

/**
 * sharedMemory全局句柄,避免对进程重复创建
*/
static mut SHMEM_GLOBAL: Option<shared_memory::SharedMem> = None;

/**
 * 创建sharedMemory
*/
fn create_open_mem() -> Result<shared_memory::SharedMem, SharedMemError> {
    let shmem = match SharedMem::create_linked("shared_mem.link", LockType::Mutex, 4096) {
        Ok(v) => v,
        Err(SharedMemError::LinkExists) => SharedMem::open_linked("shared_mem.link")?,
        Err(e) => return Err(e),
    };

    if shmem.num_locks() != 1 {
        return Err(SharedMemError::InvalidHeader);
    }
    Ok(shmem)
}

/**
 * 设置SharedMemory
*/
fn set_cache(set_cache: String) -> Result<String, SharedMemError> {
    {
        let mut  shared_state =  unsafe { SHMEM_GLOBAL.as_mut().unwrap().wlock::<ShmemStructCache>(GLOBAL_LOCK_ID)?};
        let set_string: CString = CString::new(set_cache.as_str()).unwrap();
        shared_state.message[0..set_string.to_bytes_with_nul().len()]
            .copy_from_slice(set_string.to_bytes_with_nul());
    }
    Ok("".to_owned())
}

/**
 * 读取SharedMemory
*/
fn get_cache() -> Result<String, SharedMemError> {
    let   result =
    {
        let shmem = unsafe { SHMEM_GLOBAL.as_mut().unwrap()};
        let shared_state = shmem.rlock::<ShmemStructCache>(GLOBAL_LOCK_ID)?;
        let shmem_str: &CStr = unsafe { CStr::from_ptr(shared_state.message.as_ptr() as *mut i8) };
         shmem_str.to_str().unwrap().into()
    };

    Ok(result)
}

/**
 * 暴露给js端get的方法
*/
fn get(mut cx: FunctionContext) -> JsResult<JsString> {
    match get_cache() {
        Ok(v) => Ok(cx.string(v)),
        Err(_) => Ok(cx.string("error")),
    }
}

/**
 * 暴露给js端的set方法
*/
fn set(mut cx: FunctionContext) -> JsResult<JsString> {
    let value = cx.argument::<JsString>(0)?.value();
    match set_cache(value) {
        Ok(v) => Ok(cx.string(v)),
        Err(e) => Ok(cx.string("error")),
    }
}

register_module!(mut m, {
  unsafe {
    SHMEM_GLOBAL = match create_open_mem() {
      Ok(v) => Some(v),
      _ => None,
    };
  }
  set_cache("".to_owned());
  m.export_function("get", get)?;
  m.export_function("set", set)?;
  Ok(())
});

编写js模块包

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var addon = require('../native');

/**
 * 
 * @param {缓存的键} key 
 * @param {缓存的值} value 
 */
function set(key, value) {
    let cache = get();
    cache[key] = value;
    addon.set(JSON.stringify(cache));
}

/**
 * 
 * @param {根据键名得到内容} key 
 */
function get(key) {
    const shared_memory = addon.get();
    if (shared_memory) {
        const cache = JSON.parse(cache)
        if (key) {
            return cache[key];
        } else {
            return cache;
        }

    } else {
        return {};
    }
}

module.exports = {
    set,
    get
}

// cache machine

var cache = require("cache-machine");

cache.set('key', 'value');

cache.get('key');

存在问题

rust端对不同进程做了访问控制,没有对线程做控制,考虑到node多线程场景[Worker Threads同时操作某变量]在实际业务中并未发现使用,所以后序增加线程间安全控制

  • 多进程安全的共享内存
  • 多线程安全的共享内存 TODO
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
webpack教程:如何从头开始设置 webpack 5
最近开源了一个 Vue 组件,还不够完善,欢迎大家来一起完善它,也希望大家能给个 star 支持一下,谢谢各位了。
前端小智@大迁世界
2020/11/24
2.5K0
webpack教程:如何从头开始设置 webpack 5
Webpack4教程 - 第二部分,使用loader处理scss,图片以及转换JS
今天继续我们的Webpack 4入门教程。在介绍了Webpack的基本概念之后,是时候更深入一点了。这次我们会涉及Webpack中非常强大的一个东西:loader。首先,我们会学习如何使用那些可用的loader。它将包括如何处理css、scss、图片以及对老版本的JavaScript语言的转换。让我们开始吧!
葡萄城控件
2018/09/14
9130
四大维度解锁webpack3笔记
在命令行输入webpack -h,成功就出现下图,有很多webpack命令可以看一看
FinGet
2019/06/28
1.1K0
四大维度解锁webpack3笔记
【One by one系列】一步步学习webpack打包
0配置,webpack4受Parcel打包工具启发,尽可能的让开发者运行项目的成本变低。webpack4不再强制需要webpack.config.js作为打包的入口配置文件,默认的入口为./src/和默认的出口./dist,小项目的福音。
DDGarfield
2022/06/23
4300
Webpack系列——手把手教你使用Webpack搭建简易的React开发环境
在这篇文章中我们开始利用我们之前所学搭建一个简易的React开发环境,用以巩固我们之前学习的Webpack知识。首先我们需要明确这次开发环境需要达到的效果:1、能够编译JSX语言 2、css样式使用Sass开发 3.能够将基础的ES6转化为ES5 4.能够使用ESLint在开发的时候为我们做代码风格审查
用户1515472
2019/07/24
2K0
Webpack系列——手把手教你使用Webpack搭建简易的React开发环境
Vue 07.webpack
webpack 是前端的一个项目构建工具,它是基于 Node.js 开发出来的一个前端工具;
LittlePanger
2020/04/14
8490
使用Webpack来做自己的cra脚手架
现如今的JavaScript已经出了ES6,ES7甚至许多更高的版本,但是有很多浏览器是不支持这些新的语法,所以需要通过Babel 来将你的新语法编译成浏览器可以理解的旧语法。这是通过 Babel/core模块和babel/perset-env插件完成的。当然Babel还有其他的转换功能。
学前端
2020/06/11
9520
使用Webpack来做自己的cra脚手架
09_Webpack打包工具
Webpack打包工具对项目中的复杂文件进行打包处理,可以实现项目的自动化构建,并且给前端开发人员带来了极大的便利。
张哥编程
2024/12/13
2170
09_Webpack打包工具
webpack配置
webpack 使用流程 1.创建文件目录 + direaction - dist - src + css + js + images + index.html + main.js 2.初始化项目 1 npm init -y | 文件目录 + direaction - dist - src + css + js + images +
yaoyaoah
2020/04/09
5710
webpack 入门教程
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
老马
2018/08/20
4.2K0
webpack 入门教程
从零开始配置webpack(基于webpack 4 和 babel 7版本)
webpack启动后会从 Entry 里配置的 Module 开始递归解析 Entry 依赖的所有Module.每找到一个Module,就会根据配置的Loader去找出对应的转换规则,对Module进行转换后,再解析出当前的Module依赖的Module.这些模块会以Entry为单位进行分组,一个Entry和其所有依赖的Module被分到一个组也就是一个Chunk。最好Webpack会把所有Chunk转换成文件输出。在整个流程中Webpack会在恰当的时机执行Plugin里定义的逻辑。
胡哥有话说
2019/09/12
6960
vue 学习笔记第四弹 - Webpack
webpack 是前端的一个项目构建工具,它是基于 Node.js 开发出来的一个前端工具;
syy
2020/04/07
9220
webpack从零搭建开发环境
为了方便也可以这么写,使用 npm run 命令这个命令执行的时候默认会把 node_modules 的.bin 文件放到全局上,执行之后销毁npm run buildnpm run dev
小丑同学
2020/09/21
1.3K0
webpack超详细教程!入门一篇就够了
webpack 是前端的一个项目构建工具,它是基于 Node.js 开发出来的一个前端工具;
beifengtz
2019/08/26
10K0
webpack超详细教程!入门一篇就够了
10天从入门到精通Vue(五)Webpack打包
webpack 是前端的一个项目构建工具,它是基于 Node.js 开发出来的一个前端工具;
共饮一杯无
2022/11/28
5330
10天从入门到精通Vue(五)Webpack打包
webpack快速构建项目
webpack是什么我在这里就不多说了,实在不知道的可以直接在去搜一下,都一大堆答案。关于用webpack怎么构建项目,方法也是多种多样,五花八门。今天,我就写下我平常构建项目的方式,这个方式我觉得比较便捷和简单粗暴,如果有什么要指出的,也欢迎大家评论,毕竟我也只是一个前端新人。
守候i
2018/08/22
8600
webpack快速构建项目
怎么用webpack搭建前端环境?
一、前端构建工具 grunt gulp webpack(主流,https://webpack.js.org/) Fis3(百度) 二、webpack是什么 webpack 是一个现代 JavaScript 应用程序的静态模块打包器 webpack稳定版本:v4.44 三、如何使用webpack搭建前端环境 安装node.js( v12.x) 注意:如果npm安装一些包由于网速原因,安装慢切换一下镜像源 改成淘宝镜像: npm config set registry https://registry.np
江一铭
2022/06/16
1.2K0
webpack基础探讨
本文作者:IMWeb zixinfeng 原文出处:IMWeb社区 未经同意,禁止转载 1. 使用webpack webpack命令使用 webpack --help (webpack -h) 查看所有的命令 webpack-v 打包命令 webpack [] 不适用webpack配置文件的时候 使用webpack配置文件, 直接webpack --config 指定配置文件 (默认配置文件名称 webpack.config.js或者 webpackfile.js) Basic Opt
IMWeb前端团队
2019/12/03
7600
Webpack4 常用配置详解
实现Webpack的打包最基本的就是配置好入口、出口,npm install webpack后在根目录创建webpack.config.js,代码如下:
EchoROne
2022/08/15
1.7K0
webpack5快发布了,你还没用过4吗?
webpack5 预计会在 2020 年年初发布,之前从 alpha 版本就有关注,本次重点更新在长期缓存,tree shakking 和 es6 打包这块。具体变更可以参考https://github.com/webpack/changelog-v5/blob/master/README.md。
前端森林
2020/04/23
1.6K0
webpack5快发布了,你还没用过4吗?
相关推荐
webpack教程:如何从头开始设置 webpack 5
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验