├── .gitignore ├── .idea ├── encodings.xml ├── micro-node-api-gateway.iml ├── misc.xml ├── modules.xml ├── vcs.xml └── workspace.xml ├── Microservices_Architecture.png ├── README.md ├── ServicesSetup.sh ├── ServicesStart.sh ├── api-gateway ├── Dockerbuild.sh ├── Dockerfile ├── api-gateway.js ├── api │ ├── account │ │ ├── login.js │ │ └── signup.js │ └── crm │ │ └── orders │ │ └── orders.js ├── config.js ├── config.json ├── package.json ├── server.js └── services-helper.js ├── micro-node-api-gateway.gif ├── service-log ├── Dockerbuild.sh ├── Dockerfile ├── config.js ├── config.json ├── log.js ├── package.json └── server.js ├── service-login ├── Dockerbuild.sh ├── Dockerfile ├── config.js ├── config.json ├── login.js ├── package.json └── server.js ├── service-orders ├── Dockerbuild.sh ├── Dockerfile ├── config.js ├── config.json ├── orders.js ├── package.json └── server.js └── service-signup ├── Dockerbuild.sh ├── Dockerfile ├── config.js ├── config.json ├── package.json ├── server.js └── signup.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | docs -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/micro-node-api-gateway.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 59 | 60 | 61 | 62 | true 63 | 64 | 65 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 101 | 102 | 103 | 104 | 107 | 108 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 124 | 125 | 126 | 127 | 1468269887291 128 | 133 | 134 | 135 | 136 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /Microservices_Architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alchimya/micro-node-api-gateway/1158548d29e7b7dfe52643e5cc397c2e5c8331eb/Microservices_Architecture.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | #What is this? 3 | 4 | This porject/turotial explains how to implement a NodeJs Api Gateway, into a Microservices Architecture based on a Service Registry developed with a server-side discovery pattern. 5 | 6 | ![ScreenShot](https://raw.github.com/alchimya/micro-node-api-gateway/master/Microservices_Architecture.png) 7 | 8 | Actually, this project can be described as a complete Microservices Architecture containing four different microservices accessible via Api Gateway and discovered with a Service Registry. 9 | 10 | #How to setup and configure 11 | To setup the project, it is enough to launch the the bash script ServicesSetup.sh 12 |
13 | The configuration it is a bit tedious but it is very easy. In order you need to open all the config.json file that you will find in to each project folder (services and api-gateway) and setup the MondoDB configuration within the serviceRegistry object: 14 | 15 | ```javascript 16 | "serviceRegistry":{ 17 | "watchDog":{ 18 | "isEnabled":false, 19 | "timer":30000 20 | }, 21 | "database":{ 22 | "name":"my_mongo_db", 23 | "user":"my_mongo_db_user", 24 | "password":"my_mongo_db_password", 25 | "host":"my_mongo_db_host", 26 | "port":27017 27 | } 28 | } 29 | ``` 30 | A more dtailed description of the configuration is reported in to the section at the bottom of this document. 31 | 32 | #How to use 33 | To start all services you must launch the bash script ServicesStart.sh. This script will provide to launch five differente clustered instances of a Node server as reported below: 34 |
35 | 36 | Service |Port | Service Route | Api Gateway Ruote (8080) 37 | ----------------|------------|---------------|------------------------- 38 | service-login | 8081 | /api/login | /api/account/login 39 | service-signup | 8082 | /api/signup | /api/account/signup 40 | service-orders | 8084 | /api/orders | /api/crm/orders 41 | service-log | 8084 | /api/log | ----- 42 | api-gateway | 8080 | ---- | ----- 43 | 44 |
45 | For this tutorial, it is allowed to access directly (see Service Route) to the services, but, depending of your requirements, you can block this access, alllowing only the access via Api Gateway (see Api Gateway Ruote) that for this project is listening to the port 8080. 46 | 47 | #Api Gateway Configuraiton 48 | Here, a detailed description of the config.json file for the Pai Gateway 49 | ```javascript 50 | { 51 | "server":{ 52 | "id":"MicroNodeApiGateway", 53 | "port":8080, 54 | "isCluster":true, 55 | "https":{ 56 | "isEnabled":false, 57 | "key":"", 58 | "ca":"" 59 | }, 60 | "headers":[ 61 | {"name":"Access-Control-Allow-Origin","value":"*"}, 62 | {"name":"Access-Control-Allow-Headers","value":"Origin, X-Requested-With, Content-Type, Accept"}, 63 | {"name":"Access-Control-Allow-Methods","value":"GET,PUT,POST,DELETE,OPTIONS"} 64 | ] 65 | }, 66 | "api":{ 67 | "route":"api", 68 | "modules":[ 69 | {"name":"login", "path":"api/account", "route":"account/login"}, 70 | {"name":"signup", "path":"api/account", "route":"account/signup"}, 71 | {"name":"orders", "path":"api/crm/orders", "route":"crm/orders"} 72 | ] 73 | }, 74 | "services":[ 75 | {"name":"ServiceLog", "endpointId":"log"}, 76 | {"name":"ServiceLogin", "endpointId":"login"}, 77 | {"name":"ServiceSignup", "endpointId":"signup"}, 78 | {"name":"ServiceOrders", "endpointId":"orders"} 79 | ], 80 | "serviceRegistry":{ 81 | "database":{ 82 | "name":"my_mongo_db", 83 | "user":"my_mongo_db_user", 84 | "password":"my_mongo_db_password", 85 | "host":"my_mongo_db_host", 86 | "port":27017 87 | } 88 | } 89 | } 90 | ``` 91 | where: 92 | - server.id: it is a key to identify the microservice 93 | - server.port: it is the port where the microservice is listen to 94 | - server,isCluster: set true if you want you fork the main process depending of your CPU 95 | - server.https: enable/disable the https. It is needed to have the righ certificates to allow clients to connect under https 96 | - server.headers: put here all the response headers that you want to use, for example to enable the cross-origin resource sharing. 97 | 98 | - api.route: defines the main route of the api (e.g. /api) 99 | - api.modules: add in to this array all the module (js files for example Express middleware) that you want to use as api modules. 100 | - api.services: add in to this array all the services that you want to implement with your Api Gateway using as service name and entry poin id, the same values used to register a microservice in to the service registry (see below Microservice Configuration and for more detail take a look to this project https://github.com/alchimya/micro-node-service/edit/master/README.md). 101 | 102 | - serviceRegistry.watchDog: enable/disable the auto-update for the service registry. Speficy the update seconds into the timer property 103 | - serviceRegistry.databse: configure here your MongoDb connection params. This database represents your Service Registry 104 | 105 | 106 | 107 | #Microservice Configuraiton 108 | Here, a detailed description of the config.json file for a Microservice 109 | ```javascript 110 | { 111 | "server":{ 112 | "id":"MicroNodeService", 113 | "port":8080, 114 | "isCluster":true, 115 | "https":{ 116 | "isEnabled":false, 117 | "key":"", 118 | "ca":"" 119 | }, 120 | "headers":[ 121 | {"name":"Access-Control-Allow-Origin","value":"*"}, 122 | {"name":"Access-Control-Allow-Headers","value":"Origin, X-Requested-With, Content-Type, Accept"}, 123 | {"name":"Access-Control-Allow-Methods","value":"GET,PUT,POST,DELETE,OPTIONS"} 124 | ] 125 | }, 126 | "api":{ 127 | "route":"api", 128 | "modules":[ 129 | {"name":"login", "route":"login"} 130 | ] 131 | }, 132 | "serviceRegistry":{ 133 | "watchDog":{ 134 | "isEnabled":false, 135 | "timer":30000 136 | }, 137 | "database":{ 138 | "name":"my_mongo_db", 139 | "user":"my_mongo_db_user", 140 | "password":"my_mongo_db_password", 141 | "host":"my_mongo_db_host", 142 | "port":27017 143 | } 144 | } 145 | } 146 | ``` 147 | where: 148 | - server.id: it is a key to identify the microservice 149 | - server.port: it is the port where the microservice is listen to 150 | - server,isCluster: set true if you want you fork the main process depending of your CPU 151 | - server.https: enable/disable the https. It is needed to have the righ certificates to allow clients to connect under https 152 | - server.headers: put here all the response headers that you want to use, for example to enable the cross-origin resource sharing. 153 | 154 | - api.route: defines the main route of the api (e.g. /api) 155 | - api.modules: add in to this array all the module (js files for example Express middleware) that you want to use as api modules 156 | 157 | - serviceRegistry.watchDog: enable/disable the auto-update for the service registry. Speficy the update seconds into the timer property 158 | - serviceRegistry.databse: configure here your MongoDb connection params. This database represents your Service Registry 159 | 160 | 161 | ![ScreenShot](https://raw.github.com/alchimya/micro-node-api-gateway/master/micro-node-api-gateway.gif) 162 | 163 | -------------------------------------------------------------------------------- /ServicesSetup.sh: -------------------------------------------------------------------------------- 1 | cd service-login 2 | sudo npm install 3 | 4 | cd .. 5 | cd service-orders 6 | sudo npm install 7 | 8 | cd .. 9 | cd service-signup 10 | sudo npm install 11 | 12 | cd .. 13 | cd service-log 14 | sudo npm install 15 | 16 | cd .. 17 | cd api-gateway 18 | sudo npm install -------------------------------------------------------------------------------- /ServicesStart.sh: -------------------------------------------------------------------------------- 1 | cd service-login 2 | DEBUG=http node server & 3 | 4 | cd .. 5 | cd service-orders 6 | DEBUG=http node server & 7 | 8 | cd .. 9 | cd service-signup 10 | DEBUG=http node server & 11 | 12 | cd .. 13 | cd service-log 14 | DEBUG=http node server & 15 | 16 | cd .. 17 | cd api-gateway 18 | DEBUG=http node server -------------------------------------------------------------------------------- /api-gateway/Dockerbuild.sh: -------------------------------------------------------------------------------- 1 | docker build -t micro-node-service-api-gateway:latest . 2 | winpty docker run -it --rm -p 8080:8080 --name micro-node-service-api-gateway micro-node-service-api-gateway:latest -------------------------------------------------------------------------------- /api-gateway/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:6.2.0-onbuild 2 | EXPOSE 8080 -------------------------------------------------------------------------------- /api-gateway/api-gateway.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 10/07/16. 3 | */ 4 | 5 | var debug = require('debug')('http'), 6 | config= require ('./config')(), 7 | request = require('request'), 8 | servicesHelper = require('./services-helper')(config.services), 9 | serviceRegistry = require ('micro-node-service-registry-lib')({ 10 | name:config.serviceRegistry.database.name, 11 | user:config.serviceRegistry.database.user, 12 | password:config.serviceRegistry.database.password, 13 | host:config.serviceRegistry.database.host, 14 | port:config.serviceRegistry.database.port, 15 | connectionPool:config.serviceRegistry.database.connectionPool 16 | }); 17 | 18 | var ApiGateway = function () { 19 | 20 | }; 21 | 22 | 23 | ApiGateway.prototype.sendRequest=function (serviceName,serviceEndpointId,req, res,next) { 24 | 25 | service=servicesHelper.getService(serviceName,serviceEndpointId); 26 | 27 | serviceRegistry.find(service.name,service.endpointId,function (error,service) { 28 | if (service && !error){ 29 | console.log(service); 30 | request({ 31 | url: service.endpointUrl, 32 | method: 'POST', 33 | json:req.body 34 | }, function(error, response, body){ 35 | if (error){ 36 | return next(error) 37 | }else { 38 | debug(body); 39 | return res.status(response.statusCode).send(body); 40 | } 41 | }); 42 | } else { 43 | if (error){ 44 | return next(error); 45 | }else { 46 | return res.status(500).send(responseLib.errorResponse(1001,"Service not found","Application Error")); 47 | } 48 | 49 | } 50 | }); 51 | }; 52 | 53 | module.exports=ApiGateway; -------------------------------------------------------------------------------- /api-gateway/api/account/login.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 10/07/16. 3 | */ 4 | 5 | var express = require('express'), 6 | router = express.Router(), 7 | apiGateway = require('../.././api-gateway'); 8 | 9 | router.post('/', function (req, res,next) { 10 | var request = new apiGateway(); 11 | request.sendRequest("ServiceLogin","login",req, res,next); 12 | }); 13 | 14 | module.exports = router; -------------------------------------------------------------------------------- /api-gateway/api/account/signup.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 10/07/16. 3 | */ 4 | 5 | var express = require('express'), 6 | router = express.Router(), 7 | apiGateway = require('../.././api-gateway'); 8 | 9 | router.post('/', function (req, res,next) { 10 | var request = new apiGateway(); 11 | request.sendRequest("ServiceSignup","signup",req, res,next); 12 | }); 13 | 14 | module.exports = router; -------------------------------------------------------------------------------- /api-gateway/api/crm/orders/orders.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 10/07/16. 3 | */ 4 | 5 | var express = require('express'), 6 | router = express.Router(), 7 | apiGateway = require('../../.././api-gateway'); 8 | 9 | router.post('/', function (req, res,next) { 10 | var request = new apiGateway(); 11 | request.sendRequest("ServiceOrders","orders",req, res,next); 12 | }); 13 | 14 | module.exports = router; -------------------------------------------------------------------------------- /api-gateway/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 25/05/16. 3 | */ 4 | 5 | var fs = require('fs'); 6 | 7 | function Config() { 8 | var config = JSON.parse(fs.readFileSync(__dirname + '/config.json'), 'utf8'); 9 | return{ 10 | server:{ 11 | id:config.server.id, 12 | port:config.server.port, 13 | isCluster:config.server.isCluster, 14 | https:config.server.https, 15 | headers:config.server.headers, 16 | httpsKeyContent:config.server.https.key ? fs.readFileSync(__dirname + "/" + config.server.https.key) :null, 17 | httpsCaContent:config.server.https.ca ? fs.readFileSync(__dirname + "/" + config.server.https.ca) :null, 18 | }, 19 | api:{ 20 | route:config.api.route, 21 | modules:config.api.modules 22 | }, 23 | services:config.services, 24 | serviceRegistry:config.serviceRegistry 25 | }; 26 | 27 | } 28 | module.exports=Config; 29 | -------------------------------------------------------------------------------- /api-gateway/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "server":{ 3 | "id":"MicroNodeApiGateway", 4 | "port":8080, 5 | "isCluster":true, 6 | "https":{ 7 | "isEnabled":false, 8 | "key":"", 9 | "ca":"" 10 | }, 11 | "headers":[ 12 | {"name":"Access-Control-Allow-Origin","value":"*"}, 13 | {"name":"Access-Control-Allow-Headers","value":"Origin, X-Requested-With, Content-Type, Accept"}, 14 | {"name":"Access-Control-Allow-Methods","value":"GET,PUT,POST,DELETE,OPTIONS"} 15 | ] 16 | }, 17 | "api":{ 18 | "route":"api", 19 | "modules":[ 20 | {"name":"login", "path":"api/account", "route":"account/login"}, 21 | {"name":"signup", "path":"api/account", "route":"account/signup"}, 22 | {"name":"orders", "path":"api/crm/orders", "route":"crm/orders"} 23 | ] 24 | }, 25 | "services":[ 26 | {"name":"ServiceLog", "endpointId":"log"}, 27 | {"name":"ServiceLogin", "endpointId":"login"}, 28 | {"name":"ServiceSignup", "endpointId":"signup"}, 29 | {"name":"ServiceOrders", "endpointId":"orders"} 30 | ], 31 | "serviceRegistry":{ 32 | "database":{ 33 | "name":"my_mongo_db", 34 | "user":"my_mongo_db_user", 35 | "password":"my_mongo_db_password", 36 | "host":"my_mongo_db_host", 37 | "port":27017 38 | } 39 | } 40 | } 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /api-gateway/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DoorApiGateway", 3 | "version": "0.0.1", 4 | "description": "Api Gateway", 5 | "author": { 6 | "name": "Domenico Vacchiano", 7 | "email": "domenico@doorgames.com", 8 | "url": "http://www.doorgames.com" 9 | }, 10 | "homepage": "http://www.doorgames.com/", 11 | "repository": { 12 | "type": "git", 13 | "url": "" 14 | }, 15 | 16 | "engines": { 17 | "node": ">= 0.6.0", 18 | "npm": ">= 1.0.0" 19 | }, 20 | 21 | "dependencies": { 22 | "express": "^4.13.4", 23 | "body-parser":"^1.15.1", 24 | "jsonwebtoken": "^7.0.0", 25 | "request":"^2.72.0", 26 | "morgan": "^1.7.0", 27 | "micro-node-net-lib":"git@github.com:alchimya/micro-node-net-lib.git", 28 | "micro-node-service-registry-lib":"git@github.com:alchimya/micro-node-service-registry-lib.git" 29 | 30 | }, 31 | "private": true, 32 | "scripts": { 33 | "start": "node server.js" 34 | }, 35 | "main": "server.js" 36 | } 37 | -------------------------------------------------------------------------------- /api-gateway/server.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 10/07/16. 3 | */ 4 | 5 | var config= require ('./config')(), 6 | express=require('express'), 7 | debug = require('debug')('http'), 8 | bodyParser = require('body-parser'), 9 | morgan= require('morgan'), 10 | cluster = require('cluster'), 11 | numCPUs = require('os').cpus().length, 12 | netLib = require ('micro-node-net-lib'), 13 | apiGateway = require('./api-gateway'), 14 | configServer= { 15 | server:{ 16 | port:config.server.port 17 | }, 18 | https:{ 19 | isEnabled:config.server.https.isEnabled, 20 | key:config.server.httpsKeyContent, 21 | ca:config.server.httpsCaContent 22 | }, 23 | express:{ 24 | app:null 25 | }, 26 | exitHandlers:["exit","SIGINT","SIGTERM"] 27 | }, 28 | server = netLib.server(configServer); 29 | 30 | if (cluster.isMaster && config.server.isCluster) { 31 | debug("cpus:" + numCPUs); 32 | for (var i = 0; i < numCPUs; i++) { 33 | cluster.fork(); 34 | } 35 | cluster.on('exit', function(worker, code, signal) { 36 | console.log("cluster exit"); 37 | debug('Worker %d died with code/signal %s. Restarting worker...', worker.process.pid, signal || code); 38 | cluster.fork(); 39 | }); 40 | 41 | } else { 42 | 43 | var app=express(); 44 | app.use(bodyParser.urlencoded({ extended: true })); 45 | app.use(bodyParser.json()); 46 | app.use(morgan('dev')); 47 | configServer.express.app = app; 48 | 49 | //header(s) setting 50 | app.all('/*', function(req, res, next) { 51 | config.server.headers.forEach(function(item) { 52 | //console.log(item); 53 | res.header(item.name, item.value); 54 | }); 55 | next(); 56 | }); 57 | 58 | //pu here a middleware to check the api key 59 | 60 | 61 | //load API route(s) 62 | config.api.modules.forEach(function(item) { 63 | //console.log(item); 64 | app.use('/' + config.api.route + "/" + item.route, require('./' + item.path + "/" + item.name)); 65 | }); 66 | 67 | server.create(function (err,server) { 68 | if (!err){ 69 | console.log("### " + config.server.id + " -> " + (config.server.https ? "HTTPS" : "HTTP") + " Server started on port " + 70 | config.server.port + (config.server.isCluster ? " cluster worker " + cluster.worker.id : "")); 71 | } else { 72 | debug(err); 73 | } 74 | }); 75 | 76 | 77 | //Http Error Handling on 78 | app.use(function(err, req, res, next) { 79 | debug(err); 80 | var request = new apiGateway(); 81 | request.sendRequest("ServiceLog","log",req, res,next); 82 | res.status(500).send({ 83 | code:1000, 84 | message:"Application Error", 85 | domain:"Application Error" 86 | }); 87 | }); 88 | } -------------------------------------------------------------------------------- /api-gateway/services-helper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 11/07/16. 3 | */ 4 | 5 | function ServiceHelper(services) { 6 | return{ 7 | getServiceWithName:function (serviceName) { 8 | var service=services.filter(function( item ) { 9 | return item.name == serviceName; 10 | }); 11 | if (!service || !service[0] || service[0].length==0){ 12 | return null; 13 | } 14 | return service[0]; 15 | }, 16 | getService:function (serviceName,serviceEndpointId) { 17 | var service=services.filter(function( item ) { 18 | return (item.name == serviceName && item.endpointId == serviceEndpointId); 19 | }); 20 | if (!service || !service[0] || service[0].length==0){ 21 | return null; 22 | } 23 | return service[0]; 24 | } 25 | }; 26 | }; 27 | 28 | module.exports=ServiceHelper; -------------------------------------------------------------------------------- /micro-node-api-gateway.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alchimya/micro-node-api-gateway/1158548d29e7b7dfe52643e5cc397c2e5c8331eb/micro-node-api-gateway.gif -------------------------------------------------------------------------------- /service-log/Dockerbuild.sh: -------------------------------------------------------------------------------- 1 | docker build -t micro-node-service-log:latest . 2 | winpty docker run -it --rm -p 8084:8084 --name micro-node-service-log micro-node-service-log:latest -------------------------------------------------------------------------------- /service-log/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:6.2.0-onbuild 2 | EXPOSE 8084 -------------------------------------------------------------------------------- /service-log/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 07/07/16. 3 | */ 4 | 5 | var fs = require('fs'); 6 | 7 | function Config() { 8 | var config = JSON.parse(fs.readFileSync(__dirname + '/config.json'), 'utf8'); 9 | return{ 10 | server:{ 11 | id:config.server.id, 12 | port:config.server.port, 13 | isCluster:config.server.isCluster, 14 | https:config.server.https, 15 | headers:config.server.headers, 16 | httpsKeyContent:config.server.https.key ? fs.readFileSync(__dirname + "/" + config.server.https.key) :null, 17 | httpsCaContent:config.server.https.ca ? fs.readFileSync(__dirname + "/" + config.server.https.ca) :null, 18 | }, 19 | api:{ 20 | route:config.api.route, 21 | modules:config.api.modules 22 | }, 23 | serviceRegistry:config.serviceRegistry 24 | 25 | }; 26 | 27 | } 28 | module.exports=Config; 29 | -------------------------------------------------------------------------------- /service-log/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "server":{ 3 | "id":"ServiceLog", 4 | "port":8084, 5 | "isCluster":true, 6 | "https":{ 7 | "isEnabled":false, 8 | "key":"", 9 | "ca":"" 10 | }, 11 | "headers":[ 12 | {"name":"Access-Control-Allow-Origin","value":"*"}, 13 | {"name":"Access-Control-Allow-Headers","value":"Origin, X-Requested-With, Content-Type, Accept"}, 14 | {"name":"Access-Control-Allow-Methods","value":"GET,PUT,POST,DELETE,OPTIONS"} 15 | ] 16 | }, 17 | "api":{ 18 | "route":"api", 19 | "modules":[ 20 | {"name":"log", "route":"log"} 21 | ] 22 | }, 23 | "serviceRegistry":{ 24 | "watchDog":{ 25 | "isEnabled":false, 26 | "timer":30000 27 | }, 28 | "database":{ 29 | "name":"my_mongo_db", 30 | "user":"my_mongo_db_user", 31 | "password":"my_mongo_db_password", 32 | "host":"my_mongo_db_host", 33 | "port":27017 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /service-log/log.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 07/07/16. 3 | */ 4 | 5 | var express = require('express'), 6 | router = express.Router(), 7 | debug = require('debug')('http'), 8 | config= require ('./config')() 9 | 10 | router.post('/', function (req, res,next) { 11 | return res.status(200).send("## Log -> This is just a test response ;-)"); 12 | }); 13 | 14 | module.exports = router; -------------------------------------------------------------------------------- /service-log/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MicroNodeService", 3 | "version": "0.0.1", 4 | "description": "Micro Node Tutorial", 5 | "author": { 6 | "name": "Domenico Vacchiano", 7 | "email": "info@domenicovacchiano.com", 8 | "url": "http://www.domenicovacchiano.com" 9 | }, 10 | "homepage": "http://www.domenicovacchiano.com/", 11 | "repository": { 12 | "type": "git", 13 | "url": "" 14 | }, 15 | 16 | "engines": { 17 | "node": ">= 0.6.0", 18 | "npm": ">= 1.0.0" 19 | }, 20 | 21 | "dependencies": { 22 | "express": "^4.13.4", 23 | "body-parser":"^1.15.1", 24 | "request":"^2.72.0", 25 | "morgan": "^1.7.0", 26 | "network-address": "^1.1.0", 27 | "micro-node-net-lib":"git@github.com:alchimya/micro-node-net-lib.git", 28 | "micro-node-service-registry-lib":"git@github.com:alchimya/micro-node-service-registry-lib.git" 29 | }, 30 | "private": true, 31 | "scripts": { 32 | "start": "node server.js" 33 | }, 34 | "main": "server.js" 35 | } 36 | -------------------------------------------------------------------------------- /service-log/server.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 07/07/16. 3 | */ 4 | 5 | var config= require ('./config')(), 6 | address = require('network-address'), 7 | express=require('express'), 8 | debug = require('debug')('http'), 9 | bodyParser = require('body-parser'), 10 | morgan= require('morgan'), 11 | cluster = require('cluster'), 12 | numCPUs = require('os').cpus().length, 13 | netLib = require ('micro-node-net-lib'), 14 | configServer= { 15 | server:{ 16 | port:config.server.port 17 | }, 18 | https:{ 19 | isEnabled:config.server.https.isEnabled, 20 | key:config.server.httpsKeyContent, 21 | ca:config.server.httpsCaContent 22 | }, 23 | express:{ 24 | app:null 25 | }, 26 | exitHandlers:["exit","SIGINT","SIGTERM"] 27 | } 28 | server = netLib.server(configServer), 29 | serviceRegistry = require ('micro-node-service-registry-lib')({ 30 | name:config.serviceRegistry.database.name, 31 | user:config.serviceRegistry.database.user, 32 | password:config.serviceRegistry.database.password, 33 | host:config.serviceRegistry.database.host, 34 | port:config.serviceRegistry.database.port, 35 | connectionPool:config.serviceRegistry.database.connectionPool 36 | }); 37 | 38 | if (cluster.isMaster && config.server.isCluster) { 39 | 40 | debug("cpus:" + numCPUs); 41 | for (var i = 0; i < numCPUs; i++) { 42 | cluster.fork(); 43 | } 44 | cluster.on('exit', function(worker, code, signal) { 45 | console.log("cluster exit"); 46 | debug('Worker %d died with code/signal %s. Restarting worker...', worker.process.pid, signal || code); 47 | cluster.fork(); 48 | }); 49 | 50 | } else { 51 | 52 | var app=express(); 53 | app.use(bodyParser.urlencoded({ extended: true })); 54 | app.use(bodyParser.json()); 55 | app.use(morgan('dev')); 56 | configServer.express.app = app; 57 | 58 | //header(s) setting 59 | app.all('/*', function(req, res, next) { 60 | config.server.headers.forEach(function(item) { 61 | //console.log(item); 62 | res.header(item.name, item.value); 63 | }); 64 | next(); 65 | }); 66 | 67 | //load API route(s) 68 | config.api.modules.forEach(function(item) { 69 | //console.log(item); 70 | app.use('/' + config.api.route + "/" + item.route, require('./' + item.name)); 71 | }); 72 | 73 | server.create(function (err,server) { 74 | if (!err){ 75 | //load API route(s) and register services 76 | registerServer(); 77 | if (config.serviceRegistry.watchDog.isEnabled){ 78 | setInterval(function(){ 79 | registerServer(); 80 | }, config.serviceRegistry.watchDog.timer); 81 | } 82 | console.log("### " + config.server.id + " -> " + (config.server.https ? "HTTPS" : "HTTP") + " Server started on port " + 83 | config.server.port + (config.server.isCluster ? " cluster worker " + cluster.worker.id : "")); 84 | } else { 85 | debug(err); 86 | } 87 | }); 88 | 89 | server.registerExitHandler(function () { 90 | unregisterServer(); 91 | debug("Server Exit Handled"); 92 | }); 93 | 94 | var registerServer=function () { 95 | if (!config.server.isCluster || cluster.worker.id===1){ 96 | debug("registerServer"); 97 | config.api.modules.forEach(function(item) { 98 | //console.log(item); 99 | app.use('/' + config.api.route + "/" + item.route, require('./' + item.name)); 100 | serviceRegistry.register({ 101 | serviceId:config.server.id, 102 | serviceHost:address(), 103 | servicePort:config.server.port, 104 | serviceProtocol:config.server.https.isEnabled ? "https" : "http", 105 | endpointId:item.name, 106 | endpointPath:config.api.route + "/" + item.route 107 | }, function (err,item) { 108 | if (err){ 109 | console.log(app.next()) 110 | debug(err); 111 | } 112 | }); 113 | }); 114 | } 115 | }; 116 | var unregisterServer = function () { 117 | if (!config.server.isCluster || cluster.worker.id===1){ 118 | debug("unregisterServer"); 119 | config.api.modules.forEach(function(item) { 120 | serviceRegistry.unregister(config.server.id,item.name,function (err,item) { 121 | if (err){ 122 | //TODO update flag inactive? 123 | console.log(err); 124 | } 125 | if (!config.server.isCluster){ 126 | process.exit(); 127 | } 128 | }); 129 | }); 130 | } 131 | }; 132 | 133 | 134 | 135 | } 136 | -------------------------------------------------------------------------------- /service-login/Dockerbuild.sh: -------------------------------------------------------------------------------- 1 | docker build -t micro-node-service-login:latest . 2 | winpty docker run -it --rm -p 8081:8081 --name micro-node-service-login micro-node-service-login:latest -------------------------------------------------------------------------------- /service-login/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:6.2.0-onbuild 2 | EXPOSE 8081 -------------------------------------------------------------------------------- /service-login/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 07/07/16. 3 | */ 4 | 5 | var fs = require('fs'); 6 | 7 | function Config() { 8 | var config = JSON.parse(fs.readFileSync(__dirname + '/config.json'), 'utf8'); 9 | return{ 10 | server:{ 11 | id:config.server.id, 12 | port:config.server.port, 13 | isCluster:config.server.isCluster, 14 | https:config.server.https, 15 | headers:config.server.headers, 16 | httpsKeyContent:config.server.https.key ? fs.readFileSync(__dirname + "/" + config.server.https.key) :null, 17 | httpsCaContent:config.server.https.ca ? fs.readFileSync(__dirname + "/" + config.server.https.ca) :null, 18 | }, 19 | api:{ 20 | route:config.api.route, 21 | modules:config.api.modules 22 | }, 23 | serviceRegistry:config.serviceRegistry 24 | 25 | }; 26 | 27 | } 28 | module.exports=Config; 29 | -------------------------------------------------------------------------------- /service-login/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "server":{ 3 | "id":"ServiceLogin", 4 | "port":8081, 5 | "isCluster":true, 6 | "https":{ 7 | "isEnabled":false, 8 | "key":"", 9 | "ca":"" 10 | }, 11 | "headers":[ 12 | {"name":"Access-Control-Allow-Origin","value":"*"}, 13 | {"name":"Access-Control-Allow-Headers","value":"Origin, X-Requested-With, Content-Type, Accept"}, 14 | {"name":"Access-Control-Allow-Methods","value":"GET,PUT,POST,DELETE,OPTIONS"} 15 | ] 16 | }, 17 | "api":{ 18 | "route":"api", 19 | "modules":[ 20 | {"name":"login", "route":"login"} 21 | ] 22 | }, 23 | "serviceRegistry":{ 24 | "watchDog":{ 25 | "isEnabled":false, 26 | "timer":30000 27 | }, 28 | "database":{ 29 | "name":"my_mongo_db", 30 | "user":"my_mongo_db_user", 31 | "password":"my_mongo_db_password", 32 | "host":"my_mongo_db_host", 33 | "port":27017 34 | } 35 | } 36 | } 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /service-login/login.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 07/07/16. 3 | */ 4 | 5 | var express = require('express'), 6 | router = express.Router(), 7 | debug = require('debug')('http'), 8 | config= require ('./config')() 9 | 10 | router.post('/', function (req, res,next) { 11 | return res.status(200).send("## Login -> This is just a test response ;-)"); 12 | }); 13 | 14 | module.exports = router; -------------------------------------------------------------------------------- /service-login/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MicroNodeService", 3 | "version": "0.0.1", 4 | "description": "Micro Node Tutorial", 5 | "author": { 6 | "name": "Domenico Vacchiano", 7 | "email": "info@domenicovacchiano.com", 8 | "url": "http://www.domenicovacchiano.com" 9 | }, 10 | "homepage": "http://www.domenicovacchiano.com/", 11 | "repository": { 12 | "type": "git", 13 | "url": "" 14 | }, 15 | 16 | "engines": { 17 | "node": ">= 0.6.0", 18 | "npm": ">= 1.0.0" 19 | }, 20 | 21 | "dependencies": { 22 | "express": "^4.13.4", 23 | "body-parser":"^1.15.1", 24 | "request":"^2.72.0", 25 | "morgan": "^1.7.0", 26 | "network-address": "^1.1.0", 27 | "micro-node-net-lib":"git@github.com:alchimya/micro-node-net-lib.git", 28 | "micro-node-service-registry-lib":"git@github.com:alchimya/micro-node-service-registry-lib.git" 29 | }, 30 | "private": true, 31 | "scripts": { 32 | "start": "node server.js" 33 | }, 34 | "main": "server.js" 35 | } 36 | -------------------------------------------------------------------------------- /service-login/server.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 07/07/16. 3 | */ 4 | 5 | var config= require ('./config')(), 6 | address = require('network-address'), 7 | express=require('express'), 8 | debug = require('debug')('http'), 9 | bodyParser = require('body-parser'), 10 | morgan= require('morgan'), 11 | cluster = require('cluster'), 12 | numCPUs = require('os').cpus().length, 13 | netLib = require ('micro-node-net-lib'), 14 | configServer= { 15 | server:{ 16 | port:config.server.port 17 | }, 18 | https:{ 19 | isEnabled:config.server.https.isEnabled, 20 | key:config.server.httpsKeyContent, 21 | ca:config.server.httpsCaContent 22 | }, 23 | express:{ 24 | app:null 25 | }, 26 | exitHandlers:["exit","SIGINT","SIGTERM"] 27 | } 28 | server = netLib.server(configServer), 29 | serviceRegistry = require ('micro-node-service-registry-lib')({ 30 | name:config.serviceRegistry.database.name, 31 | user:config.serviceRegistry.database.user, 32 | password:config.serviceRegistry.database.password, 33 | host:config.serviceRegistry.database.host, 34 | port:config.serviceRegistry.database.port, 35 | connectionPool:config.serviceRegistry.database.connectionPool 36 | }); 37 | 38 | if (cluster.isMaster && config.server.isCluster) { 39 | 40 | debug("cpus:" + numCPUs); 41 | for (var i = 0; i < numCPUs; i++) { 42 | cluster.fork(); 43 | } 44 | cluster.on('exit', function(worker, code, signal) { 45 | console.log("cluster exit"); 46 | debug('Worker %d died with code/signal %s. Restarting worker...', worker.process.pid, signal || code); 47 | cluster.fork(); 48 | }); 49 | 50 | } else { 51 | 52 | var app=express(); 53 | app.use(bodyParser.urlencoded({ extended: true })); 54 | app.use(bodyParser.json()); 55 | app.use(morgan('dev')); 56 | configServer.express.app = app; 57 | 58 | //header(s) setting 59 | app.all('/*', function(req, res, next) { 60 | config.server.headers.forEach(function(item) { 61 | //console.log(item); 62 | res.header(item.name, item.value); 63 | }); 64 | next(); 65 | }); 66 | 67 | //load API route(s) 68 | config.api.modules.forEach(function(item) { 69 | //console.log(item); 70 | app.use('/' + config.api.route + "/" + item.route, require('./' + item.name)); 71 | }); 72 | 73 | server.create(function (err,server) { 74 | if (!err){ 75 | //load API route(s) and register services 76 | registerServer(); 77 | if (config.serviceRegistry.watchDog.isEnabled){ 78 | setInterval(function(){ 79 | registerServer(); 80 | }, config.serviceRegistry.watchDog.timer); 81 | } 82 | console.log("### " + config.server.id + " -> " + (config.server.https ? "HTTPS" : "HTTP") + " Server started on port " + 83 | config.server.port + (config.server.isCluster ? " cluster worker " + cluster.worker.id : "")); 84 | } else { 85 | debug(err); 86 | } 87 | }); 88 | 89 | server.registerExitHandler(function () { 90 | unregisterServer(); 91 | debug("Server Exit Handled"); 92 | }); 93 | 94 | var registerServer=function () { 95 | if (!config.server.isCluster || cluster.worker.id===1){ 96 | debug("registerServer"); 97 | config.api.modules.forEach(function(item) { 98 | //console.log(item); 99 | app.use('/' + config.api.route + "/" + item.route, require('./' + item.name)); 100 | serviceRegistry.register({ 101 | serviceId:config.server.id, 102 | serviceHost:address(), 103 | servicePort:config.server.port, 104 | serviceProtocol:config.server.https.isEnabled ? "https" : "http", 105 | endpointId:item.name, 106 | endpointPath:config.api.route + "/" + item.route 107 | }, function (err,item) { 108 | if (err){ 109 | console.log(app.next()) 110 | debug(err); 111 | } 112 | }); 113 | }); 114 | } 115 | }; 116 | var unregisterServer = function () { 117 | if (!config.server.isCluster || cluster.worker.id===1){ 118 | debug("unregisterServer"); 119 | config.api.modules.forEach(function(item) { 120 | serviceRegistry.unregister(config.server.id,item.name,function (err,item) { 121 | if (err){ 122 | //TODO update flag inactive? 123 | console.log(err); 124 | } 125 | if (!config.server.isCluster){ 126 | process.exit(); 127 | } 128 | }); 129 | }); 130 | } 131 | }; 132 | 133 | 134 | } 135 | -------------------------------------------------------------------------------- /service-orders/Dockerbuild.sh: -------------------------------------------------------------------------------- 1 | docker build -t micro-node-service-orders:latest . 2 | winpty docker run -it --rm -p 8083:8083 --name micro-node-service-orders micro-node-service-orders:latest -------------------------------------------------------------------------------- /service-orders/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:6.2.0-onbuild 2 | EXPOSE 8083 -------------------------------------------------------------------------------- /service-orders/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 07/07/16. 3 | */ 4 | 5 | var fs = require('fs'); 6 | 7 | function Config() { 8 | var config = JSON.parse(fs.readFileSync(__dirname + '/config.json'), 'utf8'); 9 | return{ 10 | server:{ 11 | id:config.server.id, 12 | port:config.server.port, 13 | isCluster:config.server.isCluster, 14 | https:config.server.https, 15 | headers:config.server.headers, 16 | httpsKeyContent:config.server.https.key ? fs.readFileSync(__dirname + "/" + config.server.https.key) :null, 17 | httpsCaContent:config.server.https.ca ? fs.readFileSync(__dirname + "/" + config.server.https.ca) :null, 18 | }, 19 | api:{ 20 | route:config.api.route, 21 | modules:config.api.modules 22 | }, 23 | serviceRegistry:config.serviceRegistry 24 | 25 | }; 26 | 27 | } 28 | module.exports=Config; 29 | -------------------------------------------------------------------------------- /service-orders/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "server":{ 3 | "id":"ServiceOrders", 4 | "port":8083, 5 | "isCluster":true, 6 | "https":{ 7 | "isEnabled":false, 8 | "key":"", 9 | "ca":"" 10 | }, 11 | "headers":[ 12 | {"name":"Access-Control-Allow-Origin","value":"*"}, 13 | {"name":"Access-Control-Allow-Headers","value":"Origin, X-Requested-With, Content-Type, Accept"}, 14 | {"name":"Access-Control-Allow-Methods","value":"GET,PUT,POST,DELETE,OPTIONS"} 15 | ] 16 | }, 17 | "api":{ 18 | "route":"api", 19 | "modules":[ 20 | {"name":"orders", "route":"orders"} 21 | ] 22 | }, 23 | "serviceRegistry":{ 24 | "watchDog":{ 25 | "isEnabled":false, 26 | "timer":30000 27 | }, 28 | "database":{ 29 | "name":"my_mongo_db", 30 | "user":"my_mongo_db_user", 31 | "password":"my_mongo_db_password", 32 | "host":"my_mongo_db_host", 33 | "port":27017 34 | } 35 | } 36 | } 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /service-orders/orders.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 07/07/16. 3 | */ 4 | 5 | var express = require('express'), 6 | router = express.Router(), 7 | debug = require('debug')('http'), 8 | config= require ('./config')() 9 | 10 | router.post('/', function (req, res,next) { 11 | return res.status(200).send("## Orders -> This is just a test response ;-)"); 12 | }); 13 | 14 | module.exports = router; -------------------------------------------------------------------------------- /service-orders/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MicroNodeService", 3 | "version": "0.0.1", 4 | "description": "Micro Node Tutorial", 5 | "author": { 6 | "name": "Domenico Vacchiano", 7 | "email": "info@domenicovacchiano.com", 8 | "url": "http://www.domenicovacchiano.com" 9 | }, 10 | "homepage": "http://www.domenicovacchiano.com/", 11 | "repository": { 12 | "type": "git", 13 | "url": "" 14 | }, 15 | 16 | "engines": { 17 | "node": ">= 0.6.0", 18 | "npm": ">= 1.0.0" 19 | }, 20 | 21 | "dependencies": { 22 | "express": "^4.13.4", 23 | "body-parser":"^1.15.1", 24 | "request":"^2.72.0", 25 | "morgan": "^1.7.0", 26 | "network-address": "^1.1.0", 27 | "micro-node-net-lib":"git@github.com:alchimya/micro-node-net-lib.git", 28 | "micro-node-service-registry-lib":"git@github.com:alchimya/micro-node-service-registry-lib.git" 29 | }, 30 | "private": true, 31 | "scripts": { 32 | "start": "node server.js" 33 | }, 34 | "main": "server.js" 35 | } 36 | -------------------------------------------------------------------------------- /service-orders/server.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 07/07/16. 3 | */ 4 | 5 | var config= require ('./config')(), 6 | address = require('network-address'), 7 | express=require('express'), 8 | debug = require('debug')('http'), 9 | bodyParser = require('body-parser'), 10 | morgan= require('morgan'), 11 | cluster = require('cluster'), 12 | numCPUs = require('os').cpus().length, 13 | netLib = require ('micro-node-net-lib'), 14 | configServer= { 15 | server:{ 16 | port:config.server.port 17 | }, 18 | https:{ 19 | isEnabled:config.server.https.isEnabled, 20 | key:config.server.httpsKeyContent, 21 | ca:config.server.httpsCaContent 22 | }, 23 | express:{ 24 | app:null 25 | }, 26 | exitHandlers:["exit","SIGINT","SIGTERM"] 27 | } 28 | server = netLib.server(configServer), 29 | serviceRegistry = require ('micro-node-service-registry-lib')({ 30 | name:config.serviceRegistry.database.name, 31 | user:config.serviceRegistry.database.user, 32 | password:config.serviceRegistry.database.password, 33 | host:config.serviceRegistry.database.host, 34 | port:config.serviceRegistry.database.port, 35 | connectionPool:config.serviceRegistry.database.connectionPool 36 | }); 37 | 38 | if (cluster.isMaster && config.server.isCluster) { 39 | 40 | debug("cpus:" + numCPUs); 41 | for (var i = 0; i < numCPUs; i++) { 42 | cluster.fork(); 43 | } 44 | cluster.on('exit', function(worker, code, signal) { 45 | console.log("cluster exit"); 46 | debug('Worker %d died with code/signal %s. Restarting worker...', worker.process.pid, signal || code); 47 | cluster.fork(); 48 | }); 49 | 50 | } else { 51 | 52 | var app=express(); 53 | app.use(bodyParser.urlencoded({ extended: true })); 54 | app.use(bodyParser.json()); 55 | app.use(morgan('dev')); 56 | configServer.express.app = app; 57 | 58 | //header(s) setting 59 | app.all('/*', function(req, res, next) { 60 | config.server.headers.forEach(function(item) { 61 | //console.log(item); 62 | res.header(item.name, item.value); 63 | }); 64 | next(); 65 | }); 66 | 67 | //load API route(s) 68 | config.api.modules.forEach(function(item) { 69 | //console.log(item); 70 | app.use('/' + config.api.route + "/" + item.route, require('./' + item.name)); 71 | }); 72 | 73 | server.create(function (err,server) { 74 | if (!err){ 75 | //load API route(s) and register services 76 | registerServer(); 77 | if (config.serviceRegistry.watchDog.isEnabled){ 78 | setInterval(function(){ 79 | registerServer(); 80 | }, config.serviceRegistry.watchDog.timer); 81 | } 82 | console.log("### " + config.server.id + " -> " + (config.server.https ? "HTTPS" : "HTTP") + " Server started on port " + 83 | config.server.port + (config.server.isCluster ? " cluster worker " + cluster.worker.id : "")); 84 | } else { 85 | debug(err); 86 | } 87 | }); 88 | 89 | server.registerExitHandler(function () { 90 | unregisterServer(); 91 | debug("Server Exit Handled"); 92 | }); 93 | 94 | var registerServer=function () { 95 | if (!config.server.isCluster || cluster.worker.id===1){ 96 | debug("registerServer"); 97 | config.api.modules.forEach(function(item) { 98 | //console.log(item); 99 | app.use('/' + config.api.route + "/" + item.route, require('./' + item.name)); 100 | serviceRegistry.register({ 101 | serviceId:config.server.id, 102 | serviceHost:address(), 103 | servicePort:config.server.port, 104 | serviceProtocol:config.server.https.isEnabled ? "https" : "http", 105 | endpointId:item.name, 106 | endpointPath:config.api.route + "/" + item.route 107 | }, function (err,item) { 108 | if (err){ 109 | console.log(app.next()) 110 | debug(err); 111 | } 112 | }); 113 | }); 114 | } 115 | }; 116 | var unregisterServer = function () { 117 | if (!config.server.isCluster || cluster.worker.id===1){ 118 | debug("unregisterServer"); 119 | config.api.modules.forEach(function(item) { 120 | serviceRegistry.unregister(config.server.id,item.name,function (err,item) { 121 | if (err){ 122 | //TODO update flag inactive? 123 | console.log(err); 124 | } 125 | if (!config.server.isCluster){ 126 | process.exit(); 127 | } 128 | }); 129 | }); 130 | } 131 | }; 132 | 133 | 134 | } 135 | -------------------------------------------------------------------------------- /service-signup/Dockerbuild.sh: -------------------------------------------------------------------------------- 1 | docker build -t micro-node-service-signup:latest . 2 | winpty docker run -it --rm -p 8082:8082 --name micro-node-service-signup micro-node-service-signup:latest -------------------------------------------------------------------------------- /service-signup/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:6.2.0-onbuild 2 | EXPOSE 8082 -------------------------------------------------------------------------------- /service-signup/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 07/07/16. 3 | */ 4 | 5 | var fs = require('fs'); 6 | 7 | function Config() { 8 | var config = JSON.parse(fs.readFileSync(__dirname + '/config.json'), 'utf8'); 9 | return{ 10 | server:{ 11 | id:config.server.id, 12 | port:config.server.port, 13 | isCluster:config.server.isCluster, 14 | https:config.server.https, 15 | headers:config.server.headers, 16 | httpsKeyContent:config.server.https.key ? fs.readFileSync(__dirname + "/" + config.server.https.key) :null, 17 | httpsCaContent:config.server.https.ca ? fs.readFileSync(__dirname + "/" + config.server.https.ca) :null, 18 | }, 19 | api:{ 20 | route:config.api.route, 21 | modules:config.api.modules 22 | }, 23 | serviceRegistry:config.serviceRegistry 24 | 25 | }; 26 | 27 | } 28 | module.exports=Config; 29 | -------------------------------------------------------------------------------- /service-signup/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "server":{ 3 | "id":"ServiceSignup", 4 | "port":8082, 5 | "isCluster":true, 6 | "https":{ 7 | "isEnabled":false, 8 | "key":"", 9 | "ca":"" 10 | }, 11 | "headers":[ 12 | {"name":"Access-Control-Allow-Origin","value":"*"}, 13 | {"name":"Access-Control-Allow-Headers","value":"Origin, X-Requested-With, Content-Type, Accept"}, 14 | {"name":"Access-Control-Allow-Methods","value":"GET,PUT,POST,DELETE,OPTIONS"} 15 | ] 16 | }, 17 | "api":{ 18 | "route":"api", 19 | "modules":[ 20 | {"name":"signup", "route":"signup"} 21 | ] 22 | }, 23 | "serviceRegistry":{ 24 | "watchDog":{ 25 | "isEnabled":false, 26 | "timer":30000 27 | }, 28 | "database":{ 29 | "name":"my_mongo_db", 30 | "user":"my_mongo_db_user", 31 | "password":"my_mongo_db_password", 32 | "host":"my_mongo_db_host", 33 | "port":27017 34 | } 35 | } 36 | } 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /service-signup/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MicroNodeService", 3 | "version": "0.0.1", 4 | "description": "Micro Node Tutorial", 5 | "author": { 6 | "name": "Domenico Vacchiano", 7 | "email": "info@domenicovacchiano.com", 8 | "url": "http://www.domenicovacchiano.com" 9 | }, 10 | "homepage": "http://www.domenicovacchiano.com/", 11 | "repository": { 12 | "type": "git", 13 | "url": "" 14 | }, 15 | 16 | "engines": { 17 | "node": ">= 0.6.0", 18 | "npm": ">= 1.0.0" 19 | }, 20 | 21 | "dependencies": { 22 | "express": "^4.13.4", 23 | "body-parser":"^1.15.1", 24 | "request":"^2.72.0", 25 | "morgan": "^1.7.0", 26 | "network-address": "^1.1.0", 27 | "micro-node-net-lib":"git@github.com:alchimya/micro-node-net-lib.git", 28 | "micro-node-service-registry-lib":"git@github.com:alchimya/micro-node-service-registry-lib.git" 29 | }, 30 | "private": true, 31 | "scripts": { 32 | "start": "node server.js" 33 | }, 34 | "main": "server.js" 35 | } 36 | -------------------------------------------------------------------------------- /service-signup/server.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 07/07/16. 3 | */ 4 | 5 | var config= require ('./config')(), 6 | address = require('network-address'), 7 | express=require('express'), 8 | debug = require('debug')('http'), 9 | bodyParser = require('body-parser'), 10 | morgan= require('morgan'), 11 | cluster = require('cluster'), 12 | numCPUs = require('os').cpus().length, 13 | netLib = require ('micro-node-net-lib'), 14 | configServer= { 15 | server:{ 16 | port:config.server.port 17 | }, 18 | https:{ 19 | isEnabled:config.server.https.isEnabled, 20 | key:config.server.httpsKeyContent, 21 | ca:config.server.httpsCaContent 22 | }, 23 | express:{ 24 | app:null 25 | }, 26 | exitHandlers:["exit","SIGINT","SIGTERM"] 27 | } 28 | server = netLib.server(configServer), 29 | serviceRegistry = require ('micro-node-service-registry-lib')({ 30 | name:config.serviceRegistry.database.name, 31 | user:config.serviceRegistry.database.user, 32 | password:config.serviceRegistry.database.password, 33 | host:config.serviceRegistry.database.host, 34 | port:config.serviceRegistry.database.port, 35 | connectionPool:config.serviceRegistry.database.connectionPool 36 | }); 37 | 38 | if (cluster.isMaster && config.server.isCluster) { 39 | 40 | debug("cpus:" + numCPUs); 41 | for (var i = 0; i < numCPUs; i++) { 42 | cluster.fork(); 43 | } 44 | cluster.on('exit', function(worker, code, signal) { 45 | console.log("cluster exit"); 46 | debug('Worker %d died with code/signal %s. Restarting worker...', worker.process.pid, signal || code); 47 | cluster.fork(); 48 | }); 49 | 50 | } else { 51 | 52 | var app=express(); 53 | app.use(bodyParser.urlencoded({ extended: true })); 54 | app.use(bodyParser.json()); 55 | app.use(morgan('dev')); 56 | configServer.express.app = app; 57 | 58 | //header(s) setting 59 | app.all('/*', function(req, res, next) { 60 | config.server.headers.forEach(function(item) { 61 | //console.log(item); 62 | res.header(item.name, item.value); 63 | }); 64 | next(); 65 | }); 66 | 67 | //load API route(s) 68 | config.api.modules.forEach(function(item) { 69 | //console.log(item); 70 | app.use('/' + config.api.route + "/" + item.route, require('./' + item.name)); 71 | }); 72 | 73 | server.create(function (err,server) { 74 | if (!err){ 75 | //load API route(s) and register services 76 | registerServer(); 77 | if (config.serviceRegistry.watchDog.isEnabled){ 78 | setInterval(function(){ 79 | registerServer(); 80 | }, config.serviceRegistry.watchDog.timer); 81 | } 82 | console.log("### " + config.server.id + " -> " + (config.server.https ? "HTTPS" : "HTTP") + " Server started on port " + 83 | config.server.port + (config.server.isCluster ? " cluster worker " + cluster.worker.id : "")); 84 | } else { 85 | debug(err); 86 | } 87 | }); 88 | 89 | server.registerExitHandler(function () { 90 | unregisterServer(); 91 | debug("Server Exit Handled"); 92 | }); 93 | 94 | var registerServer=function () { 95 | if (!config.server.isCluster || cluster.worker.id===1){ 96 | debug("registerServer"); 97 | config.api.modules.forEach(function(item) { 98 | //console.log(item); 99 | app.use('/' + config.api.route + "/" + item.route, require('./' + item.name)); 100 | serviceRegistry.register({ 101 | serviceId:config.server.id, 102 | serviceHost:address(), 103 | servicePort:config.server.port, 104 | serviceProtocol:config.server.https.isEnabled ? "https" : "http", 105 | endpointId:item.name, 106 | endpointPath:config.api.route + "/" + item.route 107 | }, function (err,item) { 108 | if (err){ 109 | console.log(app.next()) 110 | debug(err); 111 | } 112 | }); 113 | }); 114 | } 115 | }; 116 | var unregisterServer = function () { 117 | if (!config.server.isCluster || cluster.worker.id===1){ 118 | debug("unregisterServer"); 119 | config.api.modules.forEach(function(item) { 120 | serviceRegistry.unregister(config.server.id,item.name,function (err,item) { 121 | if (err){ 122 | //TODO update flag inactive? 123 | console.log(err); 124 | } 125 | if (!config.server.isCluster){ 126 | process.exit(); 127 | } 128 | }); 129 | }); 130 | } 131 | }; 132 | 133 | 134 | } 135 | -------------------------------------------------------------------------------- /service-signup/signup.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by domenicovacchiano on 07/07/16. 3 | */ 4 | 5 | var express = require('express'), 6 | router = express.Router(), 7 | debug = require('debug')('http'), 8 | config= require ('./config')() 9 | 10 | router.post('/', function (req, res,next) { 11 | return res.status(200).send("## Signup -> This is just a test response ;-)"); 12 | }); 13 | 14 | module.exports = router; --------------------------------------------------------------------------------