├── .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 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
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 |
58 |
59 |
60 |
61 |
62 | true
63 |
64 |
65 |
66 |
67 |
68 |
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 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 | 1468269887291
128 |
129 |
130 | 1468269887291
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
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 | 
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 | 
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;
--------------------------------------------------------------------------------