SDK and CLI for spawning streaming stateless HTTP microservices in multiple programming languages
Software Development Kit and Command Line Interface for spawning streaming stateless HTTP microservices for any programming language or arbitrary binary.
Think of it as serverless functions meets Unix Philosophy.
see: 100+ Working Service Examples
gcc
)At it's core, microcule
maps HTTP request response streams to the STDIN STDOUT streams of a function in any arbitrary programming language or any compiled binary. It's reminiscent of CGI, but utilizes additional STDIO streams, does not attempt to parse STDOUT for HTTP response methods, and ships with streaming plugins for extending your microservices. microcule is an old concept rethought and improved with the latest industry standard toolings.
If you are using Amazon Lambda or other cloud function hosting services like Google Functions or hook.io, you might find microcule
a very interesting option to remove your dependency on third-party cloud providers. microcule allows for local deployment of enterprise ready microservices. microcule has few dependencies and will run anywhere Node.js can run.
This project is the component which several production services, including hook.io, use to spawn real-time arbitrary streaming microservices in response to streaming HTTP requests. It's been battle-hardened with over two years of development and it's largest installation is now managing over 11,0000 microservices.
You are encouraged to use this module as-is, or modify it to suite your needs. If you are interested in contributing please let us know by opening a Pull Request.
Only require the functionality you need.
microcule
itself is actually just a collection of HTTP middleware Plugins presented as a CLI tool. This is essential, as all it's features and functionality are de-coupled with an industry standard API. You are encouraged to use the microcule
binary shipped with this project, or use microcule plugins programmatically in your existing application.
ls
, echo
, or tail
)microcule
can parse any kind of request data based on the incoming request's content-type
header and will always stream requests by default.
Even binary data works great! Here is an example of resizing in image in JavaScript or Bash.
microcule
binary for starting HTTP microservice serversecho
, ls
, and tail
as streaming HTTP microservicesmicrocule
ships with no container or OS virtualizationmicrocule
will work with any Container or Virtual Machine solutionsRead more about securing microcule
microcule
can be optionally extended through a simple app.use()
based plugin architecture. Plugins are standard Node.js Express.js middlewares. This means you can use any existing Node.js middleware as a microcule
plugin, or re-use any microcule
plugin as a middleware in any existing Node application.
Available Plugins
spawn
)For Express based plugins example, see: ./examples/express-plugins.js
Since plugins are standard Node.js middlewares, writing custom plugins is very easy.
microcule
supports 20+ programming languages. The best way to get started is to visit 100+ Microcule Examples.
Want to see a new language added? Simply open a pull request or open an issue. We are glad to add it!
npm install -g microcule
This will install the microcule
binary globally on your system.
Usage: microcule [command] [options]
Commands:
help Display help
Options:
-t, --timeout <number> Sets max timeout of service in milliseconds
-h, --host <value> Host to listen on
-p, --port <number> Port to listen on
-l, --language <value> Target programming languages
-w, --watch <bool> Reloads source files on every request ( dev only )
-v, --version Output the version number
By default, microcule
will attempt to start a listening HTTP server based on a microservice file path.
microcule ./path/to/scriptOrBinary.foo
Here can find many example microservices which can be run with microcule
These same examples are available as live services at hook.io/examples.
# mount any arbitrary command to a streaming HTTP endpoint
microcule echo "hello world"
microcule cat ReadMe.md
microcule tail ReadMe.md
# start HTTP servers with mounted streaming functions directly from source files
microcule ./examples/services/echo/echo.js
microcule ./examples/services/echo/echo-async-await.js
microcule ./examples/services/echo/echo.sh
microcule ./examples/services/echo/echo.c
microcule ./examples/services/echo/echo.go
microcule ./examples/services/hello-world/hello.java
microcule ./examples/services/echo/echo.lisp
microcule ./examples/services/echo/echo.lua
microcule ./examples/services/echo/echo.ml
microcule ./examples/services/echo/echo.php
microcule ./examples/services/echo/echo.pl
microcule ./examples/services/echo/echo.py
microcule ./examples/services/echo/echo-wsgi.py
microcule -l python3 ./examples/services/echo/echo-py3.py
microcule ./examples/services/echo/echo.r
microcule ./examples/services/echo/echo.rb
microcule ./examples/services/echo/echo.rs
microcule ./examples/services/echo/echo.coffee
microcule ./examples/services/echo/echo.ss
microcule ./examples/services/echo/echo.st
microcule ./examples/services/echo/echo.tcl
# pipe in data from arbitrary commands
echo "hello world" | microcule ./examples/services/echo/echo-stdin.js
ls | microcule ./examples/services/echo-stdin.js
ls | microcule ./examples/streams/transform.js
tail -f ReadMe.md | microcule --stream=true ./examples/services/streams/echo.js
# run full-features microservices as packages
git clone https://github.com/stackvana/microcule-examples
cd microcule-examples/javascript-echo
microcule .
see: microcule-examples for 100+ examples
Each call to microcule
will automatically start a listening HTTP server on port 3000
, additional instances of microcule
will auto-increment the port to 3001
, 3002
, etc.
Service target language is automatically detected based on the file extension of the service. This can be overridden using the --language
option.
Note: For certain languages ( such as Coffeescript ), the first microservice request to microcule
may take additional time as it will perform an initial compile and cache step.
microcule
is designed to work as set of standard Node.js HTTP middlewares. This is very useful and universal in that you can re-use any existing Node.js tooling ( like Express.js middlewares ) with any microcule plugins ( like spawn
or compile
).
see: ./examples
for more examples
node express-simple.js
var microcule = require('microcule');
var express = require('express');
var app = express();
var nodeService = function testService (opts) {
var res = opts.res;
console.log('logging to console');
res.json(opts.params);
};
var handler = microcule.plugins.spawn({
code: nodeService,
language: "javascript"
});
app.use(handler);
app.listen(3000, function () {
console.log('server started on port 3000');
});
Sometimes you may need to spawn a precompiled arbitrary binary instead of a script based microservice. microcule
supports two ways of spawning arbitrary binaries.
You can create a new bash
script and execute your binary in a bash sub-shell using microcule
's built-in support for Bash scripts.
Simply create a bash script and use microcule
to spawn it. This will work for any binary. Here is a simple curl example:
bash-curl-request.sh
curl --silent --data 'foo=bar&hello=there' http://hook.io/examples/echo
Then run:
microcule bash-curl-request.sh
This same example can be found at https://github.com/Stackvana/microcule-examples/tree/master/bash-curl-request
In some cases, creating a bash sub-shell is not ideal and you'll want to directly spawn your precompiled binary.
This is very easy, simple call microcule.spawn
using the bin
and argv
options. Here is an example of spawning echo
var handler = microcule.plugins.spawn({
bin: 'echo',
argv: ['hello', 'world']
});
Since v5.1.0
and above, microcule
is able to compose multiple functions together as middlewares to create composite functionality. Since every service is dealing with streaming http, it's easy to chain them in a row.
In order to chain multiple services, simply call them as standard Node.js middlewares in the order you want them to execute.
Note: You must specify the chain
parameter of spawn()
as true
, or else microcule will automatically end the response after the first middleware executes.
app.use([logger(), basicAuthHandler, bashServiceHandler, nodeServiceHandlerA, nodeServiceHandlerB], function (req, res) {
console.log("No services ended response, made it to end");
// It's good to have a catch-all handler at the end in case none the services ended the request
res.end('caught end')
});
For full example see: ./examples/express-chain-services.js
In some configurations you may want to safely run multiple kinds of microservices on one server instance ( a small monolith ). microcule
is designed exactly for this use case.
Since every incoming service request will spawn a separate process, microcule
can safely and easily handle spawning multiple types of microservices at once without affecting the state of other services.
If you look at the ./examples/http-server-simple.js
file, you will see that spawn()
can be used as a standard Node.js or Express HTTP middleware. For multiple services per server, simply map the spawn()
method to any custom routes you may want to define.
You can also stack multiple express
apps together for multiple microservices with separate routes. see: ./examples/express-multi-language.js
Additional language support is both planned and welcomed. Please open a Pull Request if you wish to see a specific language added
Creating a custom plugin is very simple. Just code the microcule plugin the same you would any other Node.js middleware. Feel free to use any of the other existing HTTP middlewares in the Node.js ecosystem.
custom-logger.js
module.exports = function loggerMiddleware (config) {
// here the function handler can be configured based on a `config` object
return function loggerHandler (req, res, next) {
console.log('running service ' + req.url);
next();
}
}
Once you've created a new plugin, simply require()
it, and call app.use(customLogger({}))
. That's it! There are no magic or surprises with how plugins work in microcule
.
See: ./examples/express-plugins.js
for more details.
If you wish to start HTTPS SSL enabled services, simply adjust the following configuration properties in ./config/index.js
{
http: {
https: true, // enables https / ssl, requires key, cert, ca
key: "ssl key as string",
cert: "ssl cert as string",
ca: "ssl ca as string",
sslRequired: false, // redirects all http traffic to https, optional
onlySSL: false // will only start https server with no unprotected http interface, optional
}
}
Running untrusted microservice code in a safe way is a complex problem. microcule
is only intended to isolate a small part of the entire untrusted source code execution chain.
If you intend to use this module to run untrusted source code please consider the following:
Every incoming HTTP request will spawn a new system process to run the microservice instance, which then sends data to the HTTP response. Every microservice execution will happen in a fresh systems process.
All errors that can possibly happen during the execution of a microservice should be trapped and isolated to not affect any other microservices.
microcule
cannot make any guarantees about the isolation of the server or spawned processes. All microservices will have default access to the server's file-system and child processes.
To ensure isolation of the server file-system, you would want to use the microcule
binary in a chroot
jail, or another similar solution like nsjail
.
To ensure isolation of the server memory and cpu, you will want to use the microcule
binary in a virtualized environment capable of monitoring and managing resource usage per process.
In order to Coffee-Script based microservices, you must install the following packages:
npm install coffee-script
In order to run Babel / ES6 / ES7 microservices, you must install the following packages:
npm install [email protected]
npm install [email protected]
npm install [email protected]
npm install [email protected]
npm install [email protected]
npm install [email protected]
Is your business using Microcule in production? Let us know by opening a pull request with your company's logo and website.
micro - a combining form with the meanings “small”
cule - indicating smallness
Author:
Special thanks to:
for their feedback in helping review early versions of this project.