<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">

        <title>Uma Não-Gentil Introdução ao Stream Processing</title>

        <meta name="description" content="Uma introdução não-gentil ao stream processing">
        <meta name="author" content="Julio Biason">

        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">

        <link rel="stylesheet" href="reveal.js/css/reveal.css">
        <link rel="stylesheet" href="reveal.js/css/theme/night.css" id="theme">

        <!-- Code syntax highlighting -->
        <link rel="stylesheet" href="reveal.js/lib/css/zenburn.css">

        <!-- Printing and PDF exports -->
        <script>
            var link = document.createElement( 'link' );
            link.rel = 'stylesheet';
            link.type = 'text/css';
            link.href = window.location.search.match( /print-pdf/gi ) ? 'css/print/pdf.css' : 'css/print/paper.css';
            document.getElementsByTagName( 'head' )[0].appendChild( link );
        </script>

        <!--[if lt IE 9]>
        <script src="lib/js/html5shiv.js"></script>
        <![endif]-->

        <style type="text/css" media="screen">
            .happy {
                color: yellow;
            }

            .reveal section img {
                border: none;
            }

            .reveal ul.empty {
                list-style: none outside;
            }

            li {
                display: block;
            }

            .cursor {
                background-color: #666;
                color: white;
            }
            
            img {
                max-height: 90%;
            }

            td.seen {
                font-style: italic;
                font-weight: bold;
            }

			.semi-opaque {
				background-color: rgba(0, 0, 0, 0.7);
				color: #fff;
				text-shadow: 2px 2px #000;
			}

			.reveal h1 {
				font-size: 3em !important;
			}
        </style>
    </head>

    <body>
        <div class="reveal">
            <div class="slides">
                <section>
                    <section data-background="_images/streamprocessing.jpg" data-header>
                        <h2 class="semi-opaque">Uma Não-Gentil Introdução ao Stream Processing</h2>
                    </section>
                </section>

                <section>
                    <section>
                        <img src="_images/avatar-20170726.png" alt="Me" style="float:left;width:200px;" class="no-border">

                        <div>
                            <ul class="empty">
                                <li>Júlio Biason</li>
								<li>https://functional.cafe/@juliobiason</li>
                                <li>julio.biason@pm.me</li>
                                <li><a href="http://presentations.juliobiason.net">http://presentations.juliobiason.net</a></li>
                            </ul>
                        </div>
                    </section>
                </section>

				<section>
					<h2>Agenda:</h2>

					<ul>
						<li>Processamento distribuído</li>
						<li>Batch Processing</li>
						<li>Programação Funcional</li>
						<li>Stream Processing</li>
						<li>(Big Data)</li>
					</ul>
				</section>

				<section>
					<section>
                        <h2>This is a CDN</h2>
						<img class="stretch" src="_images/streamprocessing-aws.png" alt="Lista de pontos de presença da CDN da Amazon" />

						<aside class="notes">
						</aside>
					</section>

					<section>
						<h3>O que é uma CDN</h3>
					</section>

					<section>
						<img class="stretch plain" src="_images/streamprocessing-connection.png" alt="" />

						<aside class="notes">
							Numa conexão "normal", o seu computador conecta no
							modem, que se conecta em um servidor do seu
							provedor, que se conecta em outro servidor, que se
							conecta em outro, que se conecta em outro até que,
							finalmente, ele chega ao servidor que você
							realmente quer.
						</aside>
					</section>

					<section>
						<img class="stretch plain" src="_images/streamprocessing-cdn.png" alt="" />

						<aside class="notes">
							Com uma CDN, ao invés do servidor do provedor
							atravessar toda a internet até chegar ao servidor
							de destino, o servidor da CDN verifica se ele tem o
							arquivo requisitado e, se tiver, responde
							imediatamente.

							Quem sai ganhando com uma CDN?

							- O usuário, já que a resposta vem mais rápida.
							- O cliente da CDN, pois ele não vai precisar ter
							  um servidor ou uma banda larga para poder responder
							  todos os usuários, já que alguns vão ficar somente
							  na CDN.
							- O provedor, já que ele tem que pagar qualquer
							  tráfego que saia da sua rede.
						</aside>
					</section>

					<section>
						<h2>This is a CDN</h2>
						
						<p>A AWS tem um limite máximo de 100.000 requisições/segundo.</p>
					</section>

					<section>
						<h2>CDN? Stream Processing?</h2>

						<ul>
							<li class="fragment">Os clientes são cobrados pelo tráfego que passa pela CDN.</li>
							<li class="fragment"><strong>Queremos mostrar o consumo em tempo real.</strong></li>
							<li class="fragment"><strong>... para todos os clientes.</strong></li>
							<li class="fragment"><strong>...e os dados não páram de ser gerados.</strong></li>

							<aside class="notes">
								Um dos problemas que a CDN enfrenta é que ela
								está sempre atendendo requisições. Assim,
								informações estão sempre aparecendo e tentar
								gerar os resultados em tempo real é complicado.
							</aside>
						</ul>
					</section>

					<section>
						<h2>CDN? Stream Processing?</h2>

						<p>
							Impossível guardar os 100.000 registros/segundo num
							banco de dados e fazer um SELECT pra ver o total.
						</p>

						<p class="fragment">Precisamos os dados "read ready".</p>
					</section>

					<section>
						<img class="stretch" src="_images/streamprocessing-read-ready.jpg" alt="">
					</section>

					<section>
						<h2>Como resolver isso?</h2>

						<p>Poderíamos simplesmente ir somando o total</p>
						<p class="fragment">... se não tivéssemos várias máquinas processando.</p>

						<aside class="notes">
							Se estívessemos usando apenas uma máquina, a cada
							linha de log gerada poderíamos ir somando o que
							cada cliente consumiu. Acontece que temos várias
							máquinas (de novo, em alguns POPs, tem mais de um
							servidor) e aí entram questões de transferência de
							dados de um lado para o outro, tempo de latência de
							rede e tudo mais. Isso tudo complica na hora de
							juntar os dados.
						</aside>
					</section>

					<section>
						<h2>Como resolver isso?</h2>

						<p>Poderíamos mandar todos os dados para um banco de dados e ir calculando e marcando esses como processados.</p>
						<p class="fragment" title="Os arquivos de log, zipados, ocupam petabytes">... se isso não significasse que o banco cresceria infinitamente.</p>
						<p class="fragment">... a não ser que registros antigos fosse apagados.</p>
						<p class="fragment">... que é o que serviços de mensageria fazem.</p>
					</section>
				</section>

				<section>
					<section data-background="_images/streamprocessing-message-broker.png">
						<h1 class="semi-opaque">Message Brokers</h1>
					</section>

					<section>
						<img class="plain stretch" src="_images/streamprocessing-broker.png" alt="" />

						<aside class="notes">
							Um message broker é um serviço que guarda dados
							como um banco de dados, mas possui dois tipos de
							clientes: 

							- Um dos clientes é um "Producer", responsável pela
							  geração de dados; numa analogia com banco de dados,
							  seria um aplicativo que somente fizesse INSERRTS.

							- O outro cliente é o "Consumer", responsável por
							  ler os dados gerados os dados gerados pelo
							  Producer.
						</aside>
					</section>

					<section>
						<img class="plain stretch" src="_images/streamprocessing-broker2.png" alt="" />

						<aside class="notes">
							Uma das vantagens de message brokers é que, havendo
							um aumento da geração dos dados, é possível
							simplesmente plugar mais um Producer.
						</aside>
					</section>

					<section>
						<img class="plain stretch" src="_images/streamprocessing-broker3.png" alt="" />

						<aside class="notes">
							... e, da mesma forma, se a produção de dados for
							muito grande e o consumer não estiver dando conta,
							basta adicionar mais Consumers.

							... e o próprio mesage broker vai cuidar para
							distribuir os dados do Producer entre os Consumers.
						</aside>

						<aside class="notes">
							Message Brokers são também muito usados em
							micro-serviços.
						</aside>
					</section>

					<section>
                        <img src="_images/streamprocessing-kafka.png" alt="Kafka Logo" style="float:left;width:200px;margin:50px;" class="no-border">
                        <img src="_images/streamprocessing-rabbitmq.png" alt="RabbitMQ Logo" style="float:left;width:200px;margin:50px;" class="no-border">
                        <img src="_images/streamprocessing-sqs.png" alt="AWS SQS Logo" style="float:left;width:200px;margin:50px;" class="no-border">
                        <img src="_images/streamprocessing-zeromq.gif" alt="ZeroMQ Logo" style="float:left;width:200px;margin:50px;" class="no-border">

						<aside class="notes">
							Os Mesage Brokers mais usados são:

							- Apache Kafka
							- RabbitMQ
							- SQS (dentro da Amazon)
							- ZeroMQ
						</aside>

						<aside class="notes">
							Desses, o ZeroMQ e RabbitMQ são os mais usados para
							integração entre micro-serviços; para stream
							processing, Kafka é o grande vencedor
							(provavelmente pela forma como ele permite que mais
							de um consumidor se conecte a uma fila de dados e
							como os dados são particionados para permitir
							consumidores concorrentes); SQS é mais utilizado
							para integração entre outros serviços Amazon com o
							Lambda.
						</aside>
					</section>
				</section>

				<section>
					<section data-background="_images/streamprocessing-monolith.jpg">
						<h1 class="fragment semi-opaque">Batch Processing</h1>
					</section>

					<section>
						<pre><code>sudo cat /etc/shadow | cut -d ':' -f 2 | sort | uniq -c</code></pre>
					</section>

					<section>
						<ul>
							<li><strong>Entrada</strong>: conteúdo do arquivo /etc/shadow</li>
							<li><strong>Processamento</strong>: capturando o segundo campo separado por ":"</li>
							<li><strong>Agrupamento</strong>: ordenamento dos dados (sort + uniq)</li>
							<li><strong>Saída</strong>: total de duplicados (ainda uniq)</li>
						</ul>
					</section>

					<section>
						<p>Batch processing seria o caso de processar os dados de um dia.</p>

						<p>Se novos dados entrassem no total do dia, bastaria reprocessar os dados do dia.</p>

						<p class="fragment">ou do mês, ou do ano.</p>
					</section>

					<section>
						<img class="stretch plain" src="_images/dunno.jpg" alt="" />

                        <aside class="notes">
                            Esse é todo o conhecimento que eu tenho de batch
                            processing, simplesmente porque eu pulei
                            diretamente para stream processing sem nunca ter
                            feito muita coisa com batch processing.
                        </aside>
					</section>

					<section>
                        <img src="_images/streamprocessing-spark.png" alt="Apache Spark Logo" style="float:left;width:200px;margin:50px;" class="no-border">
                        <img src="_images/streamprocessing-hadoop.png" alt="Apache Hadoop Logo" style="float:left;width:200px;margin:50px;" class="no-border">
					</section>
				</section>

				<section>
					<section data-background="_images/streamprocessing-functional.jpg">
						<h1 class="semi-opaque">Programação Funcional</h1>
					</section>

					<section>
						<h2>Buzzwords!</h2>

						<ul>
							<li>Teoria das Categorias!</li>
							<li title="In category theory, a branch of mathematics, a monad (also triple, triad, standard construction and fundamental construction)[1] is an endofunctor (a functor mapping a category to itself), together with two natural transformations. Monads are used in the theory of pairs of adjoint functors, and they generalize closure operators on partially ordered sets to arbitrary categories.">Monads!</li>
							<li>Functors!</li>
						</ul>
					</section>

					<section>
						<img class="stretch" src="_images/fuck-that.jpg" alt="" />
					</section>

					<section>
						<h2>Funções Puras</h2>

						<p class="fragment">Uma função é considerada pura se
							ela sempre retorna o mesmo resultado para os mesmos
							parâmetros.</p>
					</section>

					<section>
						<pre><code>def mult(a):
    return a * 4</code></pre>
					</section>

					<section>
						<pre><code>mult(2)</code></pre>
						<span class="fragment">8</span>

						<pre class="fragment"><code>mult(2)</code></pre>
						<span class="fragment">8</span>
					</section>

					<section>
						<pre><code>class LightSwitch:
    def __init__(self):
        self.state = False

    def switch(self):
        self.state = not self.state
        print(self.state)</code></pre>
					</section>

                    <section>
                        <pre><code>light = LightSwitch()
