Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable ZipKin and Swagger #7

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 40 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Acme Air in NodeJS

An implementation of the Acme Air sample application for NodeJS. This implementation can support multiple datastores, can run in several application modes, and can support running on a variety of runtime platforms including standalone bare metal system, Virtual Machines, docker containers, IBM Bluemix, IBM Bluemix Container Service.
An implementation of the Acme Air benchmark application for NodeJS. This implementation can support multiple datastores; run in several application modes; offer oeration insights and API management capabilities. It also supports running on a variety of runtime platforms including stand-alone bare-metal system, Virtual Machines, docker containers, IBM Bluemix, IBM Bluemix Container Service, Mesos through Marathon...

## Content

Expand All @@ -26,16 +26,21 @@ One NodeJS application. The default mode.

#### Micro-Service

Main NodeJS application delegates to authorization service NodeJS application hosted on host:port, defined in AUTH_SERVICE
Main NodeJS application delegates to authorization service NodeJS application hosted on host:port, defined in AUTH_SERVICE.


### Application Run Platforms

* [Bluemix Instructions] (README_Bluemix.md)
* [Docker Instructions] (README_Docker.md)
* [Bluemix Container Service Instructions] (README_Bluemix_Container.md)
* [Bluemix CloudFoudry Instructions](README_Bluemix.md)
* [Docker on Kubernetes and Mesos Instructions](README_Docker.md)
* [Obsolete. Bluemix Container Service Instructions](README_Bluemix_Container.md)


### Insights and API Management

* Enable zipkin tracing with ENABLE_ZIPKIN
* Enable Swagger API exploring with ENABLE_SWAGGER

## How to get started

Assume MongoDB started on 127.0.0.1:27017
Expand All @@ -51,24 +56,44 @@ Assume MongoDB started on 127.0.0.1:27017

### Run Acmeair in Micro-Service on Local

node authservice-app.js
node authservice_app.js
set AUTH_SERVICE=localhost:9443 or export AUTH_SERVICE=localhost:9443
node app.js

### Run Acmeair in Micro-Service with Netflix Hystrix Stream enabled on Local

node authservice-app.js
node authservice_app.js
set AUTH_SERVICE=localhost:9443 or export AUTH_SERVICE=localhost:9443
set enableHystrix=true or export enableHystrix=true

node app.js


### Enable ZipKin tracing for all the scenarios

export ENABLE_ZIPKIN=true
export ZIPKIN_HOST= your Zipkin collector host

#### Known issue

