【问题标题】:What is the best way to run npm packages on demand as mircoservices without installing it locally?无需在本地安装即可按需将 npm 包作为 mircoservices 运行的最佳方法是什么?
【发布时间】:2017-10-04 21:58:48
【问题描述】:

假设我将这些 npm 包发布到 npm: service1@v1.0 service1@v2.0 service2@v1.0 每个包都有一个功能:

function run(extraStr) {
  return 'package_name_and_version' + extraStr; // i.e. service1 v1.0 extraStr
}

我想编写使用包而不在本地安装的 nodejs 代码

var server = require("my-server-sdk");
  // get(package_name, version, function_in_package, arguments, callback)
  server.get('service1', '2.0', 'run', ['app1'], (err, result) => {
  console.log(result); // this should print service1 v2.0 app1
});

my-server-sdk 是一个 sdk,它与我的服务器的 api 接口,它安装所需的包并将其缓存以供以后使用。 最好的方法是什么?什么安全问题以及如何预防?

这是我想要的简单图表

注意:service1@v1.0 service1@v2.0 service2@v1.0 只是 npm 中任何包的示例,即lodash


缓存示例:

假设我们的 TTL 等于 60 分钟

client1 在 01:00 向 lodash 请求了一个函数,并从 underscore 请求了另一个函数。 现在在服务器lodashunderscore 中安装了时间戳01:00

client201:30underscore 请求了一个函数,该函数会立即使用,因为之前已安装 underscore,但它的时间戳已更新为 1 :30.

02:01 lodash 被删除,因为它没有在过去的 TTL currenttime - lodash_timestamp > TTL 上使用,但 underscore 仍然存在,因为 currenttime - underscore_timestamp < TTL

因此,当 client302:30 请求 lodash 时,它会再次以 02:30 作为 timestamp 获得 intsalled .

【问题讨论】:

  • 我不确定我是否理解您要解决的问题。 NPM 已经为您处理了版本控制。 require() 缓存。为什么不想在本地安装 SDK?您要问什么样的安全问题?
  • @Brad 我想将 npm 包用作微服务而不在本地安装它,我唯一想安装的是与我的服务器连接以运行微服务的 SDK。安全问题,例如调用从服务器删除文件的函数(我希望每个包都在沙箱中运行)
  • 我还是不明白你到底想做什么。您的 SDK 可以只是您的服务的客户端。 SDK 与否,如果您不阻止人们删除您服务器上的内容,则可以通过直接点击您的服务来完成。如果要在本地运行代码,则必须拥有该代码。虽然您可以获取和评估该 JavaScript,但您正在为零收益创建不必要的复杂性。为什么它是否在磁盘上很重要?无论如何,有人可以将您的代码转储到磁盘上。而且,微服务客户端并没有隐藏任何东西......
  • 如果我理解你想告诉你的服务器“npm install MODULE”的问题,导入它,从这个模块运行一个特定的方法并返回结果。请对此提供一些反馈,以便我可以发布一些我想到的代码。
  • @alex-rokabilis 并注意我可以从同一个包中调用函数,但版本不同

标签: node.js npm microservices


【解决方案1】:

npmi 包为 npm install 提供了一个 API。

我会使用的逻辑是:

  1. 从 npm 获取特定的包和版本(如果尚未安装则安装)

  2. 需要nodejs里面的包

  3. 使用指定参数运行指定方法
  4. 将结果返回给客户端

var npmi = require('npmi');
var path = require('path');

function runModule(moduleName, moduleVersion, moduleMethod, moduleMethodParams) {

  return new Promise((resolve, reject) => {

    var options = {
      name: moduleName, // your module name 
      version: moduleVersion, // expected version [default: 'latest'] 
      forceInstall: false, // force install if set to true (even if already installed, it will do a reinstall) [default: false] 
      npmLoad: { // npm.load(options, callback): this is the "options" given to npm.load() 
        loglevel: 'silent' // [default: {loglevel: 'silent'}] 
      }
    };
    options.path = './' + options.name + "@" + options.version,
      npmi(options, function(err, result) {
        if (err) {
          if (err.code === npmi.LOAD_ERR) console.log('npm load error');
          else if (err.code === npmi.INSTALL_ERR) console.log('npm install error');
          console.log(err.message);
          return reject(err)
        }

        // installed 
        console.log(options.name + '@' + options.version + ' installed successfully in ' + path.resolve(options.path));

        var my_module = require(path.resolve(options.path, "node_modules", options.name))

        console.log("Running :", options.name + '@' + options.version)
        console.log("Method :", moduleMethod);
        console.log("With params :", ...moduleMethodParams)
        resolve(my_module[moduleMethod](...moduleMethodParams))
      });

  })

}

runModule('lodash', '4.10.0', 'fill', [Array(3), 2])
  .then(result => console.log("Result :", result))

runModule('lodash', '3.10.0', 'fill', [Array(3), 2])
  .then(result => console.log("Result :", result))

您现在可以看到有 2 个创建的文件夹 (lodash@3.10.0 , lodash@4.10.0) 指示包名称和版本。

我已经假设 npm 在路径中并且服务器有权在当前目录中安装软件包,并且 "MODULE_NAME@MODULE_VERSION" 是当前操作系统下的有效文件夹名称.

【讨论】:

  • 我喜欢这个,谢谢亚历克斯。您认为实现缓存系统的最佳方法是在 TTL 之前未使用的包被删除?
  • 我不明白。你能提供更多信息吗?或者举个例子会更好。
  • 将这种构建时逻辑拉入运行时有什么好处?
  • @timaschew 它实际上有很多好处:1-您可以跨不同的编程语言使用包,即python、java。 2- 如果您的包中有错误,您可以单独更新它,而不必担心每次更新包时都更新每个客户端 3- 将代码拆分为独立的微服务,便于单独测试每个部分并开发实时应用程序
  • @alex-rokabilis 我在问题中添加了缓存示例。我认为缓存在这种类型的系统中很重要,可以节省最少使用的包的空间,你怎么看?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-01
  • 2011-04-25
  • 1970-01-01
相关资源
最近更新 更多