Microservices am Beispiel von Seneca




English version
Navigation mit Esc, und
![johannes](images/johannes.png) ### [Johannes Hoppe](http://JohannesHoppe.de)
## Agenda
  •  Vorstellung  Microservice Architekturen
  •  Einführung  Seneca - a Micro-Services toolkit for Node.js
  •  Angerissen  Docker - an open platform for distributed apps
### Microservices ![img](images/micro-service-architecture.png)

1

### 1 Anwendung = 1 Prozess
  • Monolith:  Code ist möglichst zentral an einem Ort
  • Technologien:  ein Stack (z.B. MSSQL / C# / HTML5 / JavaScript)
  • Mehr Features:  mehr LOC
  • Dokumentation:  Betriebshandbuch essenziell
  • Deployment:  alles auf einmal, Wartungsfenster
  • Schichtenarchitektur
         Generalisierung eigene Frameworks (gefährlich!)
#### ... ich habe in meinem Entwicklerleben
schon an vielen Monolithen kräftig mitgewirkt! Das ist alles im Grunde nicht schlimm, aber...
## Time to Market!





uvm. verwenden Microservices
In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. Martin Fowler

n

### 1 Anwendung = n Services
  • Komponenten:  via Services, lose Kopplung
  • Technologien:  verschiedene Technologie-Stacks möglich
  • Mehr Features:  falls möglich, neuer Service
  • Dokumentation:  (implizit) durch Schnittstellen
  • Deployment:  jeder Service unabhängig

?

Moment! Ist das nicht eine # SOA (__S__ervice-__O__rientierte __A__rchitektur)
# SOA ### +das beste aus dem Web
  • z.B.
  • HTTP / REST / WebHooks / WebSockets - kein SOAP!
  • vielleicht NoSQL
  • CI, DevOps, Cloud, Docker,

µ


*

wenig Code pro Service

*

~ 100 LOC



[sagt Fred George](http://livestream.com/websummit/DeveloperStage2013/videos/33534085)
![img](images/logo-seneca.png)
### Vorher nicht __asynchron__, keine lose Kopplung ```js contenteditable // app.js var discountService = require('./discount-service.js'); var customerId = 121; var result = discountService.calculateDiscount(customerId); console.log('Discount for customer:', result.discount, '%'); ```
```js contenteditable // discount-service.js module.exports = { // returns applicable discount in % calculateDiscount: function(customerId) { return { discount: (customerId _LT_ 100) ? 10 : 5 } } }; ``` [Demo](https://github.com/JohannesHoppe/Presentations2015/tree/gh-pages/Microservices-Seneca/example/01_OrderWithDiscount)
### Installation
```cmd contenteditable cmd white $ npm install seneca $ node var seneca = require('seneca')(); ```
# ???
## ```javascript contenteditable if (customer.Id == 1) { /* :-( */ } else if (customer.Id == 2 _AMP__AMP_ customer.FirstName == 'Hans') { /* :-( */ } else { /* :-( */ } ```
Beispiel ### Discount für Kunden ermitteln
Nachricht von CheckoutService: ```javascript contenteditable { command: 'discount', customer: { /* Kunde */ }, products: [ { /* Produkt1 */ }, { /* Produkt2 */ } ] } ```
###### Beispiel ### Discount Service
Reagiert, wenn es eine Nachricht mit dem Pattern ```javascript contenteditable { command: 'discount' } ``` gibt. Er ignoriert alle anderen Nachrichten.
Beispiel ### VIP-Kunden Discount Service
Reagiert, wenn es eine Nachricht mit dem Pattern ```javascript contenteditable { command: 'discount', customer: { customerId: 2 } } ``` gibt. Dieses Pattern wird gegenüber Discount Service bevorzugt.
# !
### Pattern + Action seneca.add(pattern, action): __asynchron__ ```js contenteditable // app.js var seneca = require('seneca')(); seneca.use('./discount-service.js'); var customerId = 121; seneca.act({ role: 'discount-service', cmd: 'calculateDiscount', customerId: customerId }, function (e, result) { console.log('Discount for customer:', result.discount, '%'); }); ``` ```js contenteditable // discount-service.js module.exports = function() { // returns applicable discount in % var calculateDiscount = function(args, done) { done(null, { discount: (args.customerId _LT_ 100) ? 10 : 5 }); }; this.add({ role: 'discount-service', cmd: 'calculateDiscount' }, calculateDiscount); }; ``` [Demo2](https://github.com/JohannesHoppe/Presentations2015/tree/gh-pages/Microservices-Seneca/example/02_OrderWithDiscount_actions)
### Tests super einfach ```js contenteditable var assert = require('should'), seneca = require('seneca'); describe('discount-service', function () { it('should give older customers a 10% discount', function (done) { seneca({ errhandler: done }) .use('../discount-service.js') .act('role:discount-service, cmd:calculateDiscount, customerId: 5', function (err, result) { result.discount.should.equal(10); done(); }); }); }); ```
### seneca-transport µservice hier ```js contenteditable // act as a server seneca.listen(); // act as a client seneca.client(); ```
[Demo3](https://github.com/JohannesHoppe/Presentations2015/tree/gh-pages/Microservices-Seneca/example/03_OrderWithDiscount_microservices)
```cmd $ curl http://localhost:7777/act --data "{ \"role\": \"discount-service\", \"cmd\": \"calculateDiscount\", \"customerId\": 5 }" ```
## Seneca in a nutshell * [use-plugin](https://github.com/rjrodger/use-plugin) ersetzt require() * Actions == pattern matching == JSON serializable * easy wiring

[Beginner's Guide to Seneca.js](http://jakepruitt.com/2015/02/09/beginners-guide-to-seneca-js.html)
### Tipps * [seneca-web](https://github.com/rjrodger/seneca-web) schickere URL routes für [express](http://expressjs.com/) * [chairo](https://github.com/hapijs/chairo) volle Integration in [hapi](https://github.com/hapijs/hapi) * [Plugins](http://senecajs.org/plugins.html), Plugins, Plugins
![img](images/logo-docker-color.png)
## [Boot2Docker](https://docs.docker.com/installation/windows/) Docker Client on  
#### Node.js OnBuild Docker Image ``` # Dockerfile FROM node:0.10.35-onbuild EXPOSE 3000 ``` ```cmd style=font-size:1em $ boot2docker start $ docker build --tag="app-server" . $ docker run -it --rm --name my-microservice app-server ```
[OnBuild Docker Image](https://github.com/docker-library/node/blob/master/0.10/onbuild/Dockerfile) | [build](https://docs.docker.com/reference/commandline/cli/#build) | [run](https://docs.docker.com/reference/commandline/cli/#run)
## Docker on Azure
* [Verwenden der Docker-VM-Erweiterung über die plattformübergreifende Azure-Oberfläche (xplat-cli)](http://azure.microsoft.com/documentation/articles/virtual-machines-docker-with-xplat-cli/)
oder

* [Verwenden der Docker-VM-Erweiterung mit dem Azure-Portal](http://azure.microsoft.com/documentation/articles/virtual-machines-docker-with-portal/)
## Downloads ![tools](images/icon_file.png) #### [github.com/JohannesHoppe/Presentations2015](https://github.com/JohannesHoppe/Presentations2015/)
# Danke!
*  [johanneshoppe.de](http://johanneshoppe.de) *  [@JohannesHoppe](https://twitter.com/JohannesHoppe) *  [Johannes.Hoppe](https://www.facebook.com/johannes.hoppe)

Created by Johannes Hoppe | Print PDF