Cloud Native Node JS Express Reactive Microservice Starter Template (REST/GraphQL)This project provides complete Node JS / Typescript based microservices template with all that will be needed features for production deployment , monitoring , debugging , logging , security , CI/CD. Reactive extensions based samples are added as well to demonstrate how this can be used for building a microservice API edge-service , a backend for frontend or use it as a base for building any kind of microservice.
See REST API /examples/{id}
{
"pid": 3984,
"hostname": "LP-507B9DA1D355",
"level": 30,
"time": 1515813665734,
"0": {
"socket": 5.656709999995655,
"lookup": 186.8375229999947,
"connect": 389.5646870000055,
"response": 594.8022639999981,
"end": 599.1270230000082
},
"v": 1
}
http://localhost:3000/api-docs/Api.yaml
http://localhost:3000/api-docs/
curl http://localhost:3000/api/v1/starwars/people/1
{
name: "Luke Skywalker",
height: "172",
mass: "77",
hair_color: "blond",
skin_color: "fair",
eye_color: "blue",
birth_year: "19BBY",
gender: "male",
homeworld: {
name: "Tatooine",
rotation_period: "23",
orbital_period: "304",
diameter: "10465",
climate: "arid",
gravity: "1 standard",
terrain: "desert",
surface_water: "1",
population: "200000",
residents: [
"http://swapi.co/api/people/1/",
"http://swapi.co/api/people/2/",
"http://swapi.co/api/people/4/",
"http://swapi.co/api/people/6/",
"http://swapi.co/api/people/7/",
"http://swapi.co/api/people/8/",
"http://swapi.co/api/people/9/",
"http://swapi.co/api/people/11/",
"http://swapi.co/api/people/43/",
"http://swapi.co/api/people/62/"
],
films: [
"http://swapi.co/api/films/5/",
"http://swapi.co/api/films/4/",
"http://swapi.co/api/films/6/",
"http://swapi.co/api/films/3/",
"http://swapi.co/api/films/1/"
],
created: "2014-12-09T13:50:49.641000Z",
edited: "2014-12-21T20:48:04.175778Z",
url: "http://swapi.co/api/planets/1/"
},
films: [
"http://swapi.co/api/films/2/",
"http://swapi.co/api/films/6/",
"http://swapi.co/api/films/3/",
"http://swapi.co/api/films/1/",
"http://swapi.co/api/films/7/"
],
species: [
"http://swapi.co/api/species/1/"
],
vehicles: [
"http://swapi.co/api/vehicles/14/",
"http://swapi.co/api/vehicles/30/"
],
starships: [
"http://swapi.co/api/starships/12/",
"http://swapi.co/api/starships/22/"
],
created: "2014-12-09T13:50:51.644000Z",
edited: "2014-12-20T21:17:56.891000Z",
url: "http://swapi.co/api/people/1/"
}
curl http://localhost:3000/api/v1/starwars/people/1?data(name,gender,homeworld(gravity,population))
{
"data": {
"name": "Luke Skywalker",
"gender": "male",
"homeworld": {
"gravity": "1 standard",
"population": "200000"
}
}
}
GraphQL support has been added based on the apollo framework and a reference implementation (including the starwars apis from swapi.co)
Access the graphql playground from http://localhost:3000/playground
Access the graphiql tool from http://localhost:3000/graphiql
GraphQL API tracing (configurable)
Dataloader for caching and batching
Multiple samples added Dataloader Enabled
List of Queries (see schema details for complete list)
quoteOfTheDay: String
random: Float
examples: [ExampleType] <-- JWT Authentication. Please read the JWT Security section for details
example(id: Int): ExampleType
blog(id: Int) (Paginated query)
rollThreeDice: [Int]
peopleWithPlanet(id: Int): PeopleWithPlanetType (Uses RxJS to combine results from 2 APIs)
peopleDS(id: Int): PersonType (Based on REST DataSource)
people(id: Int): PersonType (Based on data loader)
planet(id: Int): PlanetType
starship(id: Int): StarshipType
peopleList(keys: [Int]): [PersonType]
movie: MovieType
Sample Query Execution
Mutations
addExample(name: String!): ExampleType
addComment(comment: CommentInput!): Comment
login(email: String!,password: String!): UserType
Sample Mutation Execution
Subscriptions
Sample Subscription Execution
VSCode Debug Launch Configuration (Preconfigured Debug Launcher added)
Node Dashboard view added for telemetry during development process
Added NodeJS cluster mode (load balanced workers)
Master cluster setting up 4 workers...
Worker 2828 is online
Worker 2816 is online
Worker 13956 is online
Worker 3756 is online
up and running in development @: LP-507B9DA1D355 on port: 3000
up and running in development @: LP-507B9DA1D355 on port: 3000
up and running in development @: LP-507B9DA1D355 on port: 3000
up and running in development @: LP-507B9DA1D355 on port: 3000
While we build GraphQL based servers, there might a need to get data from other downstream GraphQL based API servers.
As an example the graphqlcool/graphql-request module has been used to demonstrate this, using graphqlcool demo graphQL api https://api.graph.cool/simple/v1/movies
API spec
query {
movie {
releaseDate
slug
actors {
name
}
}
}
{
"data": {
"movie": {
"releaseDate": "2010-08-28T20:00:00.000Z",
"slug": "inception",
"actors": [
{
"name": "Leonardo DiCaprio"
},
{
"name": "Ellen Page"
},
{
"name": "Tom Hardy"
},
{
"name": "Joseph Gordon-Levitt"
},
{
"name": "Marion Cotillard"
}
]
}
}
}
Install npm and nodeJS
npm version >= 3.xnode version >= 6.x
npm install
Variable | Description | Default Value |
---|---|---|
PORT | Server Port | 3000 |
LOG_LEVEL | Log Level (info,debug,error) | info |
SESSION_SECRET | String used for signing cookies | |
API_TIME_OUT | Default API Timeout (in milli secs) | 10000 |
TEST_TIME_OUT | Default Test Timeout (in milli secs) | 10000 |
JWT_AUTH | Enable/Disable JWT based API security | true |
RSA_PRIVATE_KEY_FILE | Sample RSA private key path | |
RSA_PUBLIC_KEY_FILE | Sample RSA public key path | |
TOKEN_EXPIRY_TIME | JWT Token expiry (Generated from /login ) | 1 hour (1h) |
STREAM_HYSTRIX | Enable/Disable Hystrix streaming server (true or false) | false |
CORS | Enable/Disable CORS on the server (true or false). Will work only in production build | false |
CLUSTER_MODE | Enable/Disable Node Clustering on the server (true or false) | false |
SWAGGER_API_DOCS_ROOT | Serves your Swagger API file(s) so they can be used with front-end tools like like Swagger UI, PostMan. | /api-docs/ |
GRAPHQL_SUBSCRIPTIONS | Enable/Disable GraphQL subscriptions (true or false) | true |
GRAPHQL_PLAYGROUND | Enable/Disable GraphQL Playground (true or false) | true |
GRAPHQL_TRACING | Enable/Disable GraphQL tracing (true or false) | true |
GRAPHQL_MOCK | Enable/Disable GraphQL Mock for unimplemented Interfaces(true or false) | true |
API_MOCK | Enable/Disable REST API Mock unimplemented routes(true or false) | true |
npm run dev
npm run compile
npm start
npm run compile
Press F5
npm run test
npm run itest:build
npm itest:run
http://localhost:3000/swagger
curl http://localhost:3000/metrics
http://localhost:3000/graphiql
http://localhost:3000/playground/
curl http://localhost:3000/healthcheck
├───public * Landing page for nxplorer server
├───screenshots * Sample screenshots
└───server * Server configuration and apis
| ├───api * REST APIs defined on the server
| │ ├───controllers * API controllers using RxJS, Inversify
| │ │ ├───examples * Examples controller
| │ │ ├───hystrix-demo * Hystrix demo controller
| │ │ ├───security * JWT login API controller
| │ │ ├───shop * Sample shop APIs with products, prices , inventory
| │ │ └───starwars * SWAPI controller
| │ ├───interfaces * Service interfaces
| │ ├───models * API data models
| │ └───services * Service API implementations
| ├───common * Server setup and configuration
| │ ├───config * Server configuration
| │ ├───constants * Inversify and other common identifier constants
| │ ├───interfaces * Common service interfaces
| │ ├───middleware * Custom middleware
| │ ├───models * Common API data models
| │ ├───services * Common service implementations
| │ └───swagger * Swagger API specification (YAML)
| | └───env.ts * DotENV configuration
| | └───server.ts * Express Server setup and configuration
| └───graphql * GraphQL APIs defined on the server
| | ├───dataloader * GraphQL data loader functions
| | ├───errors * GraphQL error handler
| | ├───schema * GraphQL Schema Types
| | ├───mocks * GraphQL Mock Resolvers
| | └───resolvers * GraphQL resolvers
| | └───setupSchema.ts * GraphQL schema configuration
| └───index.ts * Main Server entry point
├───helm * Helm chart deployment scripts
│ ├───charts *
│ └───templates *
└───backpack.config.js * Backpack configuration
└───package.json * npm dependencies
└───build.js * ShellJS utility build scripts
└───deploy-k8s.sh * Kubernetes deployment script
└───Dockerfile * Docker build file
└───docker-compose.yml * Docker build and run file
└───build-docker.bat|sh * Docker build file
└───itest.config.json * Jest integration test configuration
└───unit.config.json * Jest unit test configuration
└───tsconfig.json * typescript config
└───tslint.json * tslint config
└───.{profile}.env * externalized environment files based on profiles (development,test,production)
└───sonar-properties.json * sonarscanner|SonarQube configuration
└───jwtRS256.key|.key.pub * Sample JWT private and public keys used by the server
A sample implementation of UUID propogation has been added. This depends on a cookie 'UUID' to be set in the request object. The LogService will add the uuid to all logs it generates.
For example if 'UUID' is set to xxxx-dddd-ssss-wwww-ssss then calling the /shop/products API will produce
{
"pid": 13492,
"hostname": "LP-507B9DA1D355",
"level": 30,
"time": 1515859200496,
"uuid": "xxxx-dddd-ssss-wwww-ssss",
"fullUrl": "http://localhost:3000/api/v1/shop/products",
"statusCode": 200,
"responseTime": "1.187",
"v": 1
}
API_MOCK=true
in the .<Profile>.env
file . Note: For security this will not work in production mode even if API_MOCK
is set to true
swagger-express-middleware
module provides out of the box support for automated mock generationMock API
and with prefix /mock
.The sample has two main entities - cars and drivers. You can search , perform CRUD operations as well as upload and download images../build-docker.sh
./deploy-k8s.sh
release "nxplorerjs-microservice" deleted
NAME: nxplorerjs-microservice
LAST DEPLOYED: Fri Sep 22 22:10:58 2017
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/ConfigMap
NAME DATA AGE
nxplorerjs-microservice-starter 5 1s
==> v1/Service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nxplorerjs-microservice-starter 10.0.0.196 <nodes> 80:30316/TCP 1s
==> v1beta1/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nxplorerjs-microservice-starter 1 1 1 0 1s
NOTES:
1. Get the application URL by running these commands:
export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services nxplorerjs-microservice-nxplorerjs-microservice-starter)
export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
Express Microservice is deployed at http://192.168.99.100:30316/
npm run compile
npm run dash
mutation {
login(email: "tsukhu@nxplorer.com",
password:"admin",role:"ADMIN") {
id
role
email
jwt
}
}
{
"Authorization": "Bearer xxx.xxx.xxx"
}
curl -X POST "http://localhost:3000/api/v1/login" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"email\": \"test@gmail.com\", \"password\": \"pwd\", \"role\": \"admin\"}"
{
"idToken":
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYWRtaW4iLCJpYXQiOjE1MTQ4NjQ3ODMsImV4cCI6MTUxNDg2ODM4Mywic3ViIjoidGVzdEBnbWFpbC5jb20ifQ.hAEa6AL1Kxxxxxxx",
"expiresIn": "1h"
}
@controller('/examples', authMiddleware(<User>{ role: 'admin'}))
curl -X POST "http://localhost:3000/api/v1/login" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"email\": \"test@gmail.com\", \"password\": \"pwd\", \"role\": \"guest\"}"
{ today(format: "mmm-dd-yy") }
) - Here the format is based on the @date
scheme Directive , that takes the output of the resolver and formats the date before sending it out to the client{ examplesWithAuth { id name } }
- This is a variation to the examples
query mentioned in the section JWT GraphQL APIs. The difference here is that we use a @auth
directive to handle the authentication based on the role instead of hardcoding the implementation in the resolver. This is a much cleaner and decoupled from the resolver.examplesWithAuth: [ExampleType] @auth(requires: ADMIN)
uses the @auth
directive which will intercept the call check for an authenticated user with appropriate role. (Note: You need to run the login
mutation before and then set the HTTP Header with the Authorization token )x-no-compression
in the request headernpm run compile
docker-compose build
docker-compose up
localhost:3001/hystrix.stream
Assuming you have SonarQube 5.5.6 (LTS) installed
npm install --global sonar-scanner
)sonar-project.properties
file for the property sonar.host.url
to point to your SonarQube server. By default this assumes that the SonarQube server is running locally using the default portnpm run test
npm run sonar-scanner
Modify the package.json to set the appropriate version of the sonarQube
jestSonar": {
"reportPath": "reports",
"reportFile": "test-reporter.xml",
"indent": 4,
"sonar56x": true
}
Note: for Sonar 6.x turn sonar56x to “false” and that will generate the test report that is using the sonar 6 schema.
npm install -g loadtest
npm run start
loadtest http://localhost:3000/api/v1/examples/1 -t 20 -c 20
heroku create
git push heroku master
heroku open
or
// Configure glob patterns of file paths to exclude from linting
"tslint.exclude": "**/node_modules/**/*.ts"
MIT
部署单元 依赖方式 架构模式 微服务涉及的技术点 服务发现 服务目录 服务列表 配置中心 服务生命周期 变更,升级 服务依赖关系 链路跟踪 限流 降级 熔断 访问控制 为微服务而生的 Kubernetes Kubernetes 架构 Kubernetes Pod - Sidecar 模式 Kubernetes 支持微服务的一些特性 微服务集大成之 istio Kubernetes 架构 一个状态存
Build a NodeJS microservice and deploy it to Docker This is the repo example for the article. Stack We’ll use a simple NodeJS service with a MongoDB for our backend. NodeJS 7.5.0 MongoDB 3.4.2 Docker
microservice-app 微服务架构实战demo, 使用 go 语言技术栈,包含如下组件: 服务注册中心 etcd Api 网关 Feed 服务 Profile 服务 Topic 服务 监控组件: prometheus + grafana 跟踪组件: zipkin + elasticsearch 其中Feed, Profile, Topic 启动时会向etcd注册服务, Apigatewa
python-flask-microservice This is the code used in this series of articles: https://medium.com/p/building-microservices-with-python-part-i-5240a8dcc2fb https://medium.com/@ssola/building-microservices
我在我的微服务中定义了一个Kafka消费者。我已经部署了我的应用程序的5个实例。我已将ConvoltKafkaListenerContainerFactory中的并发参数设置为2。这是否意味着每个应用程序实例有2个消费者实例,或者我连接的整个主题有2个消费者实例?
我已经使用spring boot和Implement zuul proxy创建了微服务,所以当我通过zuul proxy调用url时,不知何故我的服务关闭了,我得到了com。netflix。祖尔。例外ZuulException 通用域名格式。netflix。祖尔。例外ZuuleException:组织转发错误。springframework。云netflix。祖尔。过滤器。路线带状路由过滤器。ha