light.switch()</code></pre>
                        <span class="fragment">True</span>

                        <pre class="fragment"><code>light.switch()</code></pre>
                        <span class="fragment">False</span>
                    </section>

                    <section>
                        <pre><code>print()</code></pre>

                        <aside class="notes">
                            Por mais estranho que possa soar, `print()` também
                            não é uma função pura, porque chamar print() duas
                            vezes vai deixar duas linhas na tela.
                        </aside>

                        <pre class="fragment"><code>INSERT INTO table (value, value)</code></pre>

                        <aside class="notes">
                            Insert também não é considerada uma função pura,
                            porque cada vez que é chamada adiciona um novo
                            registro na tabela.
                        </aside>

                        <pre class="fragment"><code>random()</code></pre>
                    </section>

					<section>
						<p>"Idempotência"</p>

						<aside class="notes">
							A ideia de que rodar alguma coisa e ela sempre
							responde da mesma forma também é chamado de
							"idempotência".
						</aside>
					</section>

                    <section>
                        <h2>Imutabilidade</h2>

                        <p>Uma vez que o dado é gerado, ele nunca muda.</p>

                        <p class="fragment"><small>(Transparência referencial)</small></p>
                    </section>

                    <section>
                        <img src="_images/lisp.png" alt="">

                        <aside class="notes">
                            Mas uma coisa legal que seguiu a teoria das
                            categorias, implementando programação funcional,
                            foi Lisp.
                        </aside>
                    </section>

                    <section>
                        <ul>
                            <li><code>map</code></li>
                            <li><code>reduce</code> <span class="fragment">(fold)</span></li>
                            <li class="fragment"><code>filter</code></li>
                        </ul>
                    </section>

                    <section>
                        <ul>
                            <li><code>(map lambda iterator)</code></li>
                            <li><code>(fold lambda iterator start)</code></li>
                            <li><code>(filter lambda iterator start)</code></li>
                        </ul>
                    </section>

                    <section>
                        <ul>
                            <li><code><strong>map</strong></code>: transforma cada um dos
                                elementos do iterador através do função lambda
                                em uma nova lista.</li>
                            <li><code><strong>fold</strong></code>: converte todos os elementos
                                da lista em um único valor, começando com um
                                valor adicionar (por exemplo, <code>sum</code>).</li>
                            <li><code><strong>filter</strong></code>: remove elementos do
                                iterador que não sejam verdadeiros pelo lambda
                                e produz uma nova lista. </li>
                        </ul>
                    </section>
				</section>

                <section>
                    <section data-background="_images/streamprocessing.jpg">
                        <h1 class="semi-opaque">Stream Processing</h1>
                    </section>

					<section>
						<pre><code>sudo cat /etc/shadow | cut -d ':' -f 2 | sort | uniq -c</code></pre>
					</section>

					<section>
                        <pre><code>sudo cat [broker] | cut -d ':' -f 2 | sort | uniq -c</code></pre>
					</section>

					<section>
                        <pre><code>sudo cat [broker] | map | sort | uniq -c</code></pre>
					</section>

					<section>
                        <pre><code>sudo cat [broker] | map | fold</code></pre>
					</section>

					<section>
                        <pre><code>sudo cat [broker] | map | fold</code></pre>
                        <pre><code>sudo cat [broker] | map | fold</code></pre>
                        <pre><code>sudo cat [broker] | map | fold</code></pre>
                        <pre><code>sudo cat [broker] | map | fold</code></pre>
                        <pre><code>sudo cat [broker] | map | fold</code></pre>
					</section>

					<section>
                        <pre><code>sudo cat [broker] | map | group_by | fold</code></pre>
                        <pre><code>sudo cat [broker] | map | group_by | fold</code></pre>
                        <pre><code>sudo cat [broker] | map | group_by | fold</code></pre>
                        <pre><code>sudo cat [broker] | map | group_by | fold</code></pre>
                        <pre><code>sudo cat [broker] | map | group_by | fold</code></pre>
					</section>

                    <section>
                        <img class="stretch" src="_images/streamprocessing-streamprocessing.png" alt=""/>
                    </section>

                    <section>
                        <img class="stretch" src="_images/streamprocessing-pipeline.png" alt="" />
                    </section>

					<section>
						<img class="stretch" src="_images/unclephil-flinkpipelinereal.png" alt="" />
					</section>

                    <section>
                        <img src="_images/streamprocessing-storm.png" alt="Apache Storm Logo" style="float:left;width:200px;margin:50px;" class="no-border">
                        <img src="_images/streamprocessing-flink.png" alt="Apache Flink Logo" style="float:left;width:200px;margin:50px;" class="no-border">
                        <img src="_images/streamprocessing-wallaroo.png" alt="Wallaroo  Logo" style="float:left;width:200px;margin:50px;" class="no-border">
                        <img src="_images/streamprocessing-beam.png" alt="Apache Beam Logo" style="float:left;width:200px;margin:50px;" class="no-border">
                    </section>
				</section>

				<section>
					<section data-background="_images/area.jpg">
						<h2 class="semi-opaque">A Área</h2>
					</section>

					<section>
						<img class="stretch" src="_images/baby-smile.jpg" alt="" />

						<aside class="notes">
							A área de stream processing é bem jovem (o conceito
							em si começou a ser explorado a partir de 1999, com
							um protótipo em 2002) e é uma área bem divertida de
							se trabalhar.
						</aside>
					</section>

					<section>
						<img class="stretch" src="_images/broken-gif-Andy-Samberg.gif" alt="" />

						<aside class="notes">
							... entretanto, como qualquer coisa distribuída,
							coisas tendem a explodir de forma inexplicável...
						</aside>
					</section>

					<section>
						<img class="stretch" src="_images/normal12.jpg" alt="" />

						<aside class="notes">
							... e algumas coisas normais não são tão normais...
						</aside>
					</section>

					<section>
						<img class="stretch" src="_images/zuul.jpg" alt="" />

						<aside class="notes">
							... e no fim tem-se uma coisa bonitinha que esconde
							um monstro por trás.
						</aside>
					</section>

					<section>
                        "A distributed system is one in which the failure of a
                        computer you didn't even know existed can render your
                        own computer unusable"

						-- Leslie Lamport, 1987
					</section>

					<section>
						<img class="stretch" src="_images/Java-logo.jpg" alt="" />

						<aside class="notes">
							É uma área dominada pelo Java, já que tudo explodiu
							a partir do JMX...
						</aside>
					</section>

					<section>
						<img class="stretch" src="_images/python-logo.png" alt="" />

						<aside class="notes">
							... embora Python esteja sempre junto (todos
							grandes frameworks tem bibliotecas de conexão com
							Python)...
						</aside>
					</section>

					<section>
						<img class="stretch" src="_images/machine-learning.jpg" alt="" />

						<aside class="">
							... porque Python é imbatível em machine learning,
							graças ao jupyter.
						</aside>
					</section>
                </section>

                <section data-background='_images/thats-all-folks.jpg'>
					<ul class="empty fragment semi-opaque">
						<li>Júlio Biason</li>
						<li>https://functional.cafe/@juliobiason</li>
						<li>julio.biason@pm.me</li>
						<li><a href="http://presentations.juliobiason.net">http://presentations.juliobiason.net</a></li>
					</ul>

					<h3></h3>

					<h3 class="semi-opaque fragment">
						Perguntas?
					</h3>
				</section>
            </div>
        </div>

        <script src="reveal.js/lib/js/head.min.js"></script>
        <script src="reveal.js/js/reveal.js"></script>

        <script>
            // Full list of configuration options available at:
            // https://github.com/hakimel/reveal.js#configuration
            Reveal.initialize({
                controls: true,
                progress: true,
                history: true,
                center: true,
                // showNotes: true,

                transition: 'fade', // none/fade/slide/convex/concave/zoom

                // Optional reveal.js plugins
                dependencies: [
                    { src: 'reveal.js/lib/js/classList.js', condition: function() { return !document.body.classList; } },
                    { src: 'reveal.js/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
                    { src: 'reveal.js/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
                    { src: 'reveal.js/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
                    { src: 'reveal.js/plugin/zoom-js/zoom.js', async: true },
                    { src: 'reveal.js/plugin/notes/notes.js', async: true }
                ]
            });
        </script>

    </body>
</html>