From eab6898383ded6729826d550ee6071e64e28befa Mon Sep 17 00:00:00 2001 From: Julio Biason Date: Thu, 26 Dec 2019 11:14:16 -0300 Subject: [PATCH] Microservice artifacts --- config.toml | 2 - .../microservices-artifact-input-state.md | 89 ++++++++++++++++++ .../microservices-artifact-input-state.pt.md | 94 +++++++++++++++++++ 3 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 content/code/microservices-artifact-input-state.md create mode 100644 content/code/microservices-artifact-input-state.pt.md diff --git a/config.toml b/config.toml index 86133a2..f163401 100644 --- a/config.toml +++ b/config.toml @@ -28,8 +28,6 @@ highlight_code = true default_language = "en" languages = [ - {code = "en", rss = true}, - {code = "en", search = false}, {code = "pt", rss = true}, {code = "pt", search = false}, ] diff --git a/content/code/microservices-artifact-input-state.md b/content/code/microservices-artifact-input-state.md new file mode 100644 index 0000000..6c16bb1 --- /dev/null +++ b/content/code/microservices-artifact-input-state.md @@ -0,0 +1,89 @@ ++++ +title = "Microservices: Artifact = Input + State" +date = 2019-12-26 + +[taxonomies] +tags = ["microservices", "artifacts", "state"] ++++ + +Designing microservices is a bit complicated because you have to think about +different things when deciding which "domain" it will occupy. A recent +discussion with coworkers about our current microservices design led me to +rethink how to think about microservices. + + + +This may sound a bit weird for those already working with microservices -- or +that managed to build a good view of the building of microservices -- but when +the word "artifact" popped up in a discussion, it "clicked" with a bunch of +other stuff I had in mind about the topic. + +One fact that kept confusing me was that a lot of literature about +microservices talk about "domain separation" and how to figure out each +domain. Now, although there are a few tricks -- like "if it is a noun, it is a +domain" -- not everything is clear cut. Some domains are actually subdomains +of a larger domain, so you keep wondering if you should split those or keep +them into a single microservice, since splitting them would, invariably, +making the microservices coupled (something you want to avoid when building +microservices). + +And that's where "artifact" felt into place. For a while, I had the impression +that microservices had to be built "backwards", in the sense that first you +have to think in what you _need_ and then check what you _have_ -- in other +words, you have to think on your outputs before checking your inputs. And an +"artifact" is, in the end, just the output of the microservice. + +In our case, we are dealing with games. Each game has a narration, it has an +score, it has statistics and it has a roster. Even if it falls into the "it's +a noun!" rule, it actually resembles the required output of our system: we +have a request that gets the current narration of a game (which can be polled +from time to time or -- as we are currently working on -- pushed towards +clients); one request returns the match score (which, again, can be polled or +pushed); one request retrieves the match statistics, which is not frequently +updated or displayed, so it doesn't need constant updates; and so on. Each one +of those is a different microservice, because each one of those is a different +artifact. + +Alright, if those are artifacts, where does "state" gets into this? The state +is the amount of information a microservice has to keep in order to build the +artifact. For example, in the narration, each time a new narration comes in, +it has to be added to a game list of narrations in order to produce the +narration of the whole match. The state can also help this microservice into +dropping duplicate narrations. + +One "nice" effect of the state is that you can, in theory at least, be able to +recognize that even with an input, if there was no change in the state, there +should be no change in the artifact and, thus, no output is necessary. + +Another thing to keep in mind about the state is that you don't need to keep +it in memory; you can use any kind of storage: keep the narrations in a +database, keep it on a disk, keep in memory as a cache, or all the above. You +pick whatever it is _easier_ to manipulate said state to produce the artifact. +The thing to keep in mind is "If this microservice crashes, will it be able to +rebuild its previous state when it restarts?" + +And, finally, the inputs. Those may sound a bit obvious at first (is your +microservice generating data out of thin air?), but keep in mind is that one +input can be be the source of more than one microservice. For example, a +narration may be consumed by the narration microservice to produce the whole +game narration, but it may also be consumed by the score microservice, +listening to goal narrations to update its state (if the narration is not a +goal, there is no change in score, there is no change in the state and there +is no artifact generation). + +Returning to artifacts, do not worry if more than one microservice doing +almost the same thing, but generating a complete different artifact. As an +example, imagine that you want to use push notifications to report new goals. +Although this is very close to the score microservice, it produces a different +artifact (the push notification vs the update score request) and, by this, +should be a complete different microservice. It may even sound wasteful (doing +the same thing twice), but it would decouple things if you need some other +information in the score (say, adding the name of the players who did the +goals) or if you change the artifact consumer (say, you change from an in-hour +implementation of pushing to Apple and Google to using a service for this, +like Azure). + +This change in the my way of thinking about microservices design help me +rethink the way we are building our microservices at work, and it is also +helping me rethink some things on a personal project (which I hope to finish +and show it next year). diff --git a/content/code/microservices-artifact-input-state.pt.md b/content/code/microservices-artifact-input-state.pt.md new file mode 100644 index 0000000..11e196a --- /dev/null +++ b/content/code/microservices-artifact-input-state.pt.md @@ -0,0 +1,94 @@ ++++ +title = "Microserviços: Artefato = Entrada + Estado" +date = 2019-12-26 + +[taxonomies] +tags = ["microserviços", "artefatos", "estado"] ++++ + +Projetar microserviços é um pouco complicado porque temos que pensar sobre +as coisas que cada "domínio" vai ocupar. Uma discussão entre os +desenvolvedores aqui sobre nossos projetos de microserviços me levou a +repensar como pensar microserviços. + + + +Isso pode soar um pouco estranho para aqueles que já estão trabalhando com +microserviços -- ou que conseguiram ter uma boa visão da construção de +microserviços -- mas quando foi citado "artefato" na discussão, "caiu a ficha" +com outras coisas que eu estava pensando sobre o tópico. + +Um fato que continua me confundindo é que a literatura sobre microserviços +começa a falar sobre "separação de domínios" e como definir cada domínio. +Embora haja alguns truques -- como "se é um substantivo, é um domínio" -- nada +é realmente tão óbvio. Alguns domínios são, na verdade, sub domínios de um +domínio maior, e aí você fica se perguntando se deve separar esses domínios ou +mantê-los num único microserviço, já que separá-los iria, invariavelmente, +criar microserviços acoplados (algo que você quer evitar quando está usando +microserviços). + +E é aí que "artefato" encaixou no resto das coisas. Por algum tempo, eu tive a +impressão que microserviços tem que ser construídos "de trás pra frente", no +sentido de que primeiro você precisa pensar nas coisas que você _precisa_ e +depois verificar o que você _tem_ -- em outras palavras, você pensa primeiro +nas saídas do microserviço e depois olha o que tem de entrada. E um "artefato" +é, no final, simplesmente a saída do microserviço. + +No nosso caso, nós estamos lidado com jogos. Cada jogo tem uma narração, tem +um placar, tem estatística e tem uma escalação. Mesmo que essa explicação +caia na regra do "é um substantivo!", na verdade ela reflete a saída do nosso +sistema: nos temos uma requisição que retorna a narração atual do jogo (que +pode ser atualizada por polling ou -- como estamos trabalhando agora -- feito +"push" diretamente para os clientes); uma requisição para retornar o placar +(que, de novo, pode ser por "polling" ou "push"); uma requisição que retorna +as estatísticas, que não são atualizadas ou exibidas de forma tão frequente, +e por isso não precisam de atualizações visuais constantes; e assim por +diante. Cada um desses é um microserviço diferente, porque cada um desses é um +artefato diferente. + +Bom, se esses são os artefatos, onde é que o "estado" entra nessa história? O +estado é o conjunto de informações que o microserviço precisa ter para +produzir o artefato. Por exemplo, na narração, cada vez que uma nova narração +entra, ela precisa entrar na lista de narrações do jogo para que seja +produzida a narração da partida inteira. O estado também pode ajudar o +microserviço a remover narrações duplicadas. + +Um efeito "legal" do estado é que você pode, pelo menos na teoria, perceber +que mesmo com uma nova entrada, se não houve alteração do estado, então não +vai haver alteração do artefato e não é preciso ter nenhuma saída. + +Outra coisa a se ter em mente sobre o estado é que ele não precisa ser mantido +em memória; você pode usar qualquer tipo de armazenamento: mantenha as +narrações num banco de dados, no disco, na memória em cache ou todos os +anteriores. Decida usar o que ficar mais _fácil_ de ser manipulado para +produzir o artefato. Uma coisa a se manter em mente sobre isso é "Se esse +microserviço morrer, ele vai conseguir voltar ao mesmo estado quando for +reiniciado?" + +E, finalmente, as entradas. Essas podem parecer meio óbvias a princípio (o seu +microserviço está gerando dados do nada?), mas mantenha em mente que uma +entrada pode ser a origem de dados de mais de um microserviço. Por exemplo, +uma narração pode ser consumida pelo microserviço de narrações para produzir a +narração inteira da partida, mas também ser consumida pelo microserviço de +placar, que fica escutando narrações de gols para atualizar seu estado (se a +narração não for de gol, não há alteração de placar, não há alteração de +estado e não há geração do artefato). + +Voltando aos artefatos, não se preocupe se mais de um microserviço faz +basicamente a mesma coisa que outra, mas gera um artefato completamente +diferente. Como exemplo, imagine que você quer que sejam feitas notificações +por push quando acontece um gol. Embora seja um serviço bem parecido com o +microserviço de placar, ele produz um artefato diferente (a notificação por +push vs a requisição de atualização de placar) e, por isso, deveria ser um +microserviço completamente diferente. Até pode soar meio desnecessário (ter +serviços fazendo a mesma coisa, duas vezes), mas isso desacopla as coisas se +você precisar mais informações no placar (por exemplo, adicionando o nome de +cada jogador que fizeram gols) ou mudar o consumidor do artefato (por exemplo, +mudando a implementação do push para, ao invés de fazer as chamadas +diretamente paras a APIs da Apple e Google, fazer chamadas para um serviço que +já faça tudo isso, como o da Azure). + +Essa mudança na minha forma de pensar como construir microserviços me ajudou a +pensar nos nossos microserviços no trabalho, e também está me ajudando a +repensar algumas saídas em um projeto pessoal (que eu espero terminar e +mostrar no ano que vêm).