{"id":31124,"date":"2019-10-31T21:39:36","date_gmt":"2019-10-31T18:39:36","guid":{"rendered":"https:\/\/prohoster.info\/blog\/stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-priblizhenie\/"},"modified":"2019-10-31T21:39:36","modified_gmt":"2019-10-31T18:39:36","slug":"stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-priblizhenie","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-priblizhenie","title":{"rendered":"Componentes b\u00e1sicos de aplica\u00e7\u00f5es distribu\u00eddas. Segunda aproxima\u00e7\u00e3o","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><strong>An\u00fancio<\/strong><\/p>\n<p><\/p>\n<p><em>Colegas, no meio do ver\u00e3o, planejo lan\u00e7ar mais um ciclo de artigos sobre o design de sistemas de atendimento em massa: \u201cExperimento VTrade\u201d \u2014 uma tentativa de desenvolver uma estrutura para sistemas de negocia\u00e7\u00e3o. O ciclo abordar\u00e1 a teoria e a pr\u00e1tica da constru\u00e7\u00e3o de uma bolsa de valores, leil\u00e3o e loja. No final do artigo, convido todos a votarem nos temas que mais lhes interessam.<br \/>\n<\/em><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Componentes b\u00e1sicos de aplica\u00e7\u00f5es distribu\u00eddas. Segunda aproxima\u00e7\u00e3o\" src=\"\/wp-content\/uploads\/2019\/04\/358996733e805327b587176f4f992aea.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Este \u00e9 o artigo final do ciclo sobre aplicativos reativos distribu\u00eddos em Erlang\/Elixir. No <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/446028\/\">primeiro artigo<\/a><\/noindex> pode-se encontrar as bases te\u00f3ricas da arquitetura reativa. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/446108\/\">O segundo artigo<\/a><\/noindex> ilustra os principais padr\u00f5es e mecanismos de constru\u00e7\u00e3o de sistemas dessa natureza.<\/p>\n<p><\/p>\n<p>Hoje, abordaremos quest\u00f5es sobre o desenvolvimento da base de c\u00f3digo e dos projetos como um todo. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2 id=\"organizaciya-servisov\">Organiza\u00e7\u00e3o de servi\u00e7os<\/h2>\n<p><\/p>\n<p>Na vida real, ao desenvolver um servi\u00e7o, muitas vezes \u00e9 necess\u00e1rio combinar v\u00e1rios padr\u00f5es de intera\u00e7\u00e3o em um \u00fanico controlador. Por exemplo, o servi\u00e7o de usu\u00e1rios, que lida com a gest\u00e3o de perfis dos usu\u00e1rios do projeto, deve responder a solicita\u00e7\u00f5es req-resp e informar sobre atualiza\u00e7\u00f5es de perfis atrav\u00e9s de pub-sub. Este caso \u00e9 bastante simples: para mensageria, existe um controlador que implementa a l\u00f3gica do servi\u00e7o e publica atualiza\u00e7\u00f5es.<\/p>\n<p><\/p>\n<p>A situa\u00e7\u00e3o se complica quando precisamos implementar um servi\u00e7o distribu\u00eddo tolerante a falhas. Suponhamos que os requisitos para os usu\u00e1rios mudaram: <\/p>\n<p><\/p>\n<ol>\n<li>agora, o servi\u00e7o deve processar solicita\u00e7\u00f5es em 5 n\u00f3s do cluster, <\/li>\n<li>ter a capacidade de executar tarefas em segundo plano, <\/li>\n<li>e tamb\u00e9m ser capaz de gerenciar dinamicamente listas de assinatura para atualiza\u00e7\u00f5es de perfis.<\/li>\n<\/ol>\n<p><\/p>\n<p><em>Observa\u00e7\u00e3o:<\/em> A quest\u00e3o da consist\u00eancia de armazenamento e replica\u00e7\u00e3o de dados n\u00e3o ser\u00e1 abordada. Suponha que essas quest\u00f5es tenham sido resolvidas anteriormente e que j\u00e1 exista um camada de armazenamento confi\u00e1vel e escal\u00e1vel no sistema, e os manipuladores disponham de mecanismos para interagir com ela.<\/p>\n<p><\/p>\n<p>A descri\u00e7\u00e3o formal do servi\u00e7o de usu\u00e1rios se tornou mais complexa. Do ponto de vista do programador, devido ao uso de mensageria, as mudan\u00e7as s\u00e3o m\u00ednimas. Para atender ao primeiro requisito, precisamos configurar o balanceamento no ponto de troca req-resp. <\/p>\n<p><\/p>\n<p>A exig\u00eancia de processamento de tarefas em segundo plano surge frequentemente. Em users, isso pode incluir verifica\u00e7\u00f5es de documentos dos usu\u00e1rios, processamento de multim\u00eddia carregada ou sincroniza\u00e7\u00e3o de dados com redes sociais. Essas tarefas precisam ser distribu\u00eddas de alguma forma dentro do cluster e monitoradas durante a execu\u00e7\u00e3o. Portanto, temos duas op\u00e7\u00f5es de solu\u00e7\u00e3o: usar o modelo de distribui\u00e7\u00e3o de tarefas do artigo anterior ou, se n\u00e3o for adequado, escrever um planejador de tarefas personalizado que gerencie o pool de processadores da forma que precisamos. <\/p>\n<p><\/p>\n<p>O ponto 3 requer a expans\u00e3o do modelo pub-sub. Para sua implementa\u00e7\u00e3o, ap\u00f3s criar o ponto de troca pub-sub, precisamos ativar adicionalmente o controlador desse ponto no contexto do nosso servi\u00e7o. Assim, como se estiv\u00e9ssemos transferindo a l\u00f3gica de assinatura e desinscri\u00e7\u00e3o da camada de messaging para a implementa\u00e7\u00e3o de users.<\/p>\n<p><\/p>\n<p>No final, a decomposi\u00e7\u00e3o da tarefa revelou que, para atender aos requisitos, precisamos lan\u00e7ar 5 inst\u00e2ncias do servi\u00e7o em diferentes n\u00f3s e criar uma entidade adicional \u2013 um controlador pub-sub respons\u00e1vel pela assinatura.<br \/>\nPara iniciar 5 processadores, n\u00e3o \u00e9 necess\u00e1rias modifica\u00e7\u00f5es no c\u00f3digo do servi\u00e7o. A \u00fanica a\u00e7\u00e3o adicional \u00e9 configurar as regras de balanceamento no ponto de troca, o que discutiremos um pouco mais tarde.<br \/>\nAl\u00e9m disso, surgiu uma complexidade adicional: o controlador pub-sub e o planejador de tarefas personalizado devem operar em uma \u00fanica inst\u00e2ncia. Novamente, o servi\u00e7o de messaging, como elemento fundamental, deve fornecer um mecanismo para a escolha do l\u00edder.<\/p>\n<p><\/p>\n<h3 id=\"vybor-lidera\">Escolha do l\u00edder<\/h3>\n<p><\/p>\n<p>Em sistemas distribu\u00eddos, a escolha do l\u00edder \u00e9 o procedimento de nomea\u00e7\u00e3o de um \u00fanico processo respons\u00e1vel pelo planejamento do processamento distribu\u00eddo de alguma carga. <\/p>\n<p><\/p>\n<p>Em sistemas que n\u00e3o s\u00e3o propensos \u00e0 centraliza\u00e7\u00e3o, encontram-se algoritmos universais e algoritmos baseados em consenso, como o paxos ou raft.<br \/>\nUma vez que o messaging \u00e9 um broker e um elemento central, ele est\u00e1 ciente de todos os controladores do servi\u00e7o \u2013 candidatos a l\u00edderes. O messaging pode nomear um l\u00edder sem a necessidade de vota\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p>Todos os servi\u00e7os, ap\u00f3s iniciar e se conectar ao ponto de troca, recebem uma mensagem do sistema <code>#'$leader'{exchange = ?EXCHANGE, pid = LeaderPid, servers = Servers}<\/code>. No caso de <code>LeaderPid<\/code> corresponder ao <code>pid<\/code> do processo atual, ele \u00e9 nomeado l\u00edder, e a lista <code>Servers<\/code> inclui todos os n\u00f3s e suas configura\u00e7\u00f5es.<br \/>\nNo momento da chegada de um novo n\u00f3 e da desativa\u00e7\u00e3o de um n\u00f3 ativo no cluster, todos os controladores do servi\u00e7o recebem <code>#'$slave_up'{exchange = ?EXCHANGE, pid = SlavePid, options = SlaveOpts}<\/code> e <code>#'$slave_down'{exchange = ?EXCHANGE, pid = SlavePid, options = SlaveOpts}<\/code> respectivamente.<\/p>\n<p><\/p>\n<p>Assim, todos os componentes est\u00e3o cientes de todas as mudan\u00e7as, e em cada momento, h\u00e1 garantidamente um l\u00edder no cluster.<\/p>\n<p><\/p>\n<h2 id=\"posredniki\">Intermedi\u00e1rios<\/h2>\n<p><\/p>\n<p>Para implementar processos de processamento distribu\u00eddos complexos e em tarefas de otimiza\u00e7\u00e3o de uma arquitetura j\u00e1 existente, \u00e9 conveniente usar intermedi\u00e1rios.<br \/>\nPara n\u00e3o alterar o c\u00f3digo dos servi\u00e7os e resolver, por exemplo, tarefas de processamento adicional, roteamento ou registro de mensagens, pode-se inserir um manipulador proxy antes do servi\u00e7o, que realizar\u00e1 todo o trabalho adicional.<\/p>\n<p><\/p>\n<p>Um exemplo cl\u00e1ssico de otimiza\u00e7\u00e3o pub-sub \u00e9 um aplicativo distribu\u00eddo com um n\u00facleo de neg\u00f3cios que gera eventos de atualiza\u00e7\u00e3o, como altera\u00e7\u00f5es nos pre\u00e7os do mercado, e uma camada de acesso \u2014 N servidores que fornecem uma API websocket para clientes web.<br \/>\nSe a abordagem for direta, o atendimento ao cliente se apresenta da seguinte forma:<\/p>\n<p><\/p>\n<ul>\n<li>o cliente estabelece conex\u00f5es com a plataforma. No lado do servidor, onde o tr\u00e1fego \u00e9 encerrado, um processo \u00e9 iniciado para atender essa conex\u00e3o.<\/li>\n<li>no contexto do processo de atendimento, ocorre a autoriza\u00e7\u00e3o e a inscri\u00e7\u00e3o para atualiza\u00e7\u00f5es. O processo chama o m\u00e9todo subscribe para os t\u00f3picos.<\/li>\n<li>ap\u00f3s a gera\u00e7\u00e3o de um evento no n\u00facleo, ele \u00e9 entregue aos processos que atendem as conex\u00f5es.<\/li>\n<\/ul>\n<p><\/p>\n<p>Vamos imaginar que temos 50.000 assinantes no t\u00f3pico \"news\". Os assinantes est\u00e3o distribu\u00eddos uniformemente entre 5 servidores. Assim, cada atualiza\u00e7\u00e3o, ao chegar no ponto de troca, ser\u00e1 replicada 50.000 vezes: 10.000 vezes em cada servidor, de acordo com o n\u00famero de assinantes nele. Uma estrat\u00e9gia n\u00e3o muito eficiente, certo?<br \/>\nPara melhorar a situa\u00e7\u00e3o, vamos introduzir um proxy que tenha o mesmo nome que o ponto de troca. O registrador de nomes globais deve ser capaz de retornar o processo mais pr\u00f3ximo pelo nome, isso \u00e9 importante.<\/p>\n<p><\/p>\n<p>Vamos iniciar esse proxy nos servidores da camada de acesso, e todos os nossos processos que atendem a API websocket se inscrever\u00e3o nele, e n\u00e3o no ponto de troca pub-sub original no n\u00facleo. O proxy se inscreve no n\u00facleo apenas em caso de uma inscri\u00e7\u00e3o \u00fanica e replica a mensagem recebida para todos os seus assinantes.<br \/>\nComo resultado, entre o n\u00facleo e os servidores de acesso, ser\u00e3o enviadas 5 mensagens, em vez de 50.000.<\/p>\n<p><\/p>\n<h2 id=\"marshrutizaciya-i-balansirovka\">Roteamento e balanceamento<\/h2>\n<p><\/p>\n<h3 id=\"req-resp\">Req-Resp<\/h3>\n<p><\/p>\n<p>Na implementa\u00e7\u00e3o atual de messaging, existem 7 estrat\u00e9gias de distribui\u00e7\u00e3o de solicita\u00e7\u00f5es:<\/p>\n<p><\/p>\n<ul>\n<li><code>padr\u00e3o<\/code>. A solicita\u00e7\u00e3o \u00e9 enviada a todos os controladores.<\/li>\n<li><code>round-robin<\/code>. Realiza a distribui\u00e7\u00e3o c\u00edclica de solicita\u00e7\u00f5es entre os controladores.<\/li>\n<li><code>consenso<\/code>. Os controladores que gerenciam o servi\u00e7o s\u00e3o divididos em l\u00edder e seguidores. As solicita\u00e7\u00f5es s\u00e3o enviadas somente ao l\u00edder.<\/li>\n<li><code>consenso &amp; round-robin<\/code>. H\u00e1 um l\u00edder no grupo, mas as solicita\u00e7\u00f5es s\u00e3o distribu\u00eddas entre todos os membros.<\/li>\n<li><code>sticky<\/code>. Uma fun\u00e7\u00e3o hash \u00e9 calculada e vinculada a um manipulador espec\u00edfico. Solicita\u00e7\u00f5es subsequentes com essa assinatura s\u00e3o direcionadas ao mesmo manipulador.<\/li>\n<li><code>sticky-fun<\/code>. Durante a inicializa\u00e7\u00e3o do ponto de troca, uma fun\u00e7\u00e3o adicional para calcular o hash \u00e9 passada para <code>sticky<\/code> balanceamento.<\/li>\n<li><code>fun\u00e7\u00e3o<\/code>. Semelhante ao sticky-fun, mas permite redirecionar, rejeitar ou pr\u00e9-processar. <\/li>\n<\/ul>\n<p><\/p>\n<p>A estrat\u00e9gia de distribui\u00e7\u00e3o \u00e9 definida na inicializa\u00e7\u00e3o do ponto de troca.<\/p>\n<p><\/p>\n<p>Al\u00e9m do balanceamento, o messaging permite etiquetar entidades. Vamos considerar os tipos de etiquetas no sistema:<\/p>\n<p><\/p>\n<ul>\n<li>Etiqueta de conex\u00e3o. Permite entender por qual conex\u00e3o os eventos chegaram. Usado quando o processo do controlador se conecta a um ponto de troca, mas com diferentes chaves de roteamento. <\/li>\n<li>Etiqueta de servi\u00e7o. Permite agrupar manipuladores para um \u00fanico servi\u00e7o e expandir as capacidades de roteamento e balanceamento. Para o padr\u00e3o req-resp, o roteamento \u00e9 linear. Enviamos uma solicita\u00e7\u00e3o para o ponto de troca, que ent\u00e3o a encaminha para o servi\u00e7o. Mas se precisamos dividir os manipuladores em grupos l\u00f3gicos, essa divis\u00e3o \u00e9 feita atrav\u00e9s de etiquetas. Ao especificar uma etiqueta, a solicita\u00e7\u00e3o ser\u00e1 direcionada a um grupo espec\u00edfico de controladores.<\/li>\n<li>Etiqueta de solicita\u00e7\u00e3o. Permite distinguir as respostas. Como nosso sistema \u00e9 ass\u00edncrono, para processar as respostas do servi\u00e7o, precisamos ser capazes de especificar um RequestTag ao enviar a solicita\u00e7\u00e3o. Isso nos permitir\u00e1 entender qual resposta de qual solicita\u00e7\u00e3o chegou at\u00e9 n\u00f3s.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"pub-sub\">Pub-sub<\/h3>\n<p><\/p>\n<p>Para pub-sub, tudo \u00e9 um pouco mais simples. Temos um ponto de troca onde as mensagens s\u00e3o publicadas. O ponto de troca distribui mensagens entre os assinantes que se inscreveram nas chaves de roteamento desejadas (pode-se dizer que isso \u00e9 an\u00e1logo a t\u00f3picos).<\/p>\n<p><\/p>\n<h2 id=\"masshtabiruemost-i-otkazoustoychivost\">Escalabilidade e resist\u00eancia a falhas<\/h2>\n<p><\/p>\n<p>A escalabilidade do sistema como um todo depende do grau de escalabilidade das camadas e componentes do sistema:<\/p>\n<p><\/p>\n<ul>\n<li>Os servi\u00e7os s\u00e3o escal\u00e1veis adicionando n\u00f3s adicionais com manipuladores desse servi\u00e7o ao cluster. Durante a opera\u00e7\u00e3o experiente, \u00e9 poss\u00edvel escolher a pol\u00edtica de balanceamento ideal.<\/li>\n<li>O servi\u00e7o de messaging em um cluster separado, em geral, \u00e9 escal\u00e1vel seja movendo pontos de troca excessivamente carregados para n\u00f3s separados no cluster, ou adicionando processos de proxy nas \u00e1reas de carga intensa do cluster.<\/li>\n<li>A escalabilidade de todo o sistema como uma caracter\u00edstica depende da flexibilidade da arquitetura e da capacidade de unir clusters individuais em uma entidade l\u00f3gica comum.<\/li>\n<\/ul>\n<p><\/p>\n<p>A simplicidade e a rapidez da escalabilidade muitas vezes determinam o sucesso do projeto. O messaging na implementa\u00e7\u00e3o atual cresce junto com o aplicativo. Mesmo se precisarmos de um cluster com 50-60 m\u00e1quinas, podemos recorrer \u00e0 federa\u00e7\u00e3o. Infelizmente, o tema da federa\u00e7\u00e3o est\u00e1 al\u00e9m do escopo deste artigo.<\/p>\n<p><\/p>\n<h2 id=\"rezervirovanie\">Redund\u00e2ncia<\/h2>\n<p><\/p>\n<p>Ao discutir o balanceamento de carga, j\u00e1 falamos sobre a reserva de controladores de servi\u00e7os. No entanto, o messaging tamb\u00e9m deve ser reservado. Em caso de falha de um n\u00f3 ou m\u00e1quina, o messaging deve se recuperar automaticamente, e isso deve ocorrer em um curto espa\u00e7o de tempo.<\/p>\n<p><\/p>\n<p>Em meus projetos, eu uso n\u00f3s adicionais que assumem a carga em caso de falha. Em Erlang, existe uma implementa\u00e7\u00e3o padr\u00e3o do modo distribu\u00eddo para aplica\u00e7\u00f5es OTP. O modo distribu\u00eddo, na verdade, realiza a recupera\u00e7\u00e3o em caso de falha iniciando a aplica\u00e7\u00e3o que falhou em outro n\u00f3 previamente iniciado. O processo \u00e9 transparente; ap\u00f3s a falha, a aplica\u00e7\u00e3o \u00e9 automaticamente transferida para o n\u00f3 de failover. Voc\u00ea pode ler mais sobre essa funcionalidade. <noindex><a rel=\"nofollow\" href=\"http:\/\/erlang.org\/doc\/design_principles\/distributed_applications.html\">aqui<\/a><\/noindex>.<\/p>\n<p><\/p>\n<h2 id=\"proizvoditelnost\">Desempenho<\/h2>\n<p><\/p>\n<p>Vamos tentar, ao menos de maneira aproximada, comparar o desempenho do rabbitmq com o nosso messaging personalizado.<br \/>\nEu encontrei <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.openstack.org\/developer\/performance-docs\/test_results\/mq\/rabbitmq\/cmsm\/index.html\">resultados oficiais<\/a><\/noindex> dos testes do rabbitmq pela equipe do openstack.<\/p>\n<p><\/p>\n<p>Na se\u00e7\u00e3o 6.14.1.2.1.2.2 do documento original, \u00e9 apresentado o resultado do RPC CAST:<br \/>\n<img decoding=\"async\" alt=\"Componentes b\u00e1sicos de aplica\u00e7\u00f5es distribu\u00eddas. Segunda aproxima\u00e7\u00e3o\" src=\"\/wp-content\/uploads\/2019\/04\/95f615d241d70a4523fe3c400179b8e6.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Preliminarmente, n\u00e3o faremos nenhuma configura\u00e7\u00e3o adicional no n\u00facleo do SO ou na VM Erlang. As condi\u00e7\u00f5es para os testes s\u00e3o:<\/p>\n<p><\/p>\n<ul>\n<li>erl opts: +A1 +sbtu.<\/li>\n<li>O teste em um \u00fanico n\u00f3 Erlang \u00e9 executado em um laptop com um antigo i7 em vers\u00e3o m\u00f3vel.<\/li>\n<li>Os testes em cluster s\u00e3o realizados em servidores com rede de 10G.<\/li>\n<li>O c\u00f3digo funciona em cont\u00eaineres Docker. A rede est\u00e1 em modo NAT.<\/li>\n<\/ul>\n<p><\/p>\n<p>C\u00f3digo do teste:<\/p>\n<p><\/p>\n<pre><code class=\"erlang\">req_resp_bench(_) -&gt;\n  W = perftest:comprehensive(10000,\n    fun() -&gt;\n      messaging:request(?EXCHANGE, default, ping, self()),\n      receive\n        #'$msg'{message = pong} -&gt; ok\n      after 5000 -&gt;\n        throw(timeout)\n      end\n    end\n  ),\n  true = lists:any(fun(E) -&gt; E &gt;= 30000 end, W),\n  ok.<\/code><\/pre>\n<p><\/p>\n<p><em>Cen\u00e1rio 1:<\/em> O teste \u00e9 executado em um laptop com um velho i7 de vers\u00e3o m\u00f3vel. O teste, o messaging e o servi\u00e7o s\u00e3o executados em um \u00fanico n\u00f3 dentro de um cont\u00eainer Docker:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Ciclos sequenciais de 10000 em ~0 segundos (26987 ciclos\/s)\nCiclos sequenciais de 20000 em ~1 segundo (26915 ciclos\/s)\nCiclos sequenciais de 100000 em ~4 segundos (26957 ciclos\/s)\nCiclos paralelos de 2 100000 em ~2 segundos (44240 ciclos\/s)\nCiclos paralelos de 4 100000 em ~2 segundos (53459 ciclos\/s)\nCiclos paralelos de 10 100000 em ~2 segundos (52283 ciclos\/s)\nCiclos paralelos de 100 100000 em ~3 segundos (49317 ciclos\/s)<\/code><\/pre>\n<p><\/p>\n<p><em>Cen\u00e1rio 2<\/em>: 3 n\u00f3s executados em m\u00e1quinas diferentes sob Docker (NAT).<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">Ciclos sequenciais de 10000 em ~1 segundo (8684 ciclos\/s)\nCiclos sequenciais de 20000 em ~2 segundos (8424 ciclos\/s)\nCiclos sequenciais de 100000 em ~12 segundos (8655 ciclos\/s)\nCiclos paralelos de 2 100000 em ~7 segundos (15160 ciclos\/s)\nCiclos paralelos de 4 100000 em ~5 segundos (19133 ciclos\/s)\nCiclos paralelos de 10 100000 em ~4 segundos (24399 ciclos\/s)\nCiclos paralelos de 100 100000 em ~3 segundos (34517 ciclos\/s)<\/code><\/pre>\n<p><\/p>\n<p>Em todos os casos, a utiliza\u00e7\u00e3o da CPU n\u00e3o ultrapassou 250%<\/p>\n<p><\/p>\n<h2 id=\"itogi\">Resultados<\/h2>\n<p><\/p>\n<p>Espero que este ciclo n\u00e3o pare\u00e7a um despejo de consci\u00eancia e que minha experi\u00eancia traga um benef\u00edcio real tanto para os pesquisadores de sistemas distribu\u00eddos quanto para os profissionais que est\u00e3o no in\u00edcio da jornada de constru\u00e7\u00e3o de arquiteturas distribu\u00eddas para seus sistemas empresariais e que observam com interesse o Erlang\/Elixir, mas se perguntam se vale a pena...<\/p>\n<p><\/p>\n<p>Foto <noindex><a rel=\"nofollow\" href=\"https:\/\/unsplash.com\/photos\/Q4bmoSPJM18\">@chuttersnap<\/a><\/noindex><\/p>\n<p class=\"for_users_only_msg\">Apenas usu\u00e1rios registrados podem participar da pesquisa. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Entre<\/a><\/noindex>, por favor.<\/p>\n<h2 class=\"default-block__polling-title\">Quais t\u00f3picos devo abordar mais detalhadamente no ciclo 'Experimento VTrade'?<\/h2>\n<ul class=\"content-list content-list_polling\">\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Teoria: Mercados, ordens e per\u00edodos de validade: DAY, GTD, GTC, IOC, FOK, MOO, MOC, LOO, LOC<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Livro de ordens. Teoria e pr\u00e1tica da implementa\u00e7\u00e3o do livro com agrupamentos<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Visualiza\u00e7\u00e3o de negocia\u00e7\u00f5es: Ticks, barras, resolu\u00e7\u00f5es. Como armazenar e como compor<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Backoffice. Planejamento e desenvolvimento. Controle de funcion\u00e1rios e investiga\u00e7\u00e3o de incidentes<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    API. Vamos entender quais interfaces s\u00e3o necess\u00e1rias e como implement\u00e1-las<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Armazenamento de informa\u00e7\u00f5es: PostgreSQL, Timescale, Tarantool em sistemas de negocia\u00e7\u00e3o<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Reatividade em sistemas de negocia\u00e7\u00e3o<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Outro. Escreverei nos coment\u00e1rios<\/p>\n<\/li>\n<\/ul>\n<p>    6 usu\u00e1rios votaram. 4 usu\u00e1rios se abstiveram.<br \/>\n<br \/>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/446344\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0410\u043d\u043e\u043d\u0441 \u041a\u043e\u043b\u043b\u0435\u0433\u0438, \u0432 \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 \u043b\u0435\u0442\u0430 \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0432\u044b\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0441\u0438\u0441\u0442\u0435\u043c \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0433\u043e \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u044f: \u201c\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442 VTrade\u201d \u2014 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c. \u0412 \u0446\u0438\u043a\u043b\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043d\u0430 \u0442\u0435\u043e\u0440\u0438\u044f \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0431\u0438\u0440\u0436\u0438, \u0430\u0443\u043a\u0446\u0438\u043e\u043d\u0430 \u0438 \u043c\u0430\u0433\u0430\u0437\u0438\u043d\u0430. \u0412 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043f\u0440\u043e\u0433\u043e\u043b\u043e\u0441\u043e\u0432\u0430\u0442\u044c \u0437\u0430 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u0432\u0430\u043c \u0442\u0435\u043c\u044b. \u042d\u0442\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u044e\u0449\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u0446\u0438\u043a\u043b\u0430 \u043f\u043e \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":23092,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-31124","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0410\u043d\u043e\u043d\u0441 \u041a\u043e\u043b\u043b\u0435\u0433\u0438, \u0432 \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 \u043b\u0435\u0442\u0430 \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0432\u044b\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0441\u0438\u0441\u0442\u0435\u043c \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0433\u043e \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u044f: \u201c\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442 VTrade\u201d \u2014 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-priblizhenie\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"pt_PT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0421\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u0412\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u0438\u0435 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0410\u043d\u043e\u043d\u0441 \u041a\u043e\u043b\u043b\u0435\u0433\u0438, \u0432 \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 \u043b\u0435\u0442\u0430 \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0432\u044b\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0441\u0438\u0441\u0442\u0435\u043c \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0433\u043e \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u044f: \u201c\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442 VTrade\u201d \u2014 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-priblizhenie\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:39:36+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:39:36+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Elementos b\u00e1sicos de aplica\u00e7\u00f5es distribu\u00eddas. Segunda aproxima\u00e7\u00e3o | ProHoster","description":"An\u00fancio Colegas, no meio do ver\u00e3o, planejo lan\u00e7ar mais um ciclo de artigos sobre o design de sistemas de atendimento em massa: 'Experimento VTrade' \u2014 uma tentativa de escrever um framework para negocia\u00e7\u00f5es.","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-priblizhenie","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0421\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u0412\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u0438\u0435 | ProHoster","og:description":"\u0410\u043d\u043e\u043d\u0441 \u041a\u043e\u043b\u043b\u0435\u0433\u0438, \u0432 \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 \u043b\u0435\u0442\u0430 \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0432\u044b\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0441\u0438\u0441\u0442\u0435\u043c \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0433\u043e \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u044f: \u201c\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442 VTrade\u201d \u2014 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445.","og:url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/stroitelnye-bloki-raspredelennyh-prilozhenij-vtoroe-priblizhenie","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:39:36+00:00","article:modified_time":"2019-10-31T18:39:36+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"31124","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 04:39:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 03:22:34","updated":"2026-01-21 04:39:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/31124","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=31124"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/31124\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/23092"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=31124"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=31124"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=31124"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}