* [If you hit ipv6 issue](https://github.com/tryfer/node-tryfer/pull/38), you can work around it by clone the branch to replace your local node-modules

### Enable Swagger API definition for all the scenarios

export ENABLE_SWAGGER=true

* [The Swagger API definition shown as default](dist/acmeair/swagger.json). [The Swagger API definition for Authentication Service](dist/acmeair/swagger-auth.json)
* The swagger-ui is at http://host:port/v1

#### Known issue

* The Swagger API needs improvements. Especially on how to model sessionid in cookies.

### Access Application

http://localhost:9080/

Load Database
Load the database (under Configure the Acme Air environment)
preload 10k customers uid[0..9999]@email.com:password, 5 days' flights. Defined in loader/loader-settings.json
Login
Flights
Expand All @@ -91,11 +116,15 @@ Name | Default | Meaning
--- | --- | ---
dbtype | mongo | You can switch between mongo,cloudant,cassandra for datastore choices. When running on Bluemix, dbtype is automactially discovered from the service the application is bound to.
AUTH_SERVICE | | By default, there is only one main NodeJS application for all logics. When defined, in the format of host:port, it enables Micro-Service mode, main NodeJS application delegates to authorization service NodeJS application hosted on host:port.
enableHystrix | false | setting it to true will enable hystrix stream available at /rest/api/hystrix.stream
enableHystrix | false | when set to true, it will enable hystrix stream available at /rest/api/hystrix.stream
MONGO_URL||Mongo database URL. Take precedence over other settings
CLOUDANT_URL||Cloudant database URL. Take precedence over other settings
CASSANDRA_CP||Cassandra Contact Points. Take precedence over other settings
CASSANDRA_KS||Cassandra keyspace. Take precedence over other settings
ENABLE_ZIPKIN||when set to true, it will enable ZipKin integration
ZIPKIN_HOST|| zipkin collector scribe host. Take precedence over other settings
ZIPKIN_PORT|| zipkin collector scribe port. Take precedence over other settings
ENABLE_SWAGGER||when set to true, it will enable Swagger API exploring. The swagger-ui is at host:port/v1

### Configuration for Runtime

Expand All @@ -116,7 +145,8 @@ cloudant_httpclient.soTimeout | 5000 | Cloudant http client socket timeout
cloudant_httpclient.connectionTimeout | 5000 | Cloudant http client connection timeout
cassandra_contactPoints||Cassandra contact points
cassandra_keyspace|acmeair_keyspace|Cassandra keyspace

zipkin_host|127.0.0.1 | zipkin collector scribe host
zipkin_port|9410 | zipkin collector scribe port

* When running on Bluemix, datasource url will be read from bound service information.
* For Cloudant, you need to [follow instruction](document/DDL/cloudant.ddl) to create database and define search index.
Expand Down
2 changes: 1 addition & 1 deletion README_Bluemix.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Acmeair NodeJS on Bluemix
## Acmeair NodeJS on Bluemix Cloud Foundry

Assume you have access to [Bluemix](https://console.ng.bluemix.net).

Expand Down
61 changes: 53 additions & 8 deletions README_Docker.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,64 @@
## Acmeair NodeJS on Docker

Docker image is automatically built on [docker hub](https://hub.docker.com/r/yanglei99/acmeair-nodejs/builds/).

Assume you have [installed Docker and stared Docker daemon](https://docs.docker.com/installation/)

### Run MongoDB container
### To Run on Mesos or Mesosphere DC/OS

You can revise and run the predefined [marathon json](document/marathon) on Mesos cluster.

curl -i -H 'Content-Type: application/json' -d@document/marathon/$marathonJob.json $marathonIp:8080/v2/apps
or
dcos marathon app add document/marathon/$marathonJob.json

You can submit the workload run using [marathon json](document/marathon/acmeair_web_workload.json)


### To Run on Kubernetes

Verified on [Minikube on OSX](https://kubernetes.io/docs/tutorials/stateless-application/hello-minikube/)

kubectl run acmeair-mongo --image=mongo --port=27017
kubectl expose deployment/acmeair-mongo --port 27017

kubectl run acmeair-web --image=yanglei99/acmeair-nodejs --port=9080 --env "MONGO_URL=mongodb://acmeair-mongo:27017/acmeair"
kubectl expose deployment/acmeair-web --type="NodePort" --port 9080

# access the web front
minikube service acmeair-web

You can also use [yaml files](document/k8s) to create everything together. Also verified on [IBM Cloud Container Service](https://console.bluemix.net/docs/containers/cs_apps.html#cs_apps) with [Cluster Federation](https://github.com/yanglei99/kubernetes_ibmcloud/tree/master/federation)

# Monolithic
kubectl create -f document/k8s/acmeair-web.yaml

# Micro-Services
kubectl create -f document/k8s/acmeair-ms.yaml

# Micro-Services with Ingress
kubectl create -f document/k8s/acmeair-ms-ingress.yaml

# Micro-Service with Cluster Federation
kubectl create -f document/k8s/acmeair-ms-fed.yaml



### To Build and Run Docker image manually


#### Run MongoDB container

docker run --name mongo_001 -d -P mongo

docker ps
to get mapped port of 27017, e.g. 49177

### Create a docker image for Acmeair and run Acmeair container
#### Create a docker image for Acmeair and run Acmeair container

docker build -t acmeair/web .


#### Run Acmeair Container in Monolithic
##### Run Acmeair Container in Monolithic

docker run -d -P --name acmeair_web_001 --link mongo_001:mongo acmeair/web

Expand All @@ -24,7 +67,7 @@ Assume you have [installed Docker and stared Docker daemon](https://docs.docker.
docker run -d -P --name acmeair_web_002 -e MONGO_URL=mongodb://192.168.59.103:49177/acmeair acmeair/web


#### Run Acmeair Containers in Micro-Service
##### Run Acmeair Containers in Micro-Service

docker run -d -P --name acmeair_web_003 -e APP_NAME=authservice_app.js --link mongo_001:mongo acmeair/web

Expand All @@ -36,7 +79,7 @@ Assume you have [installed Docker and stared Docker daemon](https://docs.docker.
You can also use the MONGO_URL location as Monolithic case


#### Run Acmeair Containers in Micro-Service with Netflix Hystrix Stream enabled
##### Run Acmeair Containers in Micro-Service with Netflix Hystrix Stream enabled

docker run -d -P --name acmeair_web_005 -e APP_NAME=authservice_app.js --link mongo_001:mongo acmeair/web

Expand All @@ -48,15 +91,15 @@ Assume you have [installed Docker and stared Docker daemon](https://docs.docker.
You can also use the MONGO_URL location as Monolithic case


#### Get application port
##### Get application port

docker ps
get the mapped port for 9080 to get the application url. e.g. http://192.168.59.103:49178

If hystrix is enabled, it is available at : http://192.168.59.103:49178/rest/api/hystrix.stream


#### Note:
##### Note:

* For Cloudant, you can use CLOUDANT_URL for datasource location

Expand All @@ -65,6 +108,8 @@ Assume you have [installed Docker and stared Docker daemon](https://docs.docker.

### Create a docker image for Jmeter workload

[workload docker image](document/workload/Dockerfile)

docker build -t acmeair/workload document/workload

### Run Jmeter workload against Acme Air runtime
Expand Down
12 changes: 6 additions & 6 deletions acmeaircmd/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,29 @@ module.exports = function (authService,settings) {
hystrix.hystrixStream(request, response);
}

module.createSession = function(userid, callback /* (error, sessionId) */){
module.createSession = function(requestHeader, userid, callback /* (error, sessionId) */){
command.getCommand("createSession", authService.createSession, function (error, cmd){
if (error) callback (error, null);
else{
cmd.execute(userid, callback);
cmd.execute(requestHeader,userid, callback);
}
})
}

module.validateSession = function (sessionid, callback /* (error, userid) */){
module.validateSession = function (requestHeader, sessionid, callback /* (error, userid) */){
command.getCommand("validateSession", authService.validateSession, function (error, cmd){
if (error) callback (error, null);
else{
cmd.execute(sessionid, callback);
cmd.execute(requestHeader, sessionid, callback);
}
})
}

module.invalidateSession = function ( sessionid, callback /* (error) */){
module.invalidateSession = function (requestHeader, sessionid, callback /* (error) */){
command.getCommand("invalidateSession", authService.invalidateSession, function (error, cmd){
if (error) callback (error, null);
else{
cmd.execute(sessionid, callback);
cmd.execute(requestHeader,sessionid, callback);
}
})
}
Expand Down
23 changes: 10 additions & 13 deletions acmeairhttp/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module.exports = function (settings) {
var module = {};
var http = require('http')

var contextRoot = settings.authContextRoot || "/acmeair-auth-service/rest/api"
var contextRoot = settings.authContextRoot
var location = process.env.AUTH_SERVICE;

var hostAndPort = location.split(":");
Expand All @@ -27,16 +27,15 @@ module.exports = function (settings) {
var logger = log4js.getLogger('acmeairhttp');
logger.setLevel(settings.loggerLevel);

module.createSession = function (userid, callback /* (error, sessionId) */){
module.createSession = function (requestHeader, userid, callback /* (error, sessionId) */){
requestHeader['Content-Type']='application/json'
var path = contextRoot+"/authtoken/byuserid/" + userid;
var options = {
hostname: hostAndPort[0],
port: hostAndPort[1] || 80,
path: path,
method: "POST",
headers: {
'Content-Type': 'application/json'
}
headers: requestHeader
}

logger.debug('createSession options:'+JSON.stringify(options));
Expand All @@ -63,17 +62,16 @@ module.exports = function (settings) {
}


module.validateSession = function (sessionid, callback /* (error, userid) */){
module.validateSession = function (requestHeader, sessionid, callback /* (error, userid) */){
requestHeader['Content-Type']='application/json'

var path = contextRoot+"/authtoken/" + sessionid;
var options = {
hostname: hostAndPort[0],
port: hostAndPort[1],
path: path,
method: "GET",
headers: {
'Content-Type': 'application/json'
}
headers: requestHeader
}

logger.debug('validateSession request:'+JSON.stringify(options));
Expand All @@ -97,16 +95,15 @@ module.exports = function (settings) {
request.end();
}

module.invalidateSession = function ( sessionid, callback /* (error) */){
module.invalidateSession = function (requestHeader, sessionid, callback /* (error) */){
requestHeader['Content-Type']='application/json'
var path = contextRoot+"/authtoken/" + sessionid;
var options = {
hostname: hostAndPort[0],
port: hostAndPort[1],
path: path,
method: "DELETE",
headers: {
'Content-Type': 'application/json'
}
headers: requestHeader
}
logger.debug('invalidateSession request:'+JSON.stringify(options));
var request = http.request(options, function(response){
Expand Down
39 changes: 35 additions & 4 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ logger.setLevel(settings.loggerLevel);

// disable process.env.PORT for now as it cause problem on mesos slave
var port = (process.env.VMC_APP_PORT || process.env.VCAP_APP_PORT || settings.port);
var host = (process.env.VCAP_APP_HOST || 'localhost');
var host = (process.env.VCAP_APP_HOST || '127.0.0.1');

logger.info("host:port=="+host+":"+port);

Expand Down Expand Up @@ -62,9 +62,6 @@ if(process.env.VCAP_SERVICES){
}
logger.info("db type=="+dbtype);

var routes = new require('./routes/index.js')(dbtype, authService,settings);
var loader = new require('./loader/loader.js')(routes, settings);

// Setup express with 4.0.0

var app = express();
Expand All @@ -73,6 +70,40 @@ var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var cookieParser = require('cookie-parser')

// enabled zipkin or not

var enableZipkin = process.env.ENABLE_ZIPKIN
var zipkin
if (enableZipkin == "true")
{
var zport = (process.env.ZIPKIN_PORT || settings.zipkin_port);
var zhost = (process.env.ZIPKIN_HOST || settings.zipkin_host);
logger.info("zipkin collector host:port=="+zhost+":"+zport);

var zipkin = require("express-zipkin").client;
zipkin.start({
scribeClientAddress: zhost
, scribeClientPort: zport
, rpcName: "acmeair-nodejs-web"
, scribeStoreName: "zipkin"
, maxTraces: 50
, serverAddress: host
, serverPort: port
});
app.all(settings.contextRoot+"/*", zipkin.trace);
}

//enabled Swagger or not

if ( process.env.ENABLE_SWAGGER == "true")
{
var swagger = new require("./swagger.js")(express,app, host,port,settings).config();
}

var routes = new require('./routes/index.js')(dbtype, authService,settings, zipkin);
var loader = new require('./loader/loader.js')(routes, settings);


app.use(express.static(__dirname + '/public')); // set the static files location /public/img will be /img for users
if (settings.useDevLogger)
app.use(morgan('dev')); // log every request to the console
Expand Down
Loading