Building Microservices using Hydra

Building Microservices using Hydra

A hands-on workshop for building Hydra based Node microservices. First presented at the NYC JavaScript @ FlatIron meetup. https://www.meetup.com/NYC-JavaScript-Flatiron/events/235932229/

E2e942d05d5ea93ad2eddd3394ffcd96?s=128

Carlos Justiniano

December 14, 2016
Tweet

Transcript

  1. 2.

    Prereqs • Your favorite text editor or: https://atom.io/ • Your

    favorite terminal app or: iTerm2 / Hyper.js • NodeJS: https://nodejs.org
 * Requires Node 6.2.1 or greater • Lastly, if you’re cruising along - help the person sitting next to you!
  2. 4.

    Microservices • Microservice: a process which is dedicated to doing

    a kind of thing really well • A distributed computing application - works across a network • Commonly implemented using ExpressJS and other lesser known frameworks
  3. 7.

    Monolithic • Pros: • easier to deploy • easier to

    test • Cons: • can become too large for anyone on the team to fully understand • can be fragile due to the fact that a single error can take down the entire system • can be difficult to modify as modules are tightly coupled • can be difficult to build using remote teams • often requires the same tech stack
  4. 8.

    Microservice • Pros: • collection of loosely connected services •

    easier / safer to modify • can be easy to deploy • can be easy to test since you’re focused on a particular set of functionality • can be built using different tech stacks • Cons: • can be difficult to test due to its distributed nature • routing endpoints can require more consideration • services may need to discover one another
  5. 9.

    Who builds microservices? • Amazon, Comcast, eBay, IBM, Google, Groupon,

    Microsoft, Netflix, Paypal, SoundCloud, Uber • … and lots of other companies
  6. 11.

    $ mkdir express-test $ cd express-test $ npm init {

    name app: index } $ npm install express ——save
  7. 12.

    $ vi index.js var express = require('express') var app =

    express() app.get('/', function (req, res) { res.send('Hello World!') }) app.listen(3000, function () { console.log('Example app listening on port 3000!') }) Cut & paste from: express-hello.js https://goo.gl/AVW0lG
  8. 14.

    What’s Hydra? • An NPM package that facilitates building distributed

    applications - such as microservices • It addresses distributed computing concerns so you won’t have to • Open Source project - released by Flywheel Sports • Related projects: hydra-express, hydra-router
  9. 15.

    Hydra features • Automated health and presence • Automated service

    discovery • Inter-service (P2P) communication with support for socket messaging and RESTful interfaces • Built-in load balancing and routing • Self registration with near zero configuration • Built-in job queues • Built on Node using native ES6 • Great with Docker
  10. 16.
  11. 17.
  12. 20.
  13. 21.

    $ vi index.js var hydraExpress = require('fwsp-hydra-express'); var config =

    require('./config.json'); function onRegisterRoutes() { var express = hydraExpress.getExpress(); var api = express.Router(); api.get('/', function(req, res) { res.send('Hello World!'); }); hydraExpress.registerRoutes({ '': api }); } hydraExpress.init(config, onRegisterRoutes); Cut & paste hydra-express-hello.js from: https://goo.gl/AVW0lG
  14. 22.

    $ vi config.json { "hydra": { "serviceName": "hello", "serviceIP": "",

    "servicePort": 3000, "serviceType": "", "serviceDescription": "", "redis": { "url": "172.16.0.2", "port": 6379, "db": 15 } } } Cut & paste config.json from: https://goo.gl/AVW0lG
  15. 24.
  16. 25.

    $ sudo npm install -g hydra-cli $ hydra-cli config redisUrl:

    172.16.0.2 redisPort: 6379 redisDb: 15
  17. 26.

    $ hydra-cli hydra-cli version 0.3.5 Usage: hydra-cli command [parameters] See

    docs at: https://github.com/flywheelsports/hydra-cli A command line interface for Hydra services Commands: help - this help list config - configure connection to redis config list - display current configuration health [serviceName] - display service health healthlog serviceName - display service health log message create - create a message object message send message.json - send a message nodes [serviceName] - display service instance nodes rest path [payload.json] - make an HTTP RESTful call to a service routes [serviceName] - display service API routes services [serviceName] - display list of services
  18. 29.

    $ vi config.json { "hydra": { "serviceName": "hello", "serviceIP": "",

    "servicePort": 0, "serviceType": "", "serviceDescription": "", "redis": { "url": "172.16.0.2", "port": 6379, "db": 15 } } } Cut & paste config.json from: https://goo.gl/AVW0lG Change from 3000 to 0
  19. 30.

    $ vi index.js var hydraExpress = require('fwsp-hydra-express'); var hydra =

    hydraExpress.getHydra(); var config = require('./config.json'); function onRegisterRoutes() { var express = hydraExpress.getExpress(); var api = express.Router(); api.get('/', function(req, res) { res.send({ msg: `hello from ${hydra.getServiceName()} - ${hydra.getInstanceID()}` }); }); hydraExpress.registerRoutes({ '': api }); } hydraExpress.init(config, onRegisterRoutes); Cut & paste
 hydra-express-hello-id.js from: https://goo.gl/AVW0lG
  20. 34.

    var hydraExpress = require('fwsp-hydra-express'); var config = require('./config.json'); function onRegisterRoutes()

    { var express = hydraExpress.getExpress(); var api = express.Router(); api.get('/', function(req, res) { res.send('Hello World!'); }); hydraExpress.registerRoutes({ '': api }); } hydraExpress.init(config, onRegisterRoutes); var express = require('express') var app = express() app.get('/', function (req, res) { res.send('Hello World!') }) app.listen(3000, function () { console.log('Example app listening on port 3000!') }) Side by side comparison
  21. 36.

    $ vi index.js var hydraExpress = require('fwsp-hydra-express'); var hydra =

    hydraExpress.getHydra(); var config = require('./config.json'); function onRegisterRoutes() { var express = hydraExpress.getExpress(); var api = express.Router(); api.get('/hello', function(req, res) { res.send({ msg: `hello from ${hydra.getServiceName()} - ${hydra.getInstanceID()}` }); }); hydraExpress.registerRoutes({ '/v1': api }); } hydraExpress.init(config, onRegisterRoutes); Cut & paste
 hydra-express-hello-route.js from: https://goo.gl/AVW0lG
  22. 40.

    $ tree hello-service hello-service !"" README.md !"" config # !""

    config.json # $"" sample-config.json !"" package.json !"" hello-service.js !"" routes # $"" hello-v1-routes.js !"" scripts # $"" docker.js $"" specs !"" helpers # $"" chai.js $"" test.js 5 directories, 9 files
  23. 41.

    $ cd hello-service $ vi config/config.json { "appServiceName": "hello-service", "environment":

    "development", "hydra": { "serviceName": "hello-service", "serviceIP": "", "servicePort": 0, "serviceType": "hello", "serviceDescription": "", "redis": { "url": "127.0.0.1", "port": 6379, "db": 15 } } }
  24. 45.

    $ npm start > hello-service@0.0.1 start /Users/cjustiniano/dev/hello-service > node hello-service.js

    INFO { event: 'info', message: 'Successfully reconnected to redis server' } INFO { event: 'start', message: 'hello-service (v.0.0.1) server listening on port 13664' } INFO { event: 'info', message: 'Using environment: development' } serviceInfo { serviceName: 'hello-service', serviceIP: '172.16.0.12', servicePort: 13664 }
  25. 49.

    $ vi {red/blue}-service.js hydraExpress.init(config.getObject(), version, () => { hydraExpress.registerRoutes({ '/v1/red':

    require('./routes/red-v1-routes') }); }) .then((serviceInfo) => { console.log('serviceInfo', serviceInfo); let hydra = hydraExpress.getHydra(); let message = hydra.createUMFMessage({ to: 'blue-service:[get]/v1/blue/', from: 'red-service:/', body: {} }); hydra.makeAPIRequest(message) .then((response) => { console.log('response', response); }); return 0; }) Cut & paste
 red-blue-service.js from: https://goo.gl/AVW0lG Edit “red” or “blue” words accordingly
  26. 50.

    INFO { event: 'info', message: 'Successfully reconnected to redis server'

    } INFO { event: 'start', message: 'red-service (v.0.0.1) server listening on port 13185' } INFO { event: 'info', message: 'Using environment: development' } serviceInfo { serviceName: 'red-service', serviceIP: '172.16.0.12', servicePort: 13185 } response { statusCode: 200, statusMessage: 'OK', statusDescription: 'Request succeeded without error', result: { msg: 'hello from blue-service - 088c270d30d36fdda37564de2cc68773' } }
  27. 51.
  28. 61.

    Resources! • Hydra project: https://github.com/flywheelsports • Hydra Intro: https://goo.gl/Ikcx4q •

    Getting Redis: https://goo.gl/S11jdo • Code used in this workshop: https://goo.gl/AVW0lG