├── .gitignore
├── LICENSE
├── README.md
├── bower.json
├── demo
└── load.js
├── gulpfile.js
├── package.json
└── src
├── images
├── 0.01ms-2kreq-10logs.png
├── 10x.png
├── adapters.jpg
├── alan-kay.jpg
├── arch-generic.png
├── arch-microservices.png
├── arch-modules.png
├── arch-mvc.png
├── arch-services.png
├── bloomrun.png
├── bloomrun.svg
├── cc_attribution.png
├── control.png
├── dragon-scroll.jpg
├── dynamo-strategy-one.png
├── dynamodb.png
├── ecosystem-impact.jpg
├── event-loop-gc.png
├── event-loop.png
├── fg-pino-after.png
├── fg-pino-before.png
├── fire.jpg
├── five-euro.jpg
├── hashring-sharding.png
├── heartbeat.png
├── hole.jpg
├── integration.jpg
├── kaboom.gif
├── lamp.jpg
├── loadbalacing.png
├── london.jpg
├── ludicrous.gif
├── magic.gif
├── matteo.png
├── me-nodeconf-eu-2013.jpg
├── monolith.jpg
├── nearform.svg
├── no-caching.png
├── node-desktop.png
├── nodeconfeu-2013-top.jpg
├── nodejs.png
├── penguins.gif
├── piggy.jpg
├── reqhashing-with-gateway.png
├── reqhashing.png
├── sharding.png
├── shifu.png
├── snail.jpg
├── spaceballs.jpg
├── speed.jpg
├── stonehenge.JPG
├── swim.png
├── tools.jpg
├── unfeasible.gif
├── upring-events.jpeg
├── upring.svg
└── wv.jpg
├── index.jade
├── scripts
└── main.js
└── styles
└── main.styl
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | bower_components
3 | dist
4 | pdf
5 | bespoke-theme-*
6 | .DS_Store
7 | profile-*
8 | .__browserify_string_empty.js
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Matteo Collina
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Scaling State
2 |
3 | [**UpRing**][upring] provides application-level sharding, based on node.js streams. UpRing allocates some resources to a node, based on the hash of a `key`, and allows you to query the node using a request response pattern (based on JS objects) which can embed streams.
4 |
5 | [**UpRing**][upring] simplifies the implementation and deployment of a cluster of nodes using a gossip membership protocol and a [consistent hashing](https://en.wikipedia.org/wiki/Consistent_hashing) scheme (see [swim-hashring](https://github.com/mcollina/swim-hashring)). It uses [tentacoli](https://github.com/mcollina/tentacoli) as a transport layer.
6 |
7 | ## View slides locally
8 |
9 | First, ensure you have the following installed:
10 |
11 | 1. [Node.js](http://nodejs.org)
12 | 2. [Bower](http://bower.io): `$ npm install -g bower`
13 | 3. [Gulp](http://gulpjs.com): `$ npm install -g gulp`
14 |
15 | Then, install dependencies and run the preview server:
16 |
17 | ```bash
18 | $ npm install && bower install
19 | $ gulp serve
20 | ```
21 |
22 | [upring]: https://github.com/mcollina/upring
23 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "presentation-we-are-not-object-oriented-anymore",
3 | "version": "0.0.0",
4 | "dependencies": {
5 | "font-awesome": "~4.4.0",
6 | "prism": "gh-pages"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/demo/load.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const UpRingKV = require('upring-kv')
4 | var dockerNames = require('docker-names')
5 |
6 | const args = require('minimist')(process.argv.slice(2), {
7 | boolean: ['help', 'verbose'],
8 | default: {
9 | port: 0,
10 | points: 100,
11 | timeout: 200,
12 | verbose: false
13 | },
14 | alias: {
15 | port: 'p',
16 | points: 'P',
17 | timeout: 't',
18 | verbose: 'V'
19 | }
20 | })
21 |
22 | const db = UpRingKV({
23 | base: args._,
24 | logLevel: args.verbose ? 'debug' : 'info',
25 | client: true,
26 | hashring: {
27 | replicaPoints: args.points,
28 | joinTimeout: args.timeout
29 | }
30 | })
31 |
32 | db.upring.on('up', function () {
33 | setInterval(function () {
34 | var name = '/' + dockerNames.getRandomName()
35 | var value = {
36 | contentType: 'text/plain',
37 | value: 'hello ' + name
38 | }
39 | db.put(name, value, function (err) {
40 | db.logger.info('published %s %j', name, value)
41 | })
42 | }, 1000)
43 | })
44 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var pkg = require('./package.json'),
4 | gulp = require('gulp'),
5 | gutil = require('gulp-util'),
6 | plumber = require('gulp-plumber'),
7 | rename = require('gulp-rename'),
8 | connect = require('gulp-connect'),
9 | browserify = require('gulp-browserify'),
10 | uglify = require('gulp-uglify'),
11 | jade = require('gulp-jade'),
12 | stylus = require('gulp-stylus'),
13 | autoprefixer = require('gulp-autoprefixer'),
14 | csso = require('gulp-csso'),
15 | del = require('del'),
16 | through = require('through'),
17 | opn = require('opn'),
18 | ghpages = require('gh-pages'),
19 | path = require('path'),
20 | isDist = process.argv.indexOf('serve') === -1;
21 |
22 |
23 | gulp.task('js', ['clean:js'], function() {
24 | return gulp.src('src/scripts/main.js')
25 | .pipe(isDist ? through() : plumber())
26 | .pipe(browserify({ transform: ['debowerify'], debug: !isDist }))
27 | .pipe(isDist ? uglify() : through())
28 | .pipe(rename('build.js'))
29 | .pipe(gulp.dest('dist/build'))
30 | .pipe(connect.reload());
31 | });
32 |
33 | gulp.task('html', ['clean:html'], function() {
34 | return gulp.src('src/index.jade')
35 | .pipe(isDist ? through() : plumber())
36 | .pipe(jade({ pretty: true }))
37 | .pipe(rename('index.html'))
38 | .pipe(gulp.dest('dist'))
39 | .pipe(connect.reload());
40 | });
41 |
42 | gulp.task('css', ['clean:css'], function() {
43 | return gulp.src('src/styles/main.styl')
44 | .pipe(isDist ? through() : plumber())
45 | .pipe(stylus({
46 | // Allow CSS to be imported from node_modules and bower_components
47 | 'include css': true,
48 | 'paths': ['./node_modules', './bower_components']
49 | }))
50 | .pipe(autoprefixer('last 2 versions', { map: false }))
51 | .pipe(isDist ? csso() : through())
52 | .pipe(rename('build.css'))
53 | .pipe(gulp.dest('dist/build'))
54 | .pipe(connect.reload());
55 | });
56 |
57 | gulp.task('images', ['clean:images'], function() {
58 | return gulp.src('src/images/**/*')
59 | .pipe(gulp.dest('dist/images'))
60 | .pipe(connect.reload());
61 | });
62 |
63 | gulp.task('clean', function(done) {
64 | del('dist', done);
65 | });
66 |
67 | gulp.task('clean:html', function(done) {
68 | del('dist/index.html', done);
69 | });
70 |
71 | gulp.task('clean:js', function(done) {
72 | del('dist/build/build.js', done);
73 | });
74 |
75 | gulp.task('clean:css', function(done) {
76 | del('dist/build/build.css', done);
77 | });
78 |
79 | gulp.task('clean:images', function(done) {
80 | del('dist/images', done);
81 | });
82 |
83 | gulp.task('clean:fonts', function(done) {
84 | del('dist/fonts', done);
85 | });
86 |
87 | gulp.task('font-awesome', ['clean:fonts'], function() {
88 | return gulp.src('./bower_components/font-awesome/fonts/*')
89 | .pipe(gulp.dest('dist/fonts'))
90 | .pipe(connect.reload());
91 | });
92 |
93 | gulp.task('connect', ['build'], function() {
94 | connect.server({
95 | root: 'dist',
96 | livereload: true
97 | });
98 | });
99 |
100 | gulp.task('open', ['connect'], function (done) {
101 | opn('http://localhost:8080', done);
102 | });
103 |
104 | gulp.task('watch', function() {
105 | gulp.watch('src/**/*.jade', ['html']);
106 | gulp.watch('src/styles/**/*.styl', ['css']);
107 | gulp.watch('src/images/**/*', ['images']);
108 | gulp.watch([
109 | 'src/scripts/**/*.js',
110 | 'bespoke-theme-*/dist/*.js' // Allow themes to be developed in parallel
111 | ], ['js']);
112 | });
113 |
114 | gulp.task('deploy', ['build'], function(done) {
115 | ghpages.publish(path.join(__dirname, 'dist'), { logger: gutil.log }, done);
116 | });
117 |
118 | gulp.task('build', ['js', 'html', 'css', 'images', 'font-awesome']);
119 |
120 | gulp.task('serve', ['open', 'watch']);
121 |
122 | gulp.task('default', ['build', 'exit']);
123 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "presentation-the-cost-of-logging",
3 | "version": "0.0.0",
4 | "dependencies": {
5 | "bespoke-run": "^1.0.1",
6 | "bloomrun": "^2.3.0",
7 | "docker-names": "^1.0.0",
8 | "minimist": "^1.2.0",
9 | "upring-kv": "^0.4.2"
10 | },
11 | "devDependencies": {
12 | "bespoke": "^1.0.0",
13 | "bespoke-backdrop": "^1.0.0",
14 | "bespoke-bullets": "^1.0.0",
15 | "bespoke-classes": "^1.0.0",
16 | "bespoke-hash": "^1.0.0",
17 | "bespoke-keys": "^1.0.0",
18 | "bespoke-progress": "^1.0.0",
19 | "bespoke-scale": "^1.0.0",
20 | "bespoke-touch": "^1.0.0",
21 | "debowerify": "^0.7.1",
22 | "del": "^1.1.1",
23 | "gh-pages": "^0.2.0",
24 | "gulp": "^3.8.1",
25 | "gulp-autoprefixer": "0.0.7",
26 | "gulp-browserify": "^0.5.0",
27 | "gulp-connect": "^2.0.5",
28 | "gulp-csso": "^0.2.9",
29 | "gulp-jade": "^0.6.0",
30 | "gulp-plumber": "^0.6.3",
31 | "gulp-rename": "^1.2.0",
32 | "gulp-stylus": "^1.0.2",
33 | "gulp-uglify": "^0.3.1",
34 | "gulp-util": "^2.2.17",
35 | "insert-css": "^0.2.0",
36 | "normalizecss": "^3.0.0",
37 | "opn": "^0.1.2"
38 | },
39 | "engines": {
40 | "node": ">=0.10.0"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/images/0.01ms-2kreq-10logs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/0.01ms-2kreq-10logs.png
--------------------------------------------------------------------------------
/src/images/10x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/10x.png
--------------------------------------------------------------------------------
/src/images/adapters.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/adapters.jpg
--------------------------------------------------------------------------------
/src/images/alan-kay.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/alan-kay.jpg
--------------------------------------------------------------------------------
/src/images/arch-generic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/arch-generic.png
--------------------------------------------------------------------------------
/src/images/arch-microservices.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/arch-microservices.png
--------------------------------------------------------------------------------
/src/images/arch-modules.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/arch-modules.png
--------------------------------------------------------------------------------
/src/images/arch-mvc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/arch-mvc.png
--------------------------------------------------------------------------------
/src/images/arch-services.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/arch-services.png
--------------------------------------------------------------------------------
/src/images/bloomrun.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/bloomrun.png
--------------------------------------------------------------------------------
/src/images/bloomrun.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
68 |
--------------------------------------------------------------------------------
/src/images/cc_attribution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/cc_attribution.png
--------------------------------------------------------------------------------
/src/images/control.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/control.png
--------------------------------------------------------------------------------
/src/images/dragon-scroll.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/dragon-scroll.jpg
--------------------------------------------------------------------------------
/src/images/dynamo-strategy-one.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/dynamo-strategy-one.png
--------------------------------------------------------------------------------
/src/images/dynamodb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/dynamodb.png
--------------------------------------------------------------------------------
/src/images/ecosystem-impact.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/ecosystem-impact.jpg
--------------------------------------------------------------------------------
/src/images/event-loop-gc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/event-loop-gc.png
--------------------------------------------------------------------------------
/src/images/event-loop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/event-loop.png
--------------------------------------------------------------------------------
/src/images/fg-pino-after.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/fg-pino-after.png
--------------------------------------------------------------------------------
/src/images/fg-pino-before.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/fg-pino-before.png
--------------------------------------------------------------------------------
/src/images/fire.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/fire.jpg
--------------------------------------------------------------------------------
/src/images/five-euro.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/five-euro.jpg
--------------------------------------------------------------------------------
/src/images/hashring-sharding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/hashring-sharding.png
--------------------------------------------------------------------------------
/src/images/heartbeat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/heartbeat.png
--------------------------------------------------------------------------------
/src/images/hole.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/hole.jpg
--------------------------------------------------------------------------------
/src/images/integration.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/integration.jpg
--------------------------------------------------------------------------------
/src/images/kaboom.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/kaboom.gif
--------------------------------------------------------------------------------
/src/images/lamp.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/lamp.jpg
--------------------------------------------------------------------------------
/src/images/loadbalacing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/loadbalacing.png
--------------------------------------------------------------------------------
/src/images/london.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/london.jpg
--------------------------------------------------------------------------------
/src/images/ludicrous.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/ludicrous.gif
--------------------------------------------------------------------------------
/src/images/magic.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/magic.gif
--------------------------------------------------------------------------------
/src/images/matteo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/matteo.png
--------------------------------------------------------------------------------
/src/images/me-nodeconf-eu-2013.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/me-nodeconf-eu-2013.jpg
--------------------------------------------------------------------------------
/src/images/monolith.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/monolith.jpg
--------------------------------------------------------------------------------
/src/images/nearform.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
57 |
--------------------------------------------------------------------------------
/src/images/no-caching.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/no-caching.png
--------------------------------------------------------------------------------
/src/images/node-desktop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/node-desktop.png
--------------------------------------------------------------------------------
/src/images/nodeconfeu-2013-top.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/nodeconfeu-2013-top.jpg
--------------------------------------------------------------------------------
/src/images/nodejs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/nodejs.png
--------------------------------------------------------------------------------
/src/images/penguins.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/penguins.gif
--------------------------------------------------------------------------------
/src/images/piggy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/piggy.jpg
--------------------------------------------------------------------------------
/src/images/reqhashing-with-gateway.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/reqhashing-with-gateway.png
--------------------------------------------------------------------------------
/src/images/reqhashing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/reqhashing.png
--------------------------------------------------------------------------------
/src/images/sharding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/sharding.png
--------------------------------------------------------------------------------
/src/images/shifu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/shifu.png
--------------------------------------------------------------------------------
/src/images/snail.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/snail.jpg
--------------------------------------------------------------------------------
/src/images/spaceballs.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/spaceballs.jpg
--------------------------------------------------------------------------------
/src/images/speed.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/speed.jpg
--------------------------------------------------------------------------------
/src/images/stonehenge.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/stonehenge.JPG
--------------------------------------------------------------------------------
/src/images/swim.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/swim.png
--------------------------------------------------------------------------------
/src/images/tools.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/tools.jpg
--------------------------------------------------------------------------------
/src/images/unfeasible.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/unfeasible.gif
--------------------------------------------------------------------------------
/src/images/upring-events.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/upring-events.jpeg
--------------------------------------------------------------------------------
/src/images/upring.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/images/wv.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcollina/scaling-state/7219fc93c6447f2aead1f33c5ff5f81142eb3665/src/images/wv.jpg
--------------------------------------------------------------------------------
/src/index.jade:
--------------------------------------------------------------------------------
1 | doctype html
2 | html
3 | head
4 | meta(charset='utf-8')
5 | meta(name='viewport', content='width=device-width, initial-scale=1, maximum-scale=1')
6 | title Scaling State
7 |
8 | link(rel='stylesheet', type='text/css', href='build/build.css')
9 |
10 | body
11 |
12 | article
13 |
14 | section(data-bespoke-backdrop='black').trans
15 | div(style='text-align: left; margin-top: -2em; color: white')
16 | h1 Scaling State
17 | h3(style='color: white') by
18 | a(style="display:inline-block;margin-left: -.03em; color: white",href="http://twitter.com/matteocollina") @matteocollina
19 |
20 | br
21 | div(style="width: 50%; float: right; margin-bottom: -30em;")
22 | a(href="http://nearform.com")
23 | img(src="./images/nearform.svg")
24 |
25 | section()
26 | // h2 Stateless Architecture
27 | img(src='images/arch-generic.png' style='height: 90%')
28 |
29 | section()
30 | h3 Round-Robin Load Balancing
31 | img(src='images/loadbalacing.png' style='width: 90%')
32 |
33 | section
34 | h3 Round-Robin Load Balancing
35 | img(src="./images/no-caching.png", style="width: 120%")
36 |
37 | section
38 | h2 Any local caching is unfeasible
39 | br
40 | | as the load is shared
41 |
42 | section
43 | h3 Application-Level Sharding
44 | img(src="./images/reqhashing.png" style="width: 90%")
45 | // Given a request referencing data X, we must always route it to peer Y.
46 |
47 | section
48 | h3 How do we assign users to servers?
49 | img(src='images/sharding.png' style='height: 80%')
50 |
51 | section
52 | h2 What if the topology changes?
53 |
54 | section
55 | h2 Failure detection
56 | img(src="./images/heartbeat.png" style="width: 90%")
57 | h2 by heartbeat
58 |
59 | section
60 | img(src="./images/unfeasible.gif")
61 |
62 | section
63 | h2 ..or is it?
64 |
65 | section()
66 | img(src='images/upring.svg' style='width: 90%')
67 |
68 | section
69 | h2 DEMO
70 | a(href="https://youtu.be/fLDOCwiKbbo") https://youtu.be/fLDOCwiKbbo
71 |
72 | section(data-bespoke-backdrop='magic').trans
73 |
74 | section(data-bespoke-backdrop='dragon-scroll').trans
75 | h1(style="color: white; padding-top: 50%") Secret Sauce(s)
76 |
77 | section()
78 | img(src='images/dynamodb.png' style='width: 90%')
79 |
80 | section
81 | img(src="./images/dynamo-strategy-one.png" style="height: 90%")
82 |
83 | section()
84 | img(src='images/swim.png' style='width: 90%')
85 |
86 | section
87 | ul(style='text-align: left; font-size: 3em').bullet
88 | li
89 | b(style='color: red; font-style: italic;') S
90 | | calable
91 | li
92 | b(style='color: red; font-style: italic;') W
93 | | eakly-Consistent
94 | li
95 | b(style='color: red; font-style: italic;') I
96 | | nfection Style
97 | li
98 | b(style='color: red; font-style: italic;') M
99 | | embership protocol
100 |
101 | section(data-bespoke-backdrop='lamp').trans
102 | h3(style="color: white; margin-left: auto; margin-right: 0%; width: 30%; text-align: right; padding-bottom: 5%")
103 | | Let's organize our peers in a consistent hashring,
104 | | using SWIM to detect failures
105 |
106 | section(data-bespoke-backdrop='magic').trans
107 |
108 | section()
109 | img(src='images/hashring-sharding.png' style='height: 90%')
110 |
111 | section(data-bespoke-backdrop='upring-events').trans
112 |
113 | section
114 | h2 API
115 |
116 | section
117 | h2 Starting upring
118 | pre
119 | code.language-javascript.
120 | const upring = UpRing({
121 | base: ['127.0.0.1:7979'],
122 | logLevel: 'debug',
123 | hashring: {
124 | replicaPoints: 10,
125 | joinTimeout: 200
126 | }
127 | })
128 |
129 | section
130 | h2 Adding patterns
131 | pre
132 | code.language-javascript.
133 | upring.add('ns:kv,cmd:put', function (req, reply) {
134 | db.set(req.key, req.value)
135 | /* the first argument is the error
136 | the second one is the result */
137 | reply(null, { ok: true })
138 | })
139 |
140 | section
141 | h2 Send requests
142 | pre
143 | code.language-javascript.
144 | upring.request({
145 | ns: 'kv',
146 | cmd: 'get',
147 | key: 'hello'
148 | }, console.log)
149 |
150 | section
151 | h2 Do live updates 1/2
152 | pre
153 | code.language-javascript.
154 | upring.add('ns:kv,cmd:live', function (req, reply) {
155 | const updates = new Readable({
156 | objectMode: true,
157 | read: () => {}
158 | })
159 | // call push whenever you want to send data
160 | // se the full Readable API at nodejs.org
161 | updates.push({ hello: 'world' })
162 | reply(null, { streams: { updates } })
163 | })
164 |
165 | section
166 | h2 Do live updates 2/2
167 | pre
168 | code.language-javascript.
169 | upring.request({
170 | ns: 'kv',
171 | cmd: 'get',
172 | key: 'hello'
173 | }, function (err, res) {
174 | res.streams.updates.on('data', console.log)
175 | })
176 |
177 | section
178 | h2 Track
179 | pre
180 | code.language-javascript.
181 | /* call upring.track(key) if you are responsible
182 | for that key, i.e. if upring.allocatedToMe(key)
183 | returns true */
184 | const tracker = upring.track(key, { replica: true })
185 | tracker.on('replica', function (peer) {
186 | console.log('new replica', peer)
187 | })
188 | tracker.on('move', function (peer) {
189 | console.log('moved to', peer)
190 | })
191 |
192 | section
193 | h2 Replica
194 | pre
195 | code.language-javascript.
196 | /* call upring.replica(key, cb) if you are not responsible
197 | for that key, i.e. if upring.allocatedToMe(key)
198 | returns false */
199 | upring.replica(key, function () {
200 | // now upring.allocateToMe(key) returns true
201 | })
202 |
203 | section
204 | h3 Upring is a framework to
205 | b build
206 |
207 | ul.bullet
208 | li a key value store
209 | li a cache
210 | li a pub/sub system
211 | li real-time applications
212 | li a discovery system
213 | li a metadata store for microservices
214 | li ..or anything that requires distributed state!
215 |
216 | section
217 | h2 Links
218 | ul.bullet
219 | li
220 | a(href="https://github.com/mcollina/upring").
221 | https://github.com/mcollina/upring
222 | li
223 | a(href="https://github.com/mcollina/upring-kv").
224 | https://github.com/mcollina/upring-kv
225 | li
226 | a(href="https://github.com/mcollina/upring-control").
227 | https://github.com/mcollina/upring-control
228 | li
229 | a(href="https://github.com/mcollina/upring-pubsub").
230 | https://github.com/mcollina/upring-pubsub
231 |
232 | section
233 | h2 This presentation
234 | ul.bullet
235 | li
236 | a(href="https://mcollina.github.io/scaling-state").
237 | https://mcollina.github.io/scaling-state
238 | li
239 | a(href="https://github.com/mcollina/scaling-state").
240 | https://github.com/mcollina/scaling-state
241 |
242 | section
243 | img(src='images/matteo.png' style="width: 95%")
244 | h3
245 | a(href='http://github.com/mcollina') http://github.com/mcollina
246 |
247 | section
248 | h1 Thanks!
249 | a(href="http://nearform.com" style="width: 20%")
250 | img(src="./images/nearform.svg")
251 | br
252 | h3 matteo.collina@nearform.com
253 | h3 @matteocollina
254 | h3 www.nearform.com
255 |
256 | section
257 | img(src='images/upring.svg' style='width: 30%')
258 | br
259 | br
260 | h2 How does it work?
261 |
262 | section
263 | h2 Transport: tentacoli
264 | ul.bullet
265 | li
266 | a(href="https://github.com/mcollina/tentacoli")
267 | | https://github.com/mcollina/tentacoli
268 | li request/response for messages
269 | li support sending binary streams
270 | li support sending object streams
271 | li works on top any binary stream
272 |
273 | section
274 | pre
275 | code.language-javascript.
276 | var stream = net.connect(4200)
277 | var instance = tentacoli()
278 |
279 | stream.pipe(instance).pipe(stream)
280 |
281 | instance.request({
282 | cmd: 'somedata'
283 | }, function (err, res) {
284 | console.log(err, res)
285 | })
286 |
287 | section
288 | pre
289 | code.language-javascript.
290 | var server = net.createServer(function (stream) {
291 | var instance = tentacoli()
292 | stream.pipe(instance).pipe(stream)
293 | stream.on('request', handle)
294 | })
295 | server.listen(4200)
296 |
297 | section
298 | pre
299 | code.language-javascript.
300 | function handle (req, reply) {
301 | console.log('--> request is', req.cmd)
302 | reply(null, {
303 | data: 'some data'
304 | })
305 | }
306 |
307 | section
308 | h2 Streams are a first level concern
309 | p
310 | | We can use them to receive live updates
311 | pre
312 | code.language-javascript.
313 | instance.request({
314 | cmd: 'a request',
315 | }, function (err, res) {
316 | res.streams.on('data', console.log)
317 | }
318 |
319 | section
320 | pre
321 | code.language-javascript.
322 | instance.request({
323 | cmd: 'upload',
324 | streams: {
325 | file: fs.createReadStream(__filename)
326 | }
327 | }, console.log)
328 |
329 | section
330 | h2 Streams can also be in replies
331 | pre
332 | code.language-javascript.
333 | function handle (req, reply) {
334 | console.log('--> request is', req.cmd)
335 | reply(null, {
336 | streams: {
337 | file: fs.createReadStream(__filename)
338 | }
339 | })
340 | }
341 |
342 | section
343 | a(href="http://github.com/mcollina/bloomrun")
344 | img(src="./images/bloomrun.png" style="width: 90%")
345 |
346 | section
347 | h2 Pattern Matching!
348 | pre
349 | code(data-bespoke-autorun).language-javascript.
350 | var i = bloomrun()
351 | i.add({ cmd: 'save' }, function save (arg, cb) {
352 | alert('saving ' + JSON.stringify(arg))
353 | cb(null, true) })
354 |
355 | var msg = {
356 | cmd: 'save',
357 | person: { name: 'matteo' } }
358 | i.lookup(msg)(msg, function (err, result) {
359 | alert([err, result].join(' ')) })
360 |
361 | section
362 | h1 Thanks!
363 | a(href="http://nearform.com" style="width: 20%")
364 | img(src="./images/nearform.svg")
365 | br
366 | h3 matteo.collina@nearform.com
367 | h3 @matteocollina
368 | h3 www.nearform.com
369 |
370 | script(src='build/build.js')
371 |
--------------------------------------------------------------------------------
/src/scripts/main.js:
--------------------------------------------------------------------------------
1 | // Require Node modules in the browser thanks to Browserify: http://browserify.org
2 | var bespoke = require('bespoke'),
3 | classes = require('bespoke-classes'),
4 | keys = require('bespoke-keys'),
5 | touch = require('bespoke-touch'),
6 | bullets = require('bespoke-bullets'),
7 | backdrop = require('bespoke-backdrop'),
8 | scale = require('bespoke-scale'),
9 | hash = require('bespoke-hash'),
10 | progress = require('bespoke-progress'),
11 | run = require('bespoke-run'),
12 | bloomrun = require('bloomrun');
13 |
14 | // Bespoke.js
15 | bespoke.from('article', [
16 | classes(),
17 | keys(),
18 | touch(),
19 | run(),
20 | bullets('li, .bullet'),
21 | backdrop(),
22 | scale(),
23 | hash(),
24 | progress()
25 | ]);
26 |
27 | // Prism syntax highlighting
28 | // This is actually loaded from "bower_components" thanks to
29 | // debowerify: https://github.com/eugeneware/debowerify
30 | require('prism');
31 |
32 | global.bloomrun = bloomrun;
33 |
--------------------------------------------------------------------------------
/src/styles/main.styl:
--------------------------------------------------------------------------------
1 |
2 | @import 'prism/themes/prism-okaidia.css'
3 | @import 'font-awesome/css/font-awesome.css'
4 |
5 | slide_width = 640px
6 | slide_height = 480px
7 | slide_background = white
8 |
9 | slide_transition_length = .6s
10 | slide_transition_easing = ease
11 | slide_transition_rotate_y = 90deg
12 | // Safari bugs out on 3d transform-origins, so we have to fake it
13 | slide_transition_nudge_x = -100px
14 |
15 | bullet_transition_length = .3s
16 | bullet_transition_easing = ease
17 | bullet_transition_translate_x = 16px
18 |
19 | // base
20 |
21 | *
22 | box-sizing: border-box
23 | margin: 0
24 | padding: 0
25 |
26 | @media print
27 | *
28 | -webkit-print-color-adjust: exact
29 |
30 | @page
31 | size: landscape
32 | margin: 0
33 |
34 | // bespoke.js layout styles
35 |
36 | .bespoke-parent
37 | transition: background slide_transition_length slide_transition_easing
38 | position: absolute
39 | top: 0
40 | bottom: 0
41 | left: 0
42 | right: 0
43 | overflow: hidden
44 | @media print
45 | overflow: visible
46 | position: static
47 |
48 | .bespoke-theme-cube-slide-parent
49 | position: absolute
50 | top: 0
51 | left: 0
52 | right: 0
53 | bottom: 0
54 | perspective: 600px
55 |
56 | .bespoke-slide
57 | transition:
58 | transform slide_transition_length slide_transition_easing,
59 | opacity slide_transition_length slide_transition_easing,
60 | background slide_transition_length slide_transition_easing
61 | transform-origin: 50% 50% 0
62 | backface-visibility: hidden
63 | display: flex
64 | flex-direction: column
65 | justify-content: center
66 | align-items: center
67 | text-align: center
68 | width: slide_width
69 | height: slide_height
70 | position: absolute
71 | top: 50%
72 | margin-top: (slide_height / 2) * -1
73 | left: 50%
74 | margin-left: (slide_width / 2) * -1
75 | background: slide_background
76 | padding: 40px
77 | border-radius: 0
78 | @media print
79 | zoom: 1 !important // disable bespoke-scale
80 | height: 743px // seems to correspond with an A4, landscape page height
81 | width: 100%
82 | page-break-before: always
83 | position: static
84 | margin: 0
85 | transition: none
86 |
87 | .bespoke-before
88 | transform: translateX(slide_transition_nudge_x * -1) translateX(slide_width / -2) rotateY(slide_transition_rotate_y * -1) translateX(slide_width / -2)
89 | @media print
90 | transform: none
91 |
92 | .bespoke-after
93 | transform: translateX(slide_transition_nudge_x) translateX(slide_width / 2) rotateY(slide_transition_rotate_y) translateX(slide_width / 2)
94 | @media print
95 | transform: none
96 |
97 | .bespoke-inactive
98 | opacity: 0
99 | pointer-events: none
100 | @media print
101 | opacity 1
102 |
103 | .bespoke-active
104 | opacity: 1
105 |
106 | // bespoke-bullet styles
107 |
108 | .bespoke-bullet
109 | transition: all bullet_transition_length bullet_transition_easing
110 | @media print
111 | transition: none
112 |
113 | .bespoke-bullet-inactive
114 | opacity: 0
115 | li&
116 | transform: translateX(bullet_transition_translate_x)
117 | @media print
118 | transform: none
119 | @media print
120 | opacity: 1
121 |
122 | .bespoke-bullet-active
123 | opacity: 1
124 |
125 | // bespoke-scale styles
126 |
127 | .bespoke-scale-parent
128 | perspective: 600px
129 | position: absolute
130 | top: 0
131 | left: 0
132 | right: 0
133 | bottom: 0
134 | pointer-events: none
135 | .bespoke-active
136 | pointer-events: auto
137 | @media print
138 | transform: none !important
139 |
140 | // bespoke-progress styles
141 |
142 | .bespoke-progress-parent
143 | position: absolute
144 | top: 0
145 | left: 0
146 | right: 0
147 | height: 2px
148 | @media only screen and (min-width: 1366px)
149 | height: 4px
150 | @media print
151 | display: none
152 |
153 | .bespoke-progress-bar
154 | transition: width .6s ease
155 | position: absolute
156 | height: 100%
157 | background: #0089f3
158 | border-radius: 0 4px 4px 0
159 |
160 | // bespoke-backdrop styles
161 |
162 | .spaceballs
163 | background: url('../images/spaceballs.jpg') center
164 | background-size: contain
165 | background-repeat: no-repeat
166 | background-color: black
167 |
168 | .nodeconfeu
169 | background-image: url('../images/nodeconfeu-2013-top.jpg')
170 | background-size: cover
171 |
172 | .menodeconfeu
173 | background-image: url('../images/me-nodeconf-eu-2013.jpg')
174 | background-size: cover
175 |
176 | .adapters
177 | background-image: url('../images/adapters.jpg')
178 | background-size: cover
179 |
180 | .dragon-scroll
181 | background-image: url('../images/dragon-scroll.jpg')
182 | background-size: cover
183 |
184 | .steps
185 | background-image: url('../images/steps.jpg')
186 | background-size: cover
187 |
188 | .wv
189 | background-image: url('../images/wv.jpg')
190 | background-size: cover
191 |
192 | .snail
193 | background-image: url('../images/snail.jpg')
194 | background-size: cover
195 |
196 | .extreme
197 | background-image: url('../images/extreme.jpg')
198 | background-size: cover
199 |
200 | .lamp
201 | background-image: url('../images/lamp.jpg')
202 | background-size: cover
203 |
204 | .tools
205 | background-image: url('../images/tools.jpg')
206 | background-size: cover
207 |
208 | .fire
209 | background-image: url('../images/fire.jpg')
210 | background-size: cover
211 |
212 | .integration
213 | background-image: url('../images/integration.jpg')
214 | background-size: cover
215 |
216 | .monolith
217 | background-image: url('../images/monolith.jpg')
218 | background-size: cover
219 |
220 | .stonehenge
221 | background-image: url('../images/stonehenge.JPG')
222 | background-size: cover
223 |
224 | .ecosystem-impact
225 | background-image: url('../images/ecosystem-impact.jpg')
226 | background-size: cover
227 |
228 | .piggy
229 | background-image: url('../images/piggy.jpg')
230 | background-size: cover
231 |
232 | .five-euro
233 | background-image: url('../images/five-euro.jpg')
234 | background-size: cover
235 |
236 | .london
237 | background-image: url('../images/london.jpg')
238 | background-size: cover
239 |
240 | .nap-mp
241 | background-image: url('../images/nap-mp.jpg')
242 | background-size: cover
243 |
244 | .pines
245 | background-image: url('../images/pines.jpg')
246 | background-size: cover
247 |
248 | .kay
249 | background-image: url('../images/alan-kay.jpg')
250 | background-size: cover
251 |
252 | .magic
253 | background-image: url('../images/magic.gif')
254 | background-size: cover
255 |
256 | .node-desktop
257 | background-image: url('../images/node-desktop.png')
258 | background-size: cover
259 |
260 | .upring-events
261 | background-image: url('../images/upring-events.jpeg')
262 | background-size: contain
263 | background-repeat: no-repeat
264 | background-position: center
265 |
266 | .hole
267 | background-image: url('../images/hole.jpg')
268 | background-size: cover
269 |
270 | .bespoke-backdrop
271 | position: absolute
272 | top: 0
273 | left: 0
274 | right: 0
275 | bottom: 0
276 | transform: translateZ(0)
277 | transition: opacity slide_transition_length slide_transition_easing
278 | opacity: 0
279 | z-index: -1
280 | &-active
281 | opacity: 1
282 |
283 | // prism styles
284 |
285 | pre
286 | padding: 26px !important
287 | border-radius: 8px
288 |
289 | // content styles
290 |
291 | body
292 | font-family: helvetica, arial, sans-serif
293 | font-size: 18px
294 | color: #404040
295 |
296 | h1
297 | font-size: 72px
298 | line-height: 82px
299 | letter-spacing: -2px
300 | margin-bottom: 16px
301 |
302 | h2
303 | font-size: 42px
304 | letter-spacing: -1px
305 | margin-bottom: 8px
306 |
307 | h3
308 | font-size: 24px
309 | font-weight: normal
310 | margin-bottom: 24px
311 | color: #606060
312 |
313 | hr
314 | visibility: hidden
315 | height: 20px
316 |
317 | ul
318 | list-style: none
319 |
320 | li
321 | margin-bottom: 12px
322 |
323 | p
324 | margin: 0 100px 12px
325 | line-height: 22px
326 |
327 | a
328 | color: #0089f3
329 | text-decoration: none
330 |
331 | .full-imgs
332 | img
333 | width: 100%
334 | height: 100%
335 |
336 | .sensortag
337 | background-image: url('../images/sensortag.jpg')
338 | background-size: cover
339 |
340 | .sensortag-slide
341 | background: transparent !important
342 | color: white
343 |
344 | button
345 | padding: 10px
346 |
347 | .transgray
348 | background: rgba(0,0,0,0.3) !important
349 | h3
350 | color: white
351 |
352 | .transwhite
353 | background: rgba(255,255,255,0.8) !important
354 |
355 | .black
356 | background: black !important
357 |
358 | .trans
359 | background: rgba(0,0,0,0) !important
360 |
361 | .copyright
362 | font-size: 10px
363 | text-align: right
364 | position: absolute
365 | bottom: 0px
366 | right: 20px;
367 | margin: 0px
368 | padding: 0px
369 | opacity: 0.5
370 |
371 | a
372 | color: #404040
373 |
374 | img
375 | height: 10px;
376 |
--------------------------------------------------------------------------------