#Implantação

0 Seguidores · 14 Postagens

Implantação de software são todas as atividades que tornam um sistema de software disponível para uso. O processo geral de implantação consiste em várias atividades inter-relacionadas com possíveis transições entre elas. 

Artigo Danusa Calixto · Set. 17, 2025 3m read

Olá, pessoal! Tendo me integrado recentemente à InterSystems, percebi que, apesar de ter uma Edição Comunitária totalmente gratuita e incrível, não é muito claro como obtê-la. Decidi escrever um guia destacando todas as diferentes maneiras de acessar a Edição Comunitária do InterSystems IRIS:

Obtenha o InterSystems IRIS Community Edition como um contêiner

Trabalhar com uma instância em contêiner da Community Edition é a abordagem recomendada para quem está começando a desenvolver no InterSystems IRIS e, na minha opinião, é a mais simples. A Community Edition do InterSystems IRIS pode ser encontrada no DockerHub; se você tiver uma conta InterSystems SSO, também poderá encontrá-la no Registro de Contêineres da InterSystems.

Em ambos os casos, você vai querer extrair a imagem desejada usando o Docker CLI:

docker pull intersystems/iris-community:latest-em
// or
docker pull containers.intersystems.com/intersystems/iris-community:latest-em

Em seguida, você precisará iniciar o contêiner: para interagir com o IRIS de fora do contêiner (por exemplo, para usar o portal de gerenciamento), você precisará publicar algumas portas. O comando a seguir executará o contêiner IRIS Community Edition com as portas do superservidor e do servidor web publicadas; observe que você não pode executar nada que dependa das portas 1972 ou 52773!

docker run --name iris -d --publish 1972:1972 --publish 52773:52773 intersystems/iris-community:latest-em
0
0 35
Artigo Heloisa Paiva · Abr. 1, 2025 19m read

Frequentemente, clientes, fornecedores ou equipes internas me pedem para explicar o planejamento de capacidade de CPU para para grandes bancos de dados de produção rodando no VMware vSphere.

Em resumo, existem algumas práticas recomendadas simples a seguir para dimensionar a CPU para grandes bancos de dados de produção:

  • Planeje um vCPU por núcleo de CPU físico.
  • Considere o NUMA e, idealmente, dimensione as VMs para manter a CPU e a memória locais para um nó NUMA.
  • Dimensione as máquinas virtuais corretamente. Adicione vCPUs apenas quando necessário.

Geralmente, isso leva a algumas perguntas comuns:

  • Devido ao hyper-threading, o VMware me permite criar VMs com o dobro do número de CPUs físicas. Isso não dobra a capacidade? Não devo criar VMs com o máximo de CPUs possível?
  • O que é um nó NUMA? Devo me preocupar com o NUMA?
  • As VMs devem ser dimensionadas corretamente, mas como sei quando estão?

Respondo a estas perguntas com exemplos abaixo. Mas também lembre-se, as melhores práticas não são imutáveis. Às vezes, você precisa fazer concessões. Por exemplo, é provável que grandes VMs de banco de dados de produção NÃO caibam em um nó NUMA e, como veremos, isso está OK. As melhores práticas são diretrizes que você terá que avaliar e validar para seus aplicativos e ambiente.~

Embora eu esteja escrevendo isso com exemplos para bancos de dados rodando em plataformas de dados InterSystems, os conceitos e regras se aplicam geralmente ao planejamento de capacidade e desempenho para qualquer VM grande (Monstro).


Para melhores práticas de virtualização e mais posts sobre planejamento de desempenho e capacidade; [Uma lista de outros posts na série de Plataformas de Dados InterSystems e desempenho está aqui.](https://community.intersystems.com/post/capacity-planning-and-performance-series-index)

#VMs Monstruosas

Este post é principalmente sobre a implantação de _VMs Monstruosas _, às vezes chamadas de VMs Largas. Os requisitos de recursos de CPU de bancos de dados de alta transação significam que eles são frequentemente implantados em VMs Monstruosas.

Uma VM monstruosa é uma VM com mais CPUs virtuais ou memória do que um nó NUMA físico.


# Arquitetura de CPU e NUMA

A arquitetura de processador Intel atual possui arquitetura de Memória de Acesso Não Uniforme (NUMA). Por exemplo, os servidores que estou usando para executar testes para este post têm:

  • Dois sockets de CPU, cada um com um processador de 12 núcleos (Intel E5-2680 v3).
  • 256 GB de memória (16 x 16GB RDIMM)

Cada processador de 12 núcleos tem sua própria memória local (128 GB de RDIMMs e cache local) e também pode acessar a memória em outros processadores no mesmo host. Os pacotes de 12 núcleos de CPU, cache de CPU e 128 GB de memória RDIMM são um nó NUMA. Para acessar a memória em outro processador, os nós NUMA são conectados por uma interconexão rápida.

Processos em execução em um processador que acessam a memória RDIMM e Cache local têm menor latência do que atravessar a interconexão para acessar a memória remota em outro processador. O acesso através da interconexão aumenta a latência, então o desempenho não é uniforme. O mesmo design se aplica a servidores com mais de dois sockets. Um servidor Intel de quatro sockets tem quatro nós NUMA.

O ESXi entende o NUMA físico e o agendador de CPU do ESXi é projetado para otimizar o desempenho em sistemas NUMA. Uma das maneiras pelas quais o ESXi maximiza o desempenho é criar localidade de dados em um nó NUMA físico. Em nosso exemplo, se você tiver uma VM com 12 vCPUs e menos de 128 GB de memória, o ESXi atribuirá essa VM para ser executada em um dos nós NUMA físicos. O que leva à regra;

Se possível, dimensione as VMs para manter a CPU e a memória locais em um nó NUMA.

Se você precisar de uma VM Monstruosa maior que um nó NUMA, está OK, o ESXi faz um trabalho muito bom calculando e gerenciando automaticamente os requisitos. Por exemplo, o ESXi criará nós NUMA virtuais (vNUMA) que agendam de forma inteligente nos nós NUMA físicos para um desempenho ideal. A estrutura vNUMA é exposta ao sistema operacional. Por exemplo, se você tiver um servidor host com dois processadores de 12 núcleos e uma VM com 16 vCPUs, o ESXi pode usar oito núcleos físicos em cada um dos dois processadores para agendar vCPUs da VM, o sistema operacional (Linux ou Windows) verá dois nós NUMA.

Também é importante dimensionar corretamente suas VMs e não alocar mais recursos do que o necessário, pois isso pode levar a recursos desperdiçados e perda de desempenho. Além de ajudar a dimensionar para NUMA, é mais eficiente e resultará em melhor desempenho ter uma VM de 12 vCPUs com alta (mas segura) utilização de CPU do que uma VM de 24 vCPUs com utilização de CPU de VM baixa ou mediana, especialmente se houver outras VMs neste host precisando ser agendadas e competindo por recursos. Isso também reforça a regra;

Dimensione as máquinas virtuais corretamente.

Nota: Existem diferenças entre as implementações NUMA da Intel e da AMD. A AMD tem múltiplos nós NUMA por processador. Já faz um tempo desde que vi processadores AMD em um servidor de cliente, mas se você os tiver, revise o layout NUMA como parte do seu planejamento.


## VMs Largas e Licenciamento

Para o melhor agendamento NUMA, configure VMs largas; Correção Junho de 2017: Configure VMs com 1 vCPU por socket. Por exemplo, por padrão, uma VM com 24 vCPUs deve ser configurada como 24 sockets de CPU, cada um com um núcleo.

Siga as regras de melhores práticas do VMware..

Consulte este post nos blogs do VMware para exemplos. 

O post do blog do VMware entra em detalhes, mas o autor, Mark Achtemichuk, recomenda as seguintes regras práticas:

  • Embora existam muitas configurações avançadas de vNUMA, apenas em casos raros elas precisam ser alteradas dos padrões.
  • Sempre configure a contagem de vCPU da máquina virtual para ser refletida como Núcleos por Socket, até que você exceda a contagem de núcleos físicos de um único nó NUMA físico.
  • Quando você precisar configurar mais vCPUs do que há núcleos físicos no nó NUMA, divida uniformemente a contagem de vCPU pelo número mínimo de nós NUMA.
  • Não atribua um número ímpar de vCPUs quando o tamanho da sua máquina virtual exceder um nó NUMA físico.
  • Não habilite o Hot Add de vCPU a menos que você esteja OK com o vNUMA sendo desabilitado.
  • Não crie uma VM maior que o número total de núcleos físicos do seu host.t.

O licenciamento do Caché conta núcleos, então isso não é um problema, no entanto, para software ou bancos de dados diferentes do Caché, especificar que uma VM tem 24 sockets pode fazer diferença para o licenciamento de software, então você deve verificar com os fornecedores.


# Hyper-threading e o agendador de CPU

Hyper-threading (HT) frequentemente surge em discussões, e ouço: "hyper-threading dobra o número de núcleos de CPU". O que, obviamente, no nível físico, não pode acontecer — você tem tantos núcleos físicos quanto possui. O Hyper-threading deve ser habilitado e aumentará o desempenho do sistema. A expectativa é talvez um aumento de 20% ou mais no desempenho do aplicativo, mas a quantidade real depende do aplicativo e da carga de trabalho. Mas certamente não o dobro.

Como postei no post de melhores práticas do VMware, um bom ponto de partida para dimensionar grandes VMs de banco de dados de produção ié assumir que o vCPU tem dedicação total de núcleo físico no servidor — basicamente ignore o hyper-threading ao planejar a capacidade. Por exemplo;

Para um servidor host de 24 núcleos, planeje um total de até 24 vCPUs para VMs de banco de dados de produção, sabendo que pode haver folga disponível.

Após dedicar tempo monitorando o desempenho da aplicação, do sistema operacional e do VMware durante os horários de pico de processamento, você pode decidir se uma consolidação de VMs mais alta é possível. Na postagem de melhores práticas, eu estabeleci a regra como;

Um CPU físico (inclui hyper-threading) = Um vCPU (inclui hyper-threading).


## Por que o Hyper-threading não dobra o CPU

O HT em processadores Intel Xeon é uma forma de criar dois CPUs _lógicos _ CPUsem um núcleo físico. O sistema operacional pode agendar eficientemente nos dois processadores lógicos — se um processo ou thread em um processador lógico estiver esperando, por exemplo, por E/S, os recursos do CPU físico podem ser usados pelo outro processador lógico Apenas um processador lógico pode estar progredindo em qualquer ponto no tempo, então, embora o núcleo físico seja utilizado de forma mais eficiente, o desempenho não é dobrado.

Com o HT habilitado na BIOS do host, ao criar uma VM, você pode configurar um vCPU por processador lógico HT. Por exemplo, em um servidor de 24 núcleos físicos com HT habilitado, você pode criar uma VM com até 48 vCPUs. O agendador de CPU do ESXi otimizará o processamento executando os processos das VMs em núcleos físicos separados primeiro (enquanto ainda considera o NUMA). Eu exploro mais adiante na postagem se alocar mais vCPUs do que núcleos físicos em uma VM de banco de dados "Monster" ajuda no escalonamento.

Co-stop e agendamento de CPU

Após monitorar o desempenho do host e da aplicação, você pode decidir que algum sobrecomprometimento dos recursos de CPU do host é possível. Se esta é uma boa ideia dependerá muito das aplicações e cargas de trabalho. Uma compreensão do agendador e uma métrica chave para monitorar podem ajudá-lo a ter certeza de que você não está sobrecomprometendo os recursos do host.

Às vezes ouço; para que uma VM progrida, deve haver o mesmo número de CPUs lógicos livres que vCPUs na VM. Por exemplo, uma VM de 12 vCPUs deve 'esperar' que 12 CPUs lógicos estejam 'disponíveis' antes que a execução progrida. No entanto, deve-se notar que, no ESXi após a versão 3, este não é o caso. O ESXi usa co-agendamento relaxado para CPU para melhor desempenho da aplicação.

Como múltiplos threads ou processos cooperativos frequentemente se sincronizam uns com os outros, não agendá-los juntos pode aumentar a latência em suas operações. Por exemplo, um thread esperando para ser agendado por outro thread em um loop de espera ocupada (spin loop). Para melhor desempenho, o ESXi tenta agendar o máximo possível de vCPUs irmãs juntas. Mas o agendador de CPU pode agendar vCPUs de forma flexível quando há múltiplas VMs competindo por recursos de CPU em um ambiente consolidado. Se houver muita diferença de tempo, enquanto algumas vCPUs progridem e outras irmãs não (a diferença de tempo é chamada de skew), então a vCPU líder decidirá se interrompe a si mesma (co-stop). Observe que são as vCPUs que fazem co-stop (ou co-start), não a VM inteira. Isso funciona muito bem mesmo quando há algum sobrecomprometimento de recursos, no entanto, como você esperaria; muito sobrecomprometimento de recursos de CPU inevitavelmente impactará o desempenho. Mostro um exemplo de sobrecomprometimento e co-stop mais adiante no Exemplo 2.

Lembre-se que não é uma corrida direta por recursos de CPU entre VMs; o trabalho do agendador de CPU do ESXi é garantir que políticas como shares de CPU, reservas e limites sejam seguidas, maximizando a utilização da CPU e garantindo justiça, throughput, responsividade e escalabilidade. Uma discussão sobre o uso de reservas e shares para priorizar cargas de trabalho de produção está além do escopo desta postagem e depende da sua aplicação e mix de cargas de trabalho. Posso revisitar isso em um momento posterior se encontrar alguma recomendação específica do Caché. Existem muitos fatores que entram em jogo com o agendador de CPU, esta seção apenas arranha a superfície. Para um mergulho profundo, consulte o white paper da VMware e outros links nas referências no final da postagem.


# Exemplos

Para ilustrar as diferentes configurações de vCPU, executei uma série de benchmarks usando um aplicativo de Sistema de Informação Hospitalar baseado em navegador com alta taxa de transações. Um conceito semelhante ao benchmark de banco de dados DVD Store desenvolvido pela VMware.

Os scripts para o benchmark são criados com base em observações e métricas de implementações hospitalares reais e incluem fluxos de trabalho, transações e componentes de alto uso que utilizam os maiores recursos do sistema. VMs de driver em outros hosts simulam sessões web (usuários) executando scripts com dados de entrada aleatórios em taxas de transação de fluxo de trabalho definidas. Um benchmark com uma taxa de 1x é a linha de base. As taxas podem ser aumentadas e diminuídas em incrementos.

Juntamente com as métricas do banco de dados e do sistema operacional, uma boa métrica para avaliar o desempenho da VM do banco de dados do benchmark é o tempo de resposta do componente (que também pode ser uma transação) medido no servidor. Um exemplo de um componente é parte de uma tela do usuário final. Um aumento no tempo de resposta do componente significa que os usuários começariam a ver uma mudança para pior no tempo de resposta do aplicativo. Um sistema de banco de dados com bom desempenho deve fornecer alto desempenho consistente para os usuários finais. Nos gráficos a seguir, estou medindo em relação ao desempenho consistente do teste e uma indicação da experiência do usuário final, calculando a média do tempo de resposta dos 10 componentes de alto uso mais lentos. O tempo de resposta médio do componente deve ser inferior a um segundo, uma tela de usuário pode ser composta por um componente, ou telas complexas podem ter muitos componentes.

Lembre-se de que você sempre está dimensionando para a carga de trabalho máxima, mais um buffer para picos inesperados de atividade. Geralmente, busco uma utilização média de 80% da CPU no pico.

Uma lista completa do hardware e software do benchmark está no final da postagem.


## Exemplo 1. Dimensionamento correto - VM "monstro" única por host

É possível criar uma VM de banco de dados dimensionada para usar todos os núcleos físicos de um servidor host, por exemplo, uma VM de 24 vCPUs em um host de 24 núcleos físicos. Em vez de executar o servidor "bare-metal" em um espelho de banco de dados Caché para alta disponibilidade (HA) ou introduzir a complicação do clustering de failover do sistema operacional, a VM do banco de dados é incluída em um cluster vSphere para gerenciamento e HA, por exemplo, DRS e VMware HA.

Tenho visto clientes seguirem o pensamento da velha guarda e dimensionarem uma VM de banco de dados primária para a capacidade esperada no final da vida útil de cinco anos do hardware, mas como sabemos acima, é melhor dimensionar corretamente; você obterá melhor desempenho e consolidação se suas VMs não forem superdimensionadas e o gerenciamento de HA será mais fácil; pense em Tetris se houver manutenção ou falha do host e a VM monstro do banco de dados tiver que migrar ou reiniciar em outro host. Se a taxa de transações for prevista para aumentar significativamente, os vCPUs podem ser adicionados antecipadamente durante a manutenção planejada.

Observação, a opção de 'adicionar a quente' (hot add) de CPU desativa o vNUMA, portanto, não a use para VMs monstro.

Considere o seguinte gráfico mostrando uma série de testes no host de 24 núcleos. A taxa de transações 3x é o ponto ideal e a meta de planejamento de capacidade para este sistema de 24 núcleos.

  • Uma única VM está sendo executada no host.
  • Quatro tamanhos de VM foram usados para mostrar o desempenho em 12, 24, 36 e 48 vCPUs.
  • Taxas de transação (1x, 2x, 3x, 4x, 5x) foram executadas para cada tamanho de VM (se possível).
  • O desempenho/experiência do usuário é mostrado como o tempo de resposta do componente (barras).
  • Utilização média da CPU% na VM convidada (linhas).
  • A utilização da CPU do host atingiu 100% (linha tracejada vermelha) na taxa de 4x para todos os tamanhos de VM.

![Host com 24 Núcleos Físicos Média de porcentagem de CPU da VM de um único convidado e tempo de resposta do componente ](https://community.intersystems.com/sites/default/files/inline/images/single_guest_vm.png "Single Guest VM")

Há muita coisa acontecendo neste gráfico, mas podemos nos concentrar em algumas coisas interessantes.

  • A VM com 24 vCPUs (laranja) escalou suavemente para a taxa de transação alvo de 3x. Com a taxa de 3x, a VM convidada está com uma média de 76% de CPU (picos foram em torno de 91%). A utilização da CPU do host não é muito maior do que a da VM convidada. O tempo de resposta do componente é praticamente plano até 3x, então os usuários estão satisfeitos. Quanto à nossa taxa de transação alvo — esta VM está dimensionada corretamente.

Então, chega de dimensionamento correto, e quanto a aumentar as vCPUs, o que significa usar hyper threads? É possível dobrar o desempenho e a escalabilidade? A resposta curta é Não!

Neste caso, a resposta pode ser vista observando o tempo de resposta do componente a partir de 4x. Embora o desempenho seja "melhor" com mais núcleos lógicos (vCPUs) alocados, ele ainda não é plano e consistente como era até 3x. Os usuários relatarão tempos de resposta mais lentos em 4x, independentemente de quantas vCPUs forem alocadas. Lembre-se que em 4x o _host _ já está no limite, com 100% de utilização da CPU, conforme relatado pelo vSphere. Em contagens de vCPU mais altas, mesmo que as métricas de CPU do convidado (vmstat) estejam relatando menos de 100% de utilização, esse não é o caso para os recursos físicos. Lembre-se que o sistema operacional convidado não sabe que está virtualizado e está apenas relatando os recursos apresentados a ele. Observe também que o sistema operacional convidado não vê threads HT, todas as vCPUs são apresentadas como núcleos físicos.

O ponto é que os processos do banco de dados (existem mais de 200 processos Caché na taxa de transação 3x) estão muito ocupados e fazem um uso muito eficiente dos processadores, não há muita folga para os processadores lógicos agendarem mais trabalho ou consolidarem mais VMs neste host. Por exemplo, grande parte do processamento do Caché está ocorrendo na memória, então não há muita espera por IO. Portanto, embora você possa alocar mais vCPUs do que núcleos físicos, não há muito a ganhar porque o host já está 100% utilizado.

Caché é muito bom em lidar com altas cargas de trabalho. Mesmo quando o host e a VM estão com 100% de utilização da CPU, o aplicativo ainda está em execução e a taxa de transações ainda está aumentando — o escalonamento não é linear e, como podemos ver, os tempos de resposta estão ficando mais longos e a experiência do usuário sofrerá — mas o aplicativo não "cai de um penhasco" e, embora não seja um bom lugar para se estar, os usuários ainda podem trabalhar. Se você tiver um aplicativo que não é tão sensível aos tempos de resposta, é bom saber que você pode empurrar até o limite, e além, e o Caché ainda funciona com segurança.

Lembre-se de que você não deseja executar sua VM de banco de dados ou seu host com 100% de utilização da CPU. Você precisa de capacidade para picos inesperados e crescimento na VM, e o hipervisor ESXi precisa de recursos para todas as atividades de rede, armazenamento e outras que realiza.

Eu sempre planejo para picos de 80% de utilização da CPU. Mesmo assim, dimensionar a vCPU apenas até o número de núcleos físicos deixa alguma folga para o hipervisor ESXi em threads lógicos, mesmo em situações extremas.

Se você estiver executando uma solução hiperconvergente (HCI), você DEVE também considerar os requisitos de CPU do HCI no nível do host. Veja minha postagem anterior sobre HCI para mais detalhes. O dimensionamento básico da CPU de VMs implantadas em HCI é o mesmo que o de outras VMs.

Lembre-se, você deve validar e testar tudo em seu próprio ambiente e com seus aplicativos.


##Exemplo 2. Recursos supercomprometidos

Tenho visto sites de clientes relatando desempenho "lento" do aplicativo enquanto o sistema operacional convidado relata que há recursos de CPU de sobra.

Lembre-se de que o sistema operacional convidado não sabe que está virtualizado. Infelizmente, as métricas do convidado, por exemplo, conforme relatado pelo vmstat (por exemplo, em pButtons) podem ser enganosas, você também deve obter métricas de nível de host e métricas ESXi (por exemplo esxtop) para realmente entender a saúde e a capacidade do sistema.

Como você pode ver no gráfico acima, quando o host está relatando 100% de utilização, a VM convidada pode estar relatando uma utilização menor. A VM de 36 vCPU (vermelha) está relatando 80% de utilização média da CPU na taxa de 4x, enquanto o host está relatando 100%. Mesmo uma VM dimensionada corretamente pode ser privada de recursos, se, por exemplo, após a entrada em produção, outras VMs forem migradas para o host ou os recursos forem supercomprometidos por meio de regras DRS mal configuradas.

Para mostrar as principais métricas, para esta série de testes, configurei o seguinte:

  • Duas VMs de banco de dados em execução no host.
    • uma de 24 vCPU em execução a uma taxa de transação constante de 2x (não mostrada no gráfico).
  • -uma de 24 vCPU em execução a 1x, 2x, 3x (essas métricas são mostradas no gráfico).

Com outro banco de dados usando recursos; na taxa de 3x, o sistema operacional convidado (RHEL 7) vmstat está relatando apenas 86% de utilização média da CPU e a fila de execução tem uma média de apenas 25. No entanto, os usuários deste sistema estarão reclamando alto, pois o tempo de resposta do componente disparou à medida que os processos são desacelerados.

Como mostrado no gráfico a seguir, Co-stop e Tempo de Preparo contam a história de por que o desempenho do usuário é tão ruim. As métricas de Tempo de Preparo (%RDY) e CoStop (%CoStop) mostram que os recursos da CPU estão massivamente supercomprometidos na taxa alvo de 3x. Isso realmente não deveria ser uma surpresa, já que o host está executando 2x (outra VM) e a taxa de 3x desta VM de banco de dados.


![](https://community.intersystems.com/sites/default/files/inline/images/overcommit_3.png "Over-committed host")

O gráfico mostra que o tempo de espera (Ready time) aumenta quando a carga total da CPU no host aumenta.

Tempo de espera (Ready time) é o tempo em que uma VM está pronta para executar, mas não pode porque os recursos da CPU não estão disponíveis.

O co-stop também aumenta. Não há CPUs lógicas livres suficientes para permitir que a VM do banco de dados avance (como detalhei na seção HT acima). O resultado final é que o processamento é atrasado devido à contenção por recursos físicos da CPU.

Eu vi exatamente essa situação em um site de cliente onde nossa visão de suporte de pButtons e vmstat mostrava apenas o sistema operacional virtualizado. Enquanto o vmstat reportava folga de CPU, a experiência de desempenho do usuário era terrível.

A lição aqui é que só quando as métricas do ESXi e uma visão em nível de host foram disponibilizadas é que o problema real foi diagnosticado; recursos de CPU supercomprometidos causados por escassez geral de recursos de CPU do cluster e, para piorar a situação, regras DRS ruins fazendo com que VMs de banco de dados de alta transação migrassem juntas e sobrecarregassem os recursos do host.


## Exemplo 3. Recursos supercomprometidos

Neste exemplo, usei uma VM de banco de dados de linha de base de 24 vCPUs executando a uma taxa de transação 3x, e depois duas VMs de banco de dados de 24 vCPUs a uma taxa de transação constante de 3x.

A utilização média da CPU da linha de base (veja o Exemplo 1 acima) foi de 76% para a VM e 85% para o host. Uma única VM de banco de dados de 24 vCPUs está usando todos os 24 processadores físicos. Executar duas VMs de 24 vCPUs significa que as VMs estão competindo por recursos e estão usando todas as 48 threads de execução lógicas no servidor.


![](https://community.intersystems.com/sites/default/files/inline/images/overcommit_2vm.png "Over-committed host")

Lembrando que o host não estava 100% utilizado com uma única VM, ainda podemos ver uma queda significativa no throughput e no desempenho, pois duas VMs de 24 vCPUs muito ocupadas tentam usar os 24 núcleos físicos no host (mesmo com HT). Embora o Caché seja muito eficiente ao usar os recursos de CPU disponíveis, ainda há uma queda de 16% no throughput do banco de dados por VM e, mais importante, um aumento de mais de 50% no tempo de resposta do componente (usuário).


## Resumo

Meu objetivo com este post é responder às perguntas comuns. Veja a seção de referência abaixo para um mergulho mais profundo nos recursos de CPU do host e no agendador de CPU do VMware.

Embora existam muitos níveis de ajustes e detalhes técnicos do ESXi para extrair a última gota de desempenho do seu sistema, as regras básicas são bastante simples.

Para grandes bancos de dados de produção :

  • Planeje um vCPU por núcleo de CPU físico.
  • Considere o NUMA e, idealmente, dimensione as VMs para manter a CPU e a memória locais em um nó NUMA.
  • Dimensione corretamente as máquinas virtuais. Adicione vCPUs somente quando necessário.

Se você deseja consolidar VMs, lembre-se de que grandes bancos de dados são muito ocupados e utilizarão intensamente as CPUs (físicas e lógicas) em horários de pico. Não as superinscreva até que seu monitoramento indique que é seguro.


## Referências
## Testes

Executei os exemplos neste post em um cluster vSphere composto por dois processadores Dell R730 conectados a um array all-flash. Durante os exemplos, não houve gargalos na rede ou no armazenamento.

  • Caché 2016.2.1.803.0

PowerEdge R730

  • 2x Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz
  • 16x 16GB RDIMM, 2133 MT/s, Dual Rank, x4 Data Width
  • SAS 12Gbps HBA External Controller
  • HyperThreading (HT) on

PowerVault MD3420, 12G SAS, 2U-24 drive

  • 24x 24 960GB Solid State Drive SAS Read Intensive MLC 12Gbps 2.5in Hot-plug Drive, PX04SR
  • 2 Controller, 12G SAS, 2U MD34xx, 8G Cache

VMware ESXi 6.0.0 build-2494585

  • As VMs estão configuradas para as melhores práticas; VMXNET3, PVSCSI, etc.

RHEL 7

  • Páginas grandes (Large pages)

A taxa de linha de base 1x teve uma média de 700.000 glorefs/segundo (acessos ao banco de dados/segundo). A taxa 5x teve uma média de mais de 3.000.000 glorefs/segundo para 24 vCPUs. Os testes foram permitidos a serem executados até que o desempenho constante fosse alcançado e, em seguida, amostras de 15 minutos foram coletadas e calculadas a média.

Estes exemplos são apenas para mostrar a teoria, você DEVE validar com sua própria aplicação!


0
0 28
Pergunta Davidson Espindola · Dez. 6, 2024

Dear all, I hope you are well.

We migrated from CACHE 2018 to IRIS 2023.1 on 12/2/2024, and I am having a big problem identifying the client's IP address, because IRIS is getting an IP number with characters as if it were IPV6. Our LINUX support has already made all the configurations requested by Intersystems support, disabled IPv6, and several other configurations, but we have not been successful.

2
0 51
Artigo Danusa Calixto · Mar. 12, 2024 22m read

Olá, esta postagem foi escrita inicialmente para Caché. Em junho de 2023, finalmente a atualizei para IRIS. Se você está revisitando a postagem agora, a única mudança real foi a substituição do Caché pelo IRIS! Também atualizei os links para a documentação do IRIS e corrigi alguns erros de digitação e gramaticais. Aproveite :)


Nesta postagem, mostro estratégias para fazer backup do InterSystems IRIS usando o Backup Externo, incluindo exemplos da integração com soluções baseadas em cópias instantâneas. A maioria das soluções que vejo hoje são implantadas no Linux no VMware. Portanto, grande parte da postagem mostra as formas como as soluções integram a tecnologia de cópia instantânea VMware como exemplos.

Backup do IRIS - acompanha pilhas?

O backup online do IRIS está incluído na instalação do IRIS para backup contínuo dos bancos de dados do IRIS. Porém, há soluções de backup mais eficientes que você deve considerar ao ampliar os sistemas. O Backup Externo integrado com tecnologias de cópia instantânea é a solução recomendada para backup de sistemas, incluindo bancos de dados do IRIS.

Há alguma consideração especial para backup externo?

A documentação online do Backup Externo tem todos os detalhes. Uma consideração importante é:

"Para garantir a integridade cópia instantânea, o IRIS oferece métodos para congelar gravações em bancos de dados enquanto a cópia é criada. Somente as gravações físicas nos arquivos dos bancos de dados são congeladas durante a criação da cópia instantânea, permitindo que os processos do usuário continuem realizando atualizações na memória sem interrupções."

Também é importante observar que parte do processo de cópia em sistemas virtualizados causa uma pequena pausa no backup de uma VM, geralmente chamada de "tempo de stun". Ela costuma durar menos de um segundo, então não é percebida pelos usuários nem afeta a operação do sistema. Porém, em algumas circunstâncias, o stun pode durar mais tempo. Se o stun durar mais que o tempo limite de qualidade de serviço (QoS) para o espelhamento do banco de dados do IRIS, o nó de backup pensará que houve uma falha no primário e fará a tolerância a falhas. Mais adiante nesta postagem, explico como você pode revisar os tempos de stun caso precise alterar o tempo limite de QoS do espelhamento.


[Veja aqui uma lista de outras Plataformas de Dados da InterSystems e postagens da série de desempenho.](https://community.intersystems.com/post/capacity-planning-and-performance-series-index)

Leia também a Guia de Backup e Restauração da documentação online do IRIS para esta postagem.


Opções de backup

Solução de backup mínima - Backup Online do IRIS

Se você não tiver mais nada, ela vem incluída na plataforma de dados da InterSystems para backups de tempo de inatividade zero. Lembre-se: o backup online do IRIS só faz backup de arquivos dos bancos de dados do IRIS, capturando todos os blocos nos bancos de dados alocados para dados com a saída gravada em um arquivo sequencial. O Backup Online do IRIS é compatível com backups cumulativos e incrementais.

No contexto do VMware, o Backup Online do IRIS é uma solução de backup a nível de convidado. Como outras soluções de convidado, as operações do Backup Online do IRIS são praticamente as mesmas, quer o aplicativo seja virtualizado ou executado diretamente em um host. O Backup Online do IRIS precisa ser coordenado com um backup do sistema para copiar o arquivo de saída do backup online do IRIS para a mídia de backup e todos os outros sistemas de arquivos usados pelo seu aplicativo. No mínimo, o backup do sistema precisa incluir o diretório de instalação, o diário e os diretórios alternativos do diário, os arquivos do aplicativo e qualquer diretório com os arquivos externos usados pelo aplicativo.

O Backup Online do IRIS deve ser considerado como uma abordagem inicial para sites menores que querem implementar uma solução de baixo custo para fazer backup apenas de bancos de dados do IRIS ou backups ad hoc. Por exemplo, é útil na configuração do espelhamento. No entanto, como os bancos de dados crescem e o IRIS só costuma ser uma parte do cenário de dados do cliente, é uma prática recomendada combinar os Backups Externos com a tecnologia de cópia instantânea e utilitários de terceiros, o que possui vantagens como inclusão do backup de arquivos que não são dos bancos de dados, restaurações mais rápidas, visão de dados de toda a empresa e melhores ferramentas de gestão e catálogo.


Solução de backup recomendada - Backup Externo

Usando o VMware como exemplo, a virtualização no VMware adiciona funcionalidades e opções para proteger VMs inteiras. Depois de virtualizar uma solução, você encapsulará efetivamente seu sistema — incluindo o sistema operacional, o aplicativo e os dados —, tudo dentro de arquivos .vmdk (e alguns outros). Quando necessários, esses arquivos podem ser simples de gerenciar e usados para recuperar um sistema inteiro, o que difere muita da mesma situação em um sistema físico, onde você precisa recuperar e configurar os componentes separadamente – sistema operacional, drivers, aplicativos de terceiros, banco de dados, arquivos de bancos de dados etc.


# Cópia instantanea da VMware

A vSphere Data Protection (VDP) do VMware e outras soluções de backup de terceiros para o backup da VM, como Veeam ou Commvault, usam a funcionalidade de cópias instantâneas das máquinas virtuais do VMware para criar backups. Segue uma explicação de nível superior das cópias instantâneas do VMware. Veja a documentação do VMware para mais detalhes.

É importante lembrar que as cópias instantâneas são aplicados à VM inteira, e o sistema operacional e qualquer aplicativo ou mecanismo de banco de dados não sabem que a cópia está acontecendo. Além disso, lembre-se:

Sozinhas, as cópias instantâneas da VMware não são backups!

As cópias instantâneas permitem que o software de backup faça backups, mas eles não são backups por si sós.

O VDP e as soluções de backup de terceiros usam o processo de cópia do VMware em conjunto com o aplicativo de backup para gerenciar a criação e, mais importantemente, a exclusão da cópia instantânea. Em um nível superior, o processo e a sequência de eventos para um backup externo usando cópias instantâneas do VMware são os seguintes:

  • O software de backup de terceiros solicita que o host ESXi acione uma cópia instantânea do VMware.
  • Os arquivos .vmdk de uma VM são colocados em um estado somente leitura, e um arquivo delta .vmdk filho é criado para cada um dos arquivos .vmdk da VM.
  • A cópia na gravação é usada com todas as mudanças na VM gravadas nos arquivos delta. Quaisquer leituras são primeiro do arquivo delta.
  • O software de backup gerencia a cópia dos arquivos .vmdk pai somente leitura para o destino do backup.
  • Quando o backup é concluído, é feito o commit da cópia (os discos da VM retomam as gravações e atualizam os blocos nos arquivos delta gravados no pai).
  • A cópia instantânea do VMware é excluído agora.

As soluções de backup também usam outros recursos, como Changed Block Tracking (CBT), permitindo backups incrementais ou cumulativos para velocidade e eficiência (especialmente importante para a economia de espaço), e geralmente adicionam outras funções importantes, como deduplicação e compactação de dados, agendamento, montagem de VMs com endereços IP alterados para verificações de integridade etc., restaurações completas no nível da VM e do arquivo e gestão de catálogo.

As cópias instantâneas da VMware que não forem gerenciados adequadamente ou forem deixados em execução por um longo período podem usar armazenamento excessivo (quanto mais dados forem alterados, mais os arquivos delta continuarão a crescer) e deixar as VMs mais lentas.

Considere com cuidado antes de executar uma cópia instantânea manual em uma instância de produção. Por que você está fazendo isso? O que acontecerá se você reverter para quando a cópia instantânea foi criada? O que acontecerá com todas as transações do aplicativo entre a criação e a reversão?

Não tem problema se o seu software de backup criar e excluir uma cópia instantânea. A cópia instantânea deve existir apenas por um breve período. Uma parte fundamental da sua estratégia de backup será escolher um momento de baixo uso do sistema para minimizar qualquer impacto adicional nos usuários e no desempenho.

Considerações do banco de dados do IRIS para cópias instantâneas

Antes de obter a cópia instantânea, é preciso colocar o banco de dados no modo desativado. Assim, é realizado o commit de todas as gravações pendentes e o banco de dados fica em um estado consistente. O IRIS oferece métodos e uma API para fazer o commit e congelar (interromper) gravações no banco de dados por um breve período enquanto a cópia instantânea é criada. Assim, somente as gravações físicas nos arquivos do banco de dados são congeladas durante a criação da cópia instantânea, permitindo que os processos do usuário continuem realizando atualizações na memória sem interrupções. Depois que a cópia instantânea é acionada, as gravações no banco de dados são descongeladas e o backup continua copiando os dados para a mídia de backup. O tempo entre o congelamento e o descongelamento deve ser rápido (alguns segundos).

Além de pausar as gravações, o congelamento do IRIS também processa a troca de arquivos de diário e a gravação de um marcador de backup no diário. O arquivo de diário continua a ser gravado normalmente enquanto as gravações no banco de dados físico estão congeladas. Se o sistema falhar enquanto as gravações no banco de dados físico estiverem congeladas, os dados serão recuperados do diário normalmente durante a inicialização.

O diagrama a seguir mostra as etapas de congelamento e descongelamento com cópias instantâneas da VMware para criar um backup com uma imagem de banco de dados consistente.


Linha do tempo da cópia instantânea da VMware + congelamento/descongelamento do IRIS (não escalar)

image


Observe o breve período entre o congelamento e o descongelamento: apenas o suficiente para criar a cópia instantânea, e não copiar o pai somente leitura para o destino do backup​.


Resumo - Por que preciso congelar e descongelar o banco de dados do IRIS quando o VMware está criando uma cópia instantânea?

O processo de congelar e descongelar o banco de dados é fundamental para garantir a consistência e integridade dos dados. Isso ocorre porque:

Consistência dos dados: o IRIS pode escrever diários ou o WIJ ou fazer gravações aleatórias no banco de dados a qualquer momento. Uma cópia instantânea captura o estado da VM em um momento específico. Se o banco de dados estiver sendo ativamente gravado durante a cópia instantânea, isso poderá causar uma cópia com dados parciais ou inconsistentes. Congelar o banco de dados garante que todas as transações sejam concluídas e nenhuma transação nova seja iniciada durante a cópia, levando a um estado de disco consistente.

Desativação do sistema de arquivos: A tecnologia de cópia instantânea da VMware pode desativar o sistema de arquivos para garantir a consistência dele. No entanto, isso não abrange a consistência no nível do aplicativo ou do banco de dados. O congelamento do banco de dados garante que ele esteja em um estado consistente no nível do aplicativo, complementando o quiesce do VMware.

Redução do tempo de recuperação: a restauração de cópia instantânea obtida sem congelar o banco de dados pode exigir etapas adicionais, como o reparo do banco de dados ou verificações de consistência, o que pode aumentar significativamente o tempo de recuperação. O congelamento e descongelamento garantem que o banco de dados possa ser usado imediatamente após a restauração, diminuindo o tempo de inatividade.


Integração do congelamento e descongelamento do IRIS

O vSphere permite que um script seja chamado automaticamente em ambos os lados da criação da cópia instantânea. É quando são chamados o congelamento e descongelamento do IRIS. Observação: para essa funcionalidade funcionar corretamente, o host ESXi solicita que o sistema operacional convidado desative os discos pelas Ferramentas do VMware.

As ferramentas do VMware precisam ser instaladas no sistema operacional convidado.

Os scripts precisam obedecer regras rígidas de nome e localização. As permissões de arquivo também precisam ser definidas. Para o VMware no Linux, os nomes dos scripts são:

# /usr/sbin/pre-freeze-script
# /usr/sbin/post-thaw-script

Confira abaixo exemplos de scripts de congelamento e descongelamento que nossa equipe usa com o backup do Veeam para instâncias internas de laboratório de testes, mas eles também devem funcionar com outras soluções. Esses exemplos foram testados e usados no vSphere 6 e Red Hat 7.

Embora esses scripts possam ser usados como exemplos e ilustrem o método, você precisa validá-los para seus ambientes!

Exemplo de script pré-congelamento:

#!/bin/sh
#
# Script called by VMWare immediately prior to snapshot for backup.
# Tested on Red Hat 7.2
#

LOGDIR=/var/log
SNAPLOG=$LOGDIR/snapshot.log

echo >> $SNAPLOG
echo "`date`: Pre freeze script started" >> $SNAPLOG
exit_code=0

# Only for running instances
for INST in `iris qall 2>/dev/null | tail -n +3 | grep '^up' | cut -c5-  | awk '{print $1}'`; do

    echo "`date`: Attempting to freeze $INST" >> $SNAPLOG
    
    # Detailed instances specific log    
    LOGFILE=$LOGDIR/$INST-pre_post.log
    
    # Freeze
    irissession $INST -U '%SYS' "##Class(Backup.General).ExternalFreeze(\"$LOGFILE\",,,,,,1800)" >> $SNAPLOG $
    status=$?

    case $status in
        5) echo "`date`:   $INST IS FROZEN" >> $SNAPLOG
           ;;
        3) echo "`date`:   $INST FREEZE FAILED" >> $SNAPLOG
           logger -p user.err "freeze of $INST failed"
           exit_code=1
           ;;
        *) echo "`date`:   ERROR: Unknown status code: $status" >> $SNAPLOG
           logger -p user.err "ERROR when freezing $INST"
           exit_code=1
           ;;
    esac
    echo "`date`:   Completed freeze of $INST" >> $SNAPLOG
done

echo "`date`: Pre freeze script finished" >> $SNAPLOG
exit $exit_code

Exemplo de script de descongelamento:

#!/bin/sh
#
# Script called by VMWare immediately after backup snapshot has been created
# Tested on Red Hat 7.2
#

LOGDIR=/var/log
SNAPLOG=$LOGDIR/snapshot.log

echo >> $SNAPLOG
echo "`date`: Post thaw script started" >> $SNAPLOG
exit_code=0

if [ -d "$LOGDIR" ]; then

    # Only for running instances    
    for INST in `iris qall 2>/dev/null | tail -n +3 | grep '^up' | cut -c5-  | awk '{print $1}'`; do
    
        echo "`date`: Attempting to thaw $INST" >> $SNAPLOG
        
        # Detailed instances specific log
        LOGFILE=$LOGDIR/$INST-pre_post.log
        
        # Thaw
        irissession $INST -U%SYS "##Class(Backup.General).ExternalThaw(\"$LOGFILE\")" >> $SNAPLOG 2>&1
        status=$?
        
        case $status in
            5) echo "`date`:   $INST IS THAWED" >> $SNAPLOG
               irissession $INST -U%SYS "##Class(Backup.General).ExternalSetHistory(\"$LOGFILE\")" >> $SNAPLOG$
               ;;
            3) echo "`date`:   $INST THAW FAILED" >> $SNAPLOG
               logger -p user.err "thaw of $INST failed"
               exit_code=1
               ;;
            *) echo "`date`:   ERROR: Unknown status code: $status" >> $SNAPLOG
               logger -p user.err "ERROR when thawing $INST"
               exit_code=1
               ;;
        esac
        echo "`date`:   Completed thaw of $INST" >> $SNAPLOG
    done
fi

echo "`date`: Post thaw script finished" >> $SNAPLOG
exit $exit_code

Lembre-se de definir as permissões:

# sudo chown root.root /usr/sbin/pre-freeze-script /usr/sbin/post-thaw-script
# sudo chmod 0700 /usr/sbin/pre-freeze-script /usr/sbin/post-thaw-script

Teste de congelamento e descongelamento

Para testar se os scripts estão funcionando corretamente, você pode executar uma cópia instantânea manualmente em uma VM e verificar a saída do script. A captura de tela a seguir mostra a caixa de diálogo "Take VM Snapshot" (Tirar a cópia instantânea da VM) e as opções.

Desmarque- "Snapshot the virtual machine's memory" (Tirar a cópia instantânea da memória da máquina virtual).

Selecione - a caixa de seleção "Quiesce guest file system (Needs VMware Tools installed)", ou "Colocar o sistema de arquivos convidado em modo quiesced (as ferramentas do VMware precisam estar instaladas)", para pausar os processos em execução no sistema operacional convidado, deixando o conteúdo do sistema de arquivos em um estado consistente conhecido ao tirar a cópia instantânea.

Importante! Depois do teste, lembre-se de excluir a cópia instantânea!!!!

Se a sinalização quiesce for verdadeira e a máquina virtual estiver ligada ao tirar a cópia instantânea, as ferramentas do VMware serão usadas para o quiesce do sistema de arquivos na máquina virtual. O quiesce do sistema de arquivos é o processo de colocar os dados no disco em um estado adequado para backups. Esse processo pode incluir operações como a limpeza de buffers sujos no cache da memória do sistema operacional para o disco.

A saída a seguir mostra o conteúdo do arquivo de log $SNAPSHOT definido nos scripts de congelamento/descongelamento acima após executar um backup que inclui uma cópia instantânea como parte da sua operação.

Wed Jan  4 16:30:35 EST 2017: Pre freeze script started
Wed Jan  4 16:30:35 EST 2017: Attempting to freeze H20152
Wed Jan  4 16:30:36 EST 2017:   H20152 IS FROZEN
Wed Jan  4 16:30:36 EST 2017:   Completed freeze of H20152
Wed Jan  4 16:30:36 EST 2017: Pre freeze script finished

Wed Jan  4 16:30:41 EST 2017: Post thaw script started
Wed Jan  4 16:30:41 EST 2017: Attempting to thaw H20152
Wed Jan  4 16:30:42 EST 2017:   H20152 IS THAWED
Wed Jan  4 16:30:42 EST 2017:   Completed thaw of H20152
Wed Jan  4 16:30:42 EST 2017: Post thaw script finished

Esse exemplo mostra os 6 segundos decorridos entre o congelamento e o descongelamento (16:30:36-16:30:42). As operações dos usuários NÃO são interrompidas durante esse período. Você precisará coletar métricas dos seus próprios sistemas, mas, para um pouco de contexto, esse exemplo é de um sistema que está executando um benchmark de aplicativo em uma VM sem gargalos de IO e com uma média de mais de 2 milhões de glorefs/s, 170.000 de gloupds/s, 1.100 gravações físicas/s e 3.000 gravações por ciclo de daemon de gravação.

Lembre-se de que a memória não faz parte da cópia instantânea, portanto, ao reiniciar, a VM será reinicializada e recuperada. Os arquivos de banco de dados serão consistentes. Você não quer "retomar" um backup, e sim quer os arquivos em um momento conhecido. Então, você pode fazer o roll forward dos diários e quaisquer outras etapas de recuperação necessárias para o aplicativo e a consistência transacional assim que os arquivos forem recuperados.

Para proteção de dados adicional, a troca do diário pode ser feita por si só, e os diários podem ser armazenados em backup ou replicados em outro local, por exemplo, a cada hora.

Confira abaixo a saída de $LOGFILE nos scripts de congelamento/descongelamento acima, mostrando os detalhes do diário para a cópia instantânea.

01/04/2017 16:30:35: Backup.General.ExternalFreeze: Suspending system

Journal file switched to:
/trak/jnl/jrnpri/h20152/H20152_20170104.011
01/04/2017 16:30:35: Backup.General.ExternalFreeze: Start a journal restore for this backup with journal file: /trak/jnl/jrnpri/h20152/H20152_20170104.011

Journal marker set at
offset 197192 of /trak/jnl/jrnpri/h20152/H20152_20170104.011
01/04/2017 16:30:36: Backup.General.ExternalFreeze: System suspended
01/04/2017 16:30:41: Backup.General.ExternalThaw: Resuming system
01/04/2017 16:30:42: Backup.General.ExternalThaw: System resumed

Tempos de stun da VM

No ponto de criação de uma cópia instantânea da VM e após a conclusão do backup e o commit do snapshot, a VM precisa ser congelada por um breve período. Esse pequeno congelamento costuma ser chamado de "stun" da VM. Veja uma ótima postagem de blog sobre os tempos de stun aqui. Resumo os detalhes abaixo e os contextualizo para as considerações do banco de dados do IRIS.

Da postagem sobre os tempos de stun: "Para criar uma cópia instantânea da VM, é feito o 'stun' da VM para (i) serializar o estado do dispositivo no disco e (ii) encerrar o disco que está em execução e criar um ponto da cópia instantânea… Durante a consolidação, é feito o 'stun' da VM para encerrar os discos e colocá-los em um estado apropriado para a consolidação."

O tempo de stun é normalmente algumas centenas de milésimos. No entanto, se houver uma atividade muito alta de gravação em disco durante a fase de commit, o tempo de stun poderá ser de vários segundos.

Se a VM estiver participando do Espelhamento do Banco de Dados do IRIS como um membro Primário ou de Backup, e o tempo de stun for maior que o tempo limite de Qualidade de Serviço (QoS) do espelho, o espelho relatará a falha da VM Primária e assumirá o controle.

Atualização de março de 2018: Meu colega, Peter Greskoff, indicou que um membro espelho de backup poderia iniciar a tolerância a falhas na metade do tempo limite de QoS durante um stun da VM ou quando um membro espelho primário estiver indisponível.

Para conferir uma descrição detalhada das considerações de QoS e cenários de tolerância a falhas, consulte esta ótima postagem: Guia do Tempo Limite de Qualidade de Serviço para Espelhamento. Resumindo a questão dos tempos de stun da VM e QoS:

Se o espelho de backup não receber nenhuma mensagem do espelho primário dentro da metade do tempo limite de QoS, ele enviará uma mensagem para garantir que o primário ainda está ativo. Em seguida, o backup aguardará uma resposta da máquina primária pela outra metade do tempo de QoS. Se não houver resposta do primário, presume-se que ele está inativo, e o backup assumirá o controle.

Em um sistema ocupado, os diários são enviados continuamente do espelho primário para o espelho de backup, e o backup não precisa verificar se o primário ainda está ativo. No entanto, durante um período tranquilo — quando é mais provável que os backups ocorram —, se o aplicativo estiver ocioso, pode não haver mensagens entre o espelho primário e o de backup por mais da metade do tempo de QoS.

Confira abaixo o exemplo de Peter. Pense neste intervalo para um sistema ocioso com um tempo limite de QoS de 8 segundos e um tempo de stun da VM de 7 segundos:

  • :00 O primário dá um ping no árbitro com um keepalive, e o árbitro responde imediatamente
  • :01 O membro de backup envia o keepalive ao primário, e o primário responde imediatamente
  • :02
  • :03 Começa o stun da VM
  • :04 O primário tenta enviar o keepalive ao árbitro, mas não consegue até a conclusão do stun
  • :05 O membro de backup envia um ping ao primário, já que expirou metade da QoS
  • :06
  • :07
  • :08 O árbitro não recebe resposta do primário durante todo o tempo limite de QoS, então encerra a conexão
  • :09 O backup não recebeu uma resposta do primário e confirma com o árbitro que ele também perdeu a conexão, então assume o controle
  • :10 O stun da VM acaba, tarde mais!!

Leia também a seção Pitfalls and Concerns when Configuring your Quality of Service Timeout (Armadilhas e Preocupações ao Configurar o Tempo Limite de Qualidade de Serviço) na postagem do link acima para entender o equilíbrio de ter a QoS somente pelo tempo necessário. Ter a QoS por muito tempo, especialmente por mais de 30 segundos, também pode causar problemas.

Final da atualização de março de 2018:

Para obter mais informações sobre a QoS do Espelhamento, consulte também a documentação.

As estratégias para reduzir ao mínimo o tempo de stun incluem executar backups quando houver pouca atividade no banco de dados e configurar bem o armazenamento.

Como observado acima, ao criar uma cópia instantânea, há várias opções que você pode especificar. Uma delas é incluir o estado da memória na cópia - Lembre-se, o estado da memória NÃO é necessário para backups de bancos de dados do IRIS. Se estiver configurada a sinalização da memória, um dump do estado interno da máquina virtual será incluído na cópia. A criação de cópias instantâneas da memória demora muito mais. As cópias da memória são usados para reverter o estado de uma máquina virtual em execução para como estava quando a cópia foi obtida. Isso NÃO é necessário para o backup de arquivos de um banco de dados.

Ao tirar uma cópia instantânea da memória, será realizado o stun de todo o estado da máquina virtual. O tempo de stun varia.

Como observado anteriormente, para backups, a sinalização do quiesce precisa ser definida como verdadeira para cópias manuais ou pelo software de backup para garantir um backup consistente e utilizável.

Revisar tempos de stun em logs do VMware

A partir do ESXi 5.0, os tempos de stun das cópias são registrados no arquivo de log de cada máquina virtual (vmware.log) com mensagens semelhantes a:

2017-01-04T22:15:58.846Z| vcpu-0| I125: Checkpoint_Unstun: vm stopped for 38123 us

Os tempos de stun estão em microssegundos. Então, no exemplo acima, 38123 us é 38123/1.000.000 segundos ou 0,038 segundos.

Para garantir que os tempos de stun estão dentro dos limites aceitáveis ou para solucionar problemas se você suspeitar que eles estão longos e causando problemas, baixe e revise os arquivos vmware.log da pasta da VM em que tem interesse. Depois de baixar, você pode extrair e ordenar o log usando os comandos Linux de exemplo abaixo.

Exemplo de download dos arquivos vmware.log

Há várias formas de baixar os logs de suporte, incluindo criando um pacote de suporte do VMware através do console de gerenciamento do vSphere ou da linha de comando do host ESXi. Consulte a documentação do VMware para ver todos os detalhes, mas abaixo está um método simples para criar e reunir um pacote de suporte bem menor que inclui o arquivo vmware.log para você revisar os tempos de stun.

Você precisará do nome longo do diretório onde os arquivos da VM estão localizados. Faça login no host ESXi onde a VM do banco de dados está em execução usando ssh e use o comando: vim-cmd vmsvc/getallvms  para listar os arquivos vmx e os nomes longos exclusivos associados a eles.

Por exemplo, o nome longo da VM do banco de dados de exemplo usada nesta postagem fica assim: 26 vsan-tc2016-db1 [vsanDatastore] e2fe4e58-dbd1-5e79-e3e2-246e9613a6f0/vsan-tc2016-db1.vmx rhel7_64Guest vmx-11

Em seguida, execute o comando para reunir e empacotar apenas os arquivos de log:
vm-support -a VirtualMachines:logs.

O comando dará a localização do pacote de suporte, por exemplo: To see the files collected, check '/vmfs/volumes/datastore1 (3)/esx-esxvsan4.iscinternal.com-2016-12-30--07.19-9235879.tgz'.

Agora você pode usar o sftp para transferir o arquivo para fora do host para processamento e análise adicional.

Nesse exemplo, após descompactar o pacote de suporte, acesse o caminho correspondente ao nome longo da VM do banco de dados. Por exemplo, nesse caso: <bundle name>/vmfs/volumes/<host long name>/e2fe4e58-dbd1-5e79-e3e2-246e9613a6f0.

Você verá vários arquivos de log numerados. O arquivo de log mais recente não tem número, ou seja, vmware.log. O log pode ter só algumas centenas de KB, mas há muitas informações. Porém, queremos os tempos de stun/unstun, que são fáceis de encontrar com grep. Por exemplo:

$ grep Unstun vmware.log
2017-01-04T21:30:19.662Z| vcpu-0| I125: Checkpoint_Unstun: vm stopped for 1091706 us
--- 
2017-01-04T22:15:58.846Z| vcpu-0| I125: Checkpoint_Unstun: vm stopped for 38123 us
2017-01-04T22:15:59.573Z| vcpu-0| I125: Checkpoint_Unstun: vm stopped for 298346 us
2017-01-04T22:16:03.672Z| vcpu-0| I125: Checkpoint_Unstun: vm stopped for 301099 us
2017-01-04T22:16:06.471Z| vcpu-0| I125: Checkpoint_Unstun: vm stopped for 341616 us
2017-01-04T22:16:24.813Z| vcpu-0| I125: Checkpoint_Unstun: vm stopped for 264392 us
2017-01-04T22:16:30.921Z| vcpu-0| I125: Checkpoint_Unstun: vm stopped for 221633 us

Podemos ver dois grupos de tempos de stun no exemplo, um desde a criação da cópia instantânea e outro definido 45 minutos depois para cada disco quando a cópia foi excluído/consolidado (por exemplo, depois que o software de backup fez a cópia do arquivo vmx somente leitura). O exemplo acima mostra que a maioria dos tempos de stun é menor do que um segundo, mesmo que o tempo de stun inicial seja um pouco mais de um segundo.

Tempos de stun curtos não são perceptíveis para o usuário final. No entanto, os processos do sistema, como o Espelhamento do Banco de Dados do IRIS, verificam continuamente se uma instância está "ativa". Se o tempo de stun exceder o tempo limite de QoS do espelhamento, o nó poderá ser considerado fora de contato e "morto", e a tolerância a falhas será acionada.

Dica: para revisar todos os logs ou solucionar problemas, um comando útil é fazer o grep de todos os arquivos vmware*.log e procurar qualquer discrepância ou instância em que o tempo de stun chega próximo ao tempo limite de QoS. O seguinte comando canaliza a saída para awk para formatação:

grep Unstun vmware* | awk '{ printf ("%'"'"'d", $8)} {print " ---" $0}' | sort -nr


Resumo

Monitore seu sistema regularmente durante as operações normais para entender os tempos de stun e como eles podem afetar o tempo limite de QoS para HA, como o espelhamento. Como observado, as estratégias para reduzir ao mínimo o tempo de stun/unstun incluem executar backups quando houver pouca atividade no banco de dados e no armazenamento e configurar bem o armazenamento. Para monitoramento constante, os logs podem ser processados usando o VMware Log Insight ou outras ferramentas.

Em postagens futuras, revisitarei as operações de backup e restauração para as Plataformas de Dados da InterSystems. Por enquanto, caso você tenha algum comentário ou sugestão com base nos fluxos de trabalho dos seus sistemas, compartilhe nas seções de comentários abaixo.

0
0 89
Artigo Danusa Calixto · Fev. 9, 2024 13m read

Talvez você não perceba isso, mas sua conta de login da InterSystems pode ser usada para acessar uma ampla variedade de serviços da InterSystems que ajudam você a aprender e usar o InterSystems IRIS e outras tecnologias da InterSystems de maneira mais eficaz.  Continue lendo para saber mais sobre como descobrir novos conhecimentos técnicos e ferramentas usando sua conta de login da InterSystems.  Além disso, após a leitura, participe da Enquete na parte inferior, para que possamos ver como este artigo foi útil para você!

O que é uma conta de login da InterSystems? 

Uma conta de login da InterSystems é usada para acessar diversos serviços online que atendem a parceiros e clientes atuais e em potencial.  É um conjunto único de credenciais usadas em mais de 15 aplicativos voltados ao público externo.  Alguns aplicativos (como a WRC ou o iService) exigem uma ativação específica para o acesso ser concedido pela conta.  Provavelmente, há recursos disponíveis que ajudarão você, mas você não os conhece: leia sobre todas as opções e teste uma nova ferramenta para melhorar sua técnica!!

Catálogo de aplicativos

Você pode ver todos os serviços disponíveis para você com sua conta de login da InterSystems ao acessar esse catálogo de aplicativos da InterSystems, localizado em:  https://Login.InterSystems.com.  Isso só listará os aplicativos ou serviços a que você tem acesso no momento.  Ele lembra seus aplicativos usados com mais frequência e os lista na parte superior para sua conveniência. 

Não se esqueça de marcar a página como favorita para acessar facilmente todas essas ferramentas na caixa de ferramentas da sua conta de login da InterSystems!

Detalhes dos aplicativos 

Agora, é hora de entrar nos detalhes de cada aplicativo e ver como eles podem ajudar você como desenvolvedor que trabalha com as tecnologias da InterSystems!  Continue lendo e tente encontrar um novo aplicativo que você possa usar pela primeira vez para melhorar sua eficiência e habilidades como desenvolvedor....

 Getting Started - gettingstarted.intersystems.com 

Público

  • Qualquer pessoa que deseja explorar usando a plataforma de dados da InterSystems IRIS®

Descrição

  • Aprenda a criar aplicativos de missão crítica e uso intensivo de dados rapidamente com o InterSystems IRIS.
  • Siga vídeos e tutoriais que usam SQL, Java, C#/.Net, Node.js, Python ou InterSystems ObjectScript.
  • Use um Sandbox gratuito, baseado na nuvem e dentro do navegador -- IRIS+IDE+Web Terminal— para seguir tutoriais. 

Como isso ajuda a melhorar sua técnica

  • Familiarize-se rapidamente com a tecnologia da InterSystems e a veja em ação com código e exemplos reais!
  • Explore o uso de outras linguagens de programação populares com o InterSystems IRIS.

 Online Learning - learning.intersystems.com

Público

  • Todos os usuários atuais e em potencial dos produtos da InterSystems 

Descrição

  • Materiais autoguiados para ajudar você a desenvolver e dar suporte aos aplicativos mais importantes do mundo:
    • Exercícios práticos
    • Vídeos
    • Cursos online
    • Programas de aprendizado

Como isso ajuda a melhorar sua técnica

  • Aprenda, aprenda, aprenda!! 
  • Nada ajudará você a se tornar um desenvolvedor eficiente mais rápido do que seguir um instrutor técnico habilidoso ensinando novos conceitos para usar nos seus projetos do InterSystems IRIS! 

 Documentação - docs.intersystems.com 

Público

  • Todos os usuários atuais e em potencial dos produtos da InterSystems

Descrição

  • Documentação para todas as versões dos nossos produtos
  • Links, quando necessário, para documentação externa
  • Todo o conteúdo recente é fornecido pelo nosso mecanismo de pesquisa.
  • A página de pesquisa deixa você filtrar por produto, versão e outros aspectos.
  • Algumas documentações exigem autorização (pela conta de login da InterSystems):
    • Documentação da AtScale disponível para clientes da Análise Adaptativa
    • Documentação da HealthShare disponível para usuários da HealthShare
  • Use a nova Lista de Verificação de Impacto de Atualização dinâmica no servidor de documentação!

Como isso ajuda a melhorar sua técnica

  • Use rapidamente materiais de referência de classes e documentação de APIs.
  • Encontre amostras de código. 
  • Leia documentação detalhada sobre o uso de partes do InterSystems IRIS em que você precisa se aprofundar.
  • Solicite mais detalhes ou denuncie problemas diretamente nas páginas de documentação através do recurso "Feedback".

 Evaluation - evaluation.intersystems.com

Público

  • Quem deseja baixar software ou licenças da InterSystems para uso em avaliação ou desenvolvimento

Descrição

  • Downloads do InterSystems IRIS e InterSystems IRIS for Health.
  • Qualquer pessoa pode baixar os kits do Community Edition.
  • Os clientes atuais também podem solicitar uma licença avançada para avaliar os recursos corporativos.
  • As versões de prévia estão disponíveis em pré-lançamento.
  • Os pacotes do Programa de Acesso Antecipado permitem que as pessoas enviem feedback sobre produtos e recursos futuros.

Como isso ajuda a melhorar sua técnica

  • Teste versões de prévia de software para ver como os novos recursos podem ajudar a acelerar seu desenvolvimento.
  • Teste recursos corporativos ao solicitar uma licença de avaliação.
  • Confira se todos os desenvolvedores na sua organização têm a versão mais recente do InterSystems IRIS instalada nas máquinas.
  • Forneça feedback para a Gestão de Produtos da InterSystems sobre os Recursos do Acesso Antecipado para garantir que eles atendam às necessidades da sua equipe após o lançamento completo.

 Developer Community - community.intersystems.com

Público

  • Qualquer pessoa que trabalha com a tecnologia do InterSystems (clientes atuais e em potencial, funcionários e parceiros da InterSystems)

Descrição

  • Monitore comunicados relacionados aos produtos e serviços da InterSystems.
  • Encontre artigos sobre uma variedade de tópicos técnicos.
  • Faça perguntas e receba respostas da comunidade.
  • Explore vagas de trabalho ou desenvolvedores disponíveis para contratação.
  • Participe de competições com prêmios em dinheiro de US$ 1000.
  • Fique por dentro de tudo relacionado a InterSystems!

Como isso ajuda a melhorar sua técnica

  • Com o acesso aos principais especialistas do mundo em tecnologia da InterSystems, você pode aprender com os melhores e continuar interagindo com perguntas, tendências e tópicos em alta.
  • Receba atualizações automaticamente na sua caixa de entrada sobre novos produtos, lançamentos e oportunidades do Programa de Acesso Antecipado.
  • Obtenha ajuda de colegas para tirar suas dúvidas e superar obstáculos.
  • Tenha discussões enriquecedoras com Gerentes e Desenvolvedores de Produtos da InterSystems: aprenda direto da fonte!
  • Eleve suas habilidades a um novo patamar ao compartilhar soluções técnicas e código, além de receber feedback de outros.

 Ideias da InterSystems - ideas.intersystems.com

Público

  • Quem deseja compartilhar ideias para melhorar a tecnologia da InterSystems.

Descrição

  • Publique ideais sobre como melhorar a tecnologia da InterSystems.
  • Leia avaliações existentes e vote ou participe em discussões.
  • A InterSystems levará em conta as ideias mais populares para o desenvolvimento de produtos futuros.

Como isso ajuda a melhorar sua técnica

  • Veja suas ideias e necessidades virarem realidade em produtos da InterSystems ou bibliotecas de código aberto.
  • Familiarize-com ideias de colegas e aprenda a usar os produtos da InterSystems de novas maneiras.
  • Implemente ideias sugeridas por outros, explorando novas partes da tecnologia da InterSystems.

 Global Masters - globalmasters.intersystems.com

Público

  • Quem quer apoiar a tecnologia da InterSystems e ganhar emblemas e brindes

Descrição

  • A plataforma de gamificação criada para que os desenvolvedores aprendam, fiquem por dentro e ganhem reconhecimento pelas contribuições através de conteúdo interativo.
  • Os usuários recebem pontos e emblemas pelo seguinte:
    • Engajamento no Developer Community
    • Engajamento no Open Exchange
    • Publicação de posts nas redes sociais sobre produtos e tecnologias InterSystems
  • Troque pontos por brindes ou treinamento gratuito da InterSystems

Como isso ajuda a melhorar sua técnica

  • Os desafios chamam sua atenção para artigos ou vídeos que talvez não tenha visto no Developer Community, site Learning ou canal do YouTube, sempre aprendendo coisas novas para aplicar aos seus projetos!

 Open Exchange - openexchange.intersystems.com 

Público

  • Desenvolvedores que buscam publicar ou usar ferramentas e pacotes de software reutilizáveis

Descrição

  • Ferramentas e pacotes de desenvolvedores criados com as plataformas de dados e os produtos da InterSystems. 
  • Os pacotes são publicados sob uma variedade de licenças de software (em grande parte, de código aberto).
  • Integração com o GitHub para versionamento de pacotes, discussões e rastreamento de bugs
  • Leia e envie avaliações e encontre os pacotes mais populares.
  • Os desenvolvedores podem enviar issues e fazer melhorias nos pacotes por solicitações pull do GitHub para ajudar a avançar o software da comunidade.
  • Os desenvolvedores podem ver estatísticas de tráfego e downloads de pacotes que publicaram

Como isso ajuda a melhorar sua técnica

  • Não reinvente a roda!  Use pacotes de código aberto criados e mantidos pela InterSystems Community para resolver problemas genéricos, deixando que você foque no desenvolvimento de soluções específicas de que sua empresa precisa.
  • A contribuição com os pacotes de código aberto é uma ótima maneira de receber feedback construtivo no seu trabalho e aprimorar seus padrões de desenvolvimento.
  • Ser um contribuidor respeitado em projetos de código aberto é uma forma excelente de aumentar a demanda pelas suas habilidades e insights. 

 WRC - wrc.intersystems.com

Público

  • Sistema de monitoramento para todos os problemas relatados por clientes no InterSystems IRIS e InterSystems HealthShare.  Os clientes com SUTA podem trabalhar diretamente com o aplicativo.

Descrição

  • Aplicativo Central de Suporte (ou "WRC Direct").
  • sistema de monitoramento para todos os problemas relatados por clientes. 
  • Abra novas solicitações. 
  • Veja todas as ações investigativas e adicione informações e comentários sobre uma solicitação. 
  • Veja informações estatísticas sobre seu histórico de chamadas de suporte. 
  • Encerre solicitações e ofereça feedback sobre o processo de suporte. 
  • Revise arquivos de patches ad-hoc. 
  • Monitore pedidos de alterações de software.
  • Baixe versões de software de produto e cliente atuais.

Como isso ajuda a melhorar sua técnica

  • Os Engenheiros de Suporte da InterSystems podem ajudar você a enfrentar obstáculos técnicos em relação ao desenvolvimento ou gerenciamento de sistemas com os produtos da InterSystems.
  • Relate bugs para garantir que os problemas sejam corrigidos em versões futuras.  

 iService - iservice.intersystems.com

Público

  • Clientes que precisam de suporte sob um contrato SLA

Descrição

  • Uma plataforma de tíquetes de suporte para nossos clientes da saúde, na nuvem e hospedados.
  • Permite cálculos e relatórios de compliance com o acordo de nível de serviço (SLA) orientado por regras.
  • Oferece recursos avançados de exportação e pesquisa de aspectos. 
  • Incorpora um sistema de gestão de Segurança Clínica completo.

Como isso ajuda a melhorar sua técnica

  • Os Engenheiros de Suporte da InterSystems podem ajudar você a enfrentar obstáculos técnicos em relação ao desenvolvimento ou gerenciamento de sistemas com os produtos da InterSystems da saúde ou na nuvem.
  • Relate bugs para garantir que os problemas sejam corrigidos em versões futuras.  

 ICR - containers.intersystems.com

Público

  • Qualquer pessoa que queira usar contêineres da InterSystems

Descrição

  • InterSystems Container Registry
  • Um registro de contêineres acessível programaticamente e IU da Web para navegação.
  • Contêineres do Community Edition disponíveis para todos.
  • Versões comerciais do InterSystems IRIS e InterSystems IRIS for Health disponíveis para clientes atendidos.
  • Gere tokens para usar nos pipelines CICD para buscar contêineres automaticamente.

Como isso ajuda a melhorar sua técnica

  • Aumente a maturidade do seu SDLC ao migrar para pipelines CICD baseados em contêineres para desenvolvimento, testes e implantação!

 Diretório de Parceiros - partner.intersystems.com 

Público

  • Quem quer encontrar um parceiro ou o produto de um parceiro da InterSystems 
  • Parceiros que buscam anunciar software e serviços  

Descrição

  • Pesquise todos os tipos de parceiros da InterSystems:
    • Parceiros de implementação
    • Parceiros de soluções
    • Parceiros de tecnologia
    • Parceiros da nuvem
  • Os parceiros existentes podem gerenciar seus anúncios de serviços e software. 

Como isso ajuda a melhorar sua técnica

  • Contrate especialistas certificados para aprender com eles nos seus projetos.
  • Licencie soluções corporativas baseadas na tecnologia da InterSystems para não precisar desenvolver tudo do zero.
  • Leve seus produtos e serviços para um público mais amplo, melhorando a procura e exigindo uma maior capacidade de entrega!

 CCR - ccr.intersystems.com 

Público

  • Organizações selecionadas que gerenciam as alterações feitas em uma implementação da InterSystems (funcionários, parceiros e usuários finais)

Descrição

  • Change Control Record
    • Aplicativo de fluxo de trabalho personalizado integrado na sua própria tecnologia para monitorar todas as personalizações dos produtos de saúde da InterSystems instalados no mundo todo.
  • Versionamento e implantação de código personalizado no local e alterações na configuração.
  • Vários níveis e opções de configuração de fluxo de trabalho.
  • Bastante adaptável para atender às necessidades específicas da fase do projeto

Como isso ajuda a melhorar sua técnica

  • Para equipes com o uso autorizado, encontre e reutilize código ou planos de implementação na sua organização, evitando precisar resolver o mesmo problema várias vezes.
  • Resolva problemas na produção com muito mais rapidez, deixando mais tempo para o trabalho de desenvolvimento. 

 Client Connection - client.intersystems.com  

Público

  • Disponível para qualquer cliente do TrakCare

Descrição

  • InterSystems Client Connection é uma plataforma de colaboração e compartilhamento de conhecimento para clientes do TrakCare.
  • Comunidade online para clientes do TrakCare desenvolvem conexões melhores e mais próximas.
  • Em Client Connection, você encontrará o seguinte: 
    • Notícias e eventos do TrakCare 
    • Materiais de lançamentos do TrakCare, por exemplo, documentação de versões e vídeos de prévia
    • Acesso a guias de produtos atualizados.
    • Materiais de suporte para desenvolver o conhecimento pessoal.
    • Fóruns de discussão para aproveitar o conhecimento de colegas. 

Como isso ajuda a melhorar sua técnica

  • Os especialistas técnicos e de aplicativos nos sites do TrakCare podem compartilhar perguntas e conhecimentos rapidamente, se conectando com outros usuários do mundo todo.  Com respostas mais rápidas, sobra mais tempo para desenvolver soluções!

 Pedidos online - store.intersystems.com

Público

  • Usuários de operações em parceiros/usuários finais de aplicativos selecionados

Descrição

  • Permita que os clientes escolham diferentes produtos de acordo com seus contratos e façam novos pedidos.  
  • Permita que os clientes atualizem/troquem pedidos existentes.
  • Envie pedidos às Operações de Clientes da InterSystems para processá-los para entrega e faturamento.
  • Permita que os clientes migrem as licenças existentes para o InterSystems IRIS.

Como isso ajuda a melhorar sua técnica

  • Honestamente, não ajuda!  É uma ferramenta usada pela equipe de operações, e não usuários técnicos, mas está incluída aqui para ficar completo, já que o acesso é controlado por uma conta de login da InterSystems ;)  

Outras coisas que você deve saber sobre sua conta de login da InterSystems

Aqui estão mais alguns fatos úteis sobre as contas de login da InterSystems...

Como criar uma conta de login

Os usuários podem criar sua própria conta ao clicar em "Create Account" em qualquer aplicativo da InterSystems voltado ao público, incluindo:

Como alternativa, o FRC (First Response Center) da InterSystems criará uma conta de login para clientes atendidos pela primeira vez que precisarem acessar a Central de Suporte (WRC) ou o iService (os clientes atendidos também podem criar contas para os colegas).

Antes de usar a conta, o usuário precisa aceitar os Termos e Condições, durante o processo de autoinscrição ou no primeiro login.

Opções alternativas de login

Alguns aplicativos permitem o login com o Google ou GitHub:

É a mesma conta de login da InterSystems, mas com a autenticação pelo Google ou GitHub.

Perfil da conta

Se você for até https://Login.InterSystems.com e fizer a autenticação, poderá acessar Opções > Profile e fazer alterações básicas na sua conta.  O e-mail pode ser alterado em Options > Change Email.  

Como resolver problemas da conta de login

Os problemas das contas de login da InterSystems devem ser encaminhados para Support@InterSystems.com.  Inclua o seguinte:

  • Nome de usuário utilizado na tentativa de login
  • E-mail
  • Tipo e versão do navegador
  • Mensagens e/ou capturas de tela do erro específico
  • Data e hora do erro recebido   
0
0 146
Artigo Danusa Calixto · Fev. 23, 2023 3m read

Nesta série de artigos, quero apresentar e discutir várias abordagens possíveis para o desenvolvimento de software com tecnologias da InterSystems e do GitLab. Vou cobrir tópicos como:

  • Primeiro artigo
    • Conceitos básicos do Git, por que um entendimento de alto nível dos conceitos do Git é importante para o desenvolvimento de software moderno
    • Como o Git pode ser usado para desenvolver software (fluxos do Git)
  • Segundo artigo
    • Fluxo de trabalho do GitLab — um processo completo do ciclo de vida do software, desde a ideia até o feedback do usuário
    • Entrega Contínua — uma abordagem de engenharia de software em que as equipes produzem software em ciclos curtos, garantindo que o software possa ser lançado de forma confiável a qualquer momento. Seu objetivo é construir, testar e lançar software com mais rapidez e frequência
  • Terceiro artigo
    • Instalação e configuração do GitLab
    • Conexão dos seus ambientes ao GitLab
  • Quarto artigo
    • Configuração da entrega contínua
  • Quinto artigo
    • Contêineres e como (e por que) podem ser usados
  • Sexto artigo
    • Principais componentes para um pipeline de entrega contínua com contêineres
    • Como todos eles trabalham juntos
  • Sétimo artigo
    • Configuração da entrega contínua com contêineres
  • Oitavo artigo
    • Configuração da entrega contínua com o InterSystems Cloud Manager
  • Nono artigo
    • Arquitetura do contêiner
  • Décimo artigo
    • CI/CD para configuração e dados
  • Décimo primeiro artigo
    • Interoperabilidade e CI/CD

Nessa série de artigos, discuti abordagens gerais de entrega contínua. É um tema extremamente vasto e essa série de artigos precisa ser vista mais como uma coleção de receitas do que algo definitivo. Se você deseja automatizar o desenvolvimento, os testes e a entrega do seu aplicativo, a entrega contínua em geral e o GitLab em particular é o melhor caminho. A entrega contínua e os contêineres permitem que você personalize seu fluxo de trabalho conforme necessário.

0
0 175
Artigo Danusa Calixto · Dez. 22, 2022 10m read

Nesta série de artigos, quero apresentar e discutir várias abordagens possíveis para o desenvolvimento de software com tecnologias da InterSystems e do GitLab. Vou cobrir tópicos como:

  • Git básico
  • Fluxo Git (processo de desenvolvimento)
  • Instalação do GitLab
  • Fluxo de trabalho do GitLab
  • Entrega contínua
  • Instalação e configuração do GitLab
  • CI/CD do GitLab

No primeiro artigo, abordamos os fundamentos do Git, por que um entendimento de alto nível dos conceitos do Git é importante para o desenvolvimento de software moderno e como o Git pode ser usado para desenvolver software.

No segundo artigo, abordamos o fluxo de trabalho do GitLab: um processo inteiro do ciclo de vida do software e a entrega contínua.

No terceiro artigo, abordamos a instalação e configuração do GitLab e a conexão dos seus ambientes a ele

Neste artigo, finalmente, vamos escrever uma configuração de CD.

Plano

Ambientes

Em primeiro lugar, precisamos de vários ambientes e branches que correspondam a eles:

EnvironmentBranchDeliveryWho can commitWho can merge
TestmasterAutomaticDevelopers  OwnersDevelopers  Owners
PreprodpreprodAutomaticNo oneOwners
ProdprodSemiautomatic (press button to deliver)No one

Owners

Ciclo de desenvolvimento

E, como exemplo, desenvolveremos um novo recurso usando o fluxo do GitLab e o entregaremos usando a CD do GitLab.

  1. O recurso é desenvolvido em um branch de recursos.
  2. O branch de recurso é revisado e mesclado no master branch.
  3. Depois de um tempo (vários recursos mesclados), o master é mesclado com o preprod
  4. Depois de um tempo (teste do usuário, etc.), o preprod é mesclado com o prod

Veja como isso ficaria (marquei as partes que precisamos desenvolver para o CD em itálico):

  1. Desenvolvimento e teste
    • O desenvolvedor envia o código para o novo recurso em um branch de recursos separado
    • Depois que o recurso se torna estável, o desenvolvedor mescla nosso branch de recursos no master branch
    • O código do branch master é entregue ao ambiente de teste, onde é carregado e testado
  2. Entrega para o ambiente de pré-produção
    • O desenvolvedor cria a solicitação de mesclagem do branch master para o branch de pré-produção
    • Depois de algum tempo, o proprietário do repositório aprova a solicitação de mesclagem
    • O código do branch de pré-produção é entregue ao ambiente de pré-produção
  3. Entrega para o ambiente de produção
    • O desenvolvedor cria a solicitação de mesclagem do branch de pré-produção para o branch de produção
    • Depois de algum tempo, o proprietário do repositório aprova a solicitação de mesclagem
    • O proprietário do repositório aperta o botão "Implantar"
    • O código do branch de produção é entregue ao ambiente de produção

Ou o mesmo, mas em formato de gráfico:

Aplicativo

Nosso aplicativo consiste em duas partes:

  • API REST desenvolvida na plataforma InterSystems
  • Web application de JavaScript cliente

Estágios

Com o plano acima, podemos determinar as etapas que precisamos definir na nossa configuração de entrega contínua:

  • Carregamento — para importar o código do lado do servidor para o InterSystems IRIS
  • Teste — para testar o código do servidor e cliente
  • Pacote — para criar o código do cliente
  • Implantação — para "publicar" o código do cliente usando o servidor web

Veja como isso fica no arquivo de configuração gitlab-ci.yml:

stages:
  - load
  - test
  - package
  - deploy

Scripts

Carregamento

Em seguida, vamos definir os scripts. Documentos de scripts. Primeiro, vamos definir um script load server que carrega o código do lado do servidor:

load server:
  environment:
    name: test
    url: http://test.hostname.com
  only:
    - master
  tags:
    - test
  stage: load
  script: csession IRIS "##class(isc.git.GitLab).load()"

O que acontece aqui?

  • load server é o nome de um script
  • em seguida, descrevemos o ambiente em que esse script é executado
  • only: master — informa ao GitLab que esse script só deve ser executado quando houver um commit para o master branch
  • tags: test especifica que esse script só deve ser executado em um runner com a tag test
  • stage especifica o estágio para um script
  • script define o código para executar. No nosso caso, chamamos o classmethod load da classe isc.git.GitLab

Observação importante

Para InterSystems IRIS, troque csession por iris session.

Para Windows, use: irisdb -s ../mgr -U TEST "##class(isc.git.GitLab).load()

Agora, vamos escrever a classe isc.git.GitLab correspondente. Todos os pontos de entrada nessa classe ficam desta forma:

ClassMethod method()
{
    try {
        // code
        halt
    } catch ex {
        write !,$System.Status.GetErrorText(ex.AsStatus()),!
        do $system.Process.Terminate(, 1)
    }
}

Observe que esse método pode terminar de duas maneiras:

  • interrompendo o processo atual — que é registrado no GitLab como uma conclusão bem-sucedida
  • chamando $system.Process.Terminate — que termina o processo de maneira anormal e o GitLab registra isso como um erro

Dito isso, aqui está nosso código de carregamento:

/// Do a full load
/// do ##class(isc.git.GitLab).load()
ClassMethod load()
{
    try {
        set dir = ..getDir()
        do ..log("Importing dir " _ dir)
        do $system.OBJ.ImportDir(dir, ..getExtWildcard(), "c", .errors, 1)
        throw:$get(errors,0)'=0 ##class(%Exception.General).%New("Load error")

        halt
    } catch ex {
        write !,$System.Status.GetErrorText(ex.AsStatus()),!
        do $system.Process.Terminate(, 1)
    }
}

Dois métodos de utilitários são chamados:

  • getExtWildcard — para obter uma lista das extensões de arquivo relevantes
  • getDir — para obter o diretório do repositório

Como podemos obter o diretório?

Quando o GitLab executa um script, primeiro, ele especifica várias variáveis de ambiente. Uma delas é a CI_PROJECT_DIR — o caminho completo onde o repositório é clonado e onde o job é executado. Ele pode ser obtido facilmente no nosso método getDir :

ClassMethod getDir() [ CodeMode = expression ]
{
##class(%File).NormalizeDirectory($system.Util.GetEnviron("CI_PROJECT_DIR"))
}

####Testes

Aqui está o script de teste:

load test:
  environment:
    name: test
    url: http://test.hostname.com
  only:
    - master
  tags:
    - test
  stage: test
  script: csession IRIS "##class(isc.git.GitLab).test()"
  artifacts:
    paths:
      - tests.html

O que mudou? O nome e o código do script, é claro, mas o artefato também foi adicionado. Um artefato é uma lista de arquivos e diretórios que são anexados a um job depois que ele é concluído com sucesso. No nosso caso, depois que os testes forem concluídos, podemos gerar a página HTML redirecionando para os resultados dos testes e disponibilizá-la a partir do GitLab. 

Observe que há bastante copiar e colar do estágio de carregamento — o ambiente é o mesmo, partes do script, como ambientes, podem ser rotuladas separadamente e anexadas a um script. Vamos definir o ambiente de teste:

.env_test: &env_test
  environment:
    name: test
    url: http://test.hostname.com
  only:
    - master
  tags:
    - test

Agora, nosso script de teste fica assim:

load test:
  <<: *env_test
  script: csession IRIS "##class(isc.git.GitLab).test()"
  artifacts:
    paths:
      - tests.html

Em seguida, vamos executar os testes usando o framework UnitTest.

/// do ##class(isc.git.GitLab).test()
ClassMethod test()
{
    try {
        set tests = ##class(isc.git.Settings).getSetting("tests")
        if (tests'="") {
            set dir = ..getDir()
            set ^UnitTestRoot = dir

            $$$TOE(sc, ##class(%UnitTest.Manager).RunTest(tests, "/nodelete"))
            $$$TOE(sc, ..writeTestHTML())
            throw:'..isLastTestOk() ##class(%Exception.General).%New("Tests error")
        }
        halt
    } catch ex {
        do ..logException(ex)
        do $system.Process.Terminate(, 1)
    }
}

A definição do teste, nesse caso, é um caminho relativo à raiz do repositório onde os testes de unidade são armazenados. Se estiver vazio, pulamos testes. O método writeTestHTML é usado para gerar o html com um redirecionamento para os resultados dos testes:

ClassMethod writeTestHTML()
{
    set text = ##class(%Dictionary.XDataDefinition).IDKEYOpen($classname(), "html").Data.Read()
    set text = $replace(text, "!!!", ..getURL())
    
    set file = ##class(%Stream.FileCharacter).%New()
    set name = ..getDir() _  "tests.html"
    do file.LinkToFile(name)
    do file.Write(text)
    quit file.%Save()
}

ClassMethod getURL()
{
    set url = ##class(isc.git.Settings).getSetting("url")
    set url = url _ $system.CSP.GetDefaultApp("%SYS")
    set url = url_"/%25UnitTest.Portal.Indices.cls?Index="_ $g(^UnitTest.Result, 1) _ "&$NAMESPACE=" _ $zconvert($namespace,"O","URL")
    quit url
}

ClassMethod isLastTestOk() As %Boolean
{
    set in = ##class(%UnitTest.Result.TestInstance).%OpenId(^UnitTest.Result)
    for i=1:1:in.TestSuites.Count() {
        #dim suite As %UnitTest.Result.TestSuite
        set suite = in.TestSuites.GetAt(i)
        return:suite.Status=0 $$$NO
    }
    quit $$$YES
}

XData html
{
<html lang="en-US">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="refresh" content="0; url=!!!"/>
<script type="text/javascript">
window.location.href = "!!!"
</script>
</head>
<body>
If you are not redirected automatically, follow this <a href='!!!'>link to tests</a>.
</body>
</html>
}

Pacote

Nosso cliente é uma página HTML simples:

<html>
<head>
<script type="text/javascript">
function initializePage() {
  var xhr = new XMLHttpRequest();
  var url = "${CI_ENVIRONMENT_URL}:57772/MyApp/version";
  xhr.open("GET", url, true);
  xhr.send();
  xhr.onloadend = function (data) {
    document.getElementById("version").innerHTML = "Version: " + this.response;
  };
  
  var xhr = new XMLHttpRequest();
  var url = "${CI_ENVIRONMENT_URL}:57772/MyApp/author";
  xhr.open("GET", url, true);
  xhr.send();
  xhr.onloadend = function (data) {
    document.getElementById("author").innerHTML = "Author: " + this.response;
  };
}
</script>
</head>
<body  onload="initializePage()">
<div id = "version"></div>
<div id = "author"></div>
</body>
</html>

E, para criá-la, precisamos substituir ${CI_ENVIRONMENT_URL} pelo seu valor. Claro, um aplicativo real provavelmente exigiria npm, mas esse é apenas um exemplo. Aqui está o script:

package client:
  <<: *env_test
  stage: package
  script: envsubst < client/index.html > index.html
  artifacts:
    paths:
      - index.html

Implantação

Por fim, implantamos nosso cliente ao copiar index.html para o diretório raiz do servidor web.

deploy client:
  <<: *env_test
  stage: deploy
  script: cp -f index.html /var/www/html/index.html

É isso!

Vários ambientes

O que fazer se você precisar executar o mesmo script (semelhante) em vários ambientes? Partes do script também podem ser rótulos, então aqui está uma configuração de exemplo que carrega o código em ambientes de teste e pré-produção:

stages:
  - load
  - test

.env_test: &env_test
  environment:
    name: test
    url: http://test.hostname.com
  only:
    - master
  tags:
    - test
    
.env_preprod: &env_preprod
  environment:
    name: preprod
    url: http://preprod.hostname.com
  only:
    - preprod
  tags:
    - preprod

.script_load: &script_load
  stage: load
  script: csession IRIS "##class(isc.git.GitLab).loadDiff()"

load test:
  <<: *env_test
  <<: *script_load

load preprod:
  <<: *env_preprod
  <<: *script_load

Assim, podemos fugir de copiar e colar o código.

Veja a configuração de CD completa aqui. Ela segue o plano original de mover código entre os ambientes de teste, pré-produção e produção.

Conclusão

A entrega contínua pode ser configurada para automatizar qualquer fluxo de trabalho de desenvolvimento necessário.

Links

O que vem a seguir

No próximo artigo, vamos criar a configuração de CD que usa o contêiner Docker do InterSystems IRIS.

0
0 101
Artigo Danusa Calixto · Dez. 15, 2022 5m read

Nesta série de artigos, quero apresentar e discutir várias abordagens possíveis para o desenvolvimento de software com tecnologias da InterSystems e do GitLab. Vou cobrir tópicos como:

  • Git básico
  • Fluxo Git (processo de desenvolvimento)
  • Instalação do GitLab
  • Fluxo de trabalho do GitLab
  • Entrega contínua
  • Instalação e configuração do GitLab
  • CI/CD do GitLab

No primeiro artigo, abordamos os fundamentos do Git, por que um entendimento de alto nível dos conceitos do Git é importante para o desenvolvimento de software moderno e como o Git pode ser usado para desenvolver software.

No segundo artigo, abordamos o fluxo de trabalho do GitLab: um processo inteiro do ciclo de vida do software e a entrega contínua.

Neste artigo, vamos discutir:

  • Instalação e configuração do GitLab
  • Conexão dos seus ambientes ao GitLab

Instalação do GitLab

Vamos instalar o GitLab no local. Há várias maneiras de instalar o GitLab — da fonte, pacote, em um contêiner. Não descreverei todos os passos aqui, há um guia para isso. Ainda assim, algumas observações.

Pré-requisitos:

  • Servidor separado — como é um web application e um recurso bastante intensivo, é melhor executar em um servidor separado
  • Linux
  • (Opcional, mas altamente recomendável) Domínio — necessário para executar páginas e proteger a configuração inteira

Configuração

Primeiro de tudo, você provavelmente precisa enviar e-mails com notificações.

Em seguida, recomendo instalar Páginas. Como discutido no artigo anterior — artefatos do script podem ser enviados para o GitLab. O usuário pode fazer o download deles, mas é útil poder abri-los diretamente no navegador e, para isso, precisamos de páginas.

Por que você precisa de páginas:

Como as páginas html podem ter um redirecionamento onload, elas podem ser usadas para enviar o usuário para onde precisamos. Por exemplo, veja este código que gera uma página html que envia um usuário para o último teste de unidade executado (no momento da geração do html):

ClassMethod writeTestHTML()
{
  set text = ##class(%Dictionary.XDataDefinition).IDKEYOpen($classname(), "html").Data.Read()
  set text = $replace(text, "!!!", ..getURL())
  
  set file = ##class(%Stream.FileCharacter).%New()
  set name = "tests.html"
  do file.LinkToFile(name)
  do file.Write(text)
  quit file.%Save()
}

ClassMethod getURL()
{
  set url = "http://host:57772"
  set url = url _ $system.CSP.GetDefaultApp("%SYS")
  set url = url_"/%25UnitTest.Portal.Indices.cls?Index="_ $g(^UnitTest.Result, 1) _ "&$NAMESPACE=" _ $zconvert($namespace,"O","URL")
  quit url
}

XData html
{

  
  
    If you are not redirected automatically, follow this link to tests.
  

}

Encontrei um bug usando as páginas (erro 502 ao procurar artefatos), veja aqui a correção.

 

Conexão dos seus ambientes ao GitLab

Para executar scripts de CD, você precisa de ambientes, servidores configurados para executar seu aplicativo. Presumindo que você tem um servidor Linux com o produto InterSystems instalado (digamos InterSystems IRIS, mas funciona também com o Caché e Ensemble), estas etapas conectam o ambiente ao GitLab:

  1. Instalar o runner do GitLab
  2. Registrar o runner com o GitLab
  3. Permitir que o runner chame o InterSystems IRIS

Observação importante sobre a instalação do runner GitLab, NÃO clone servidores após instalar o runner do GitLab.  Os resultados são imprevisíveis e muito indesejados.

Registrar o runner com o GitLab

Após executar o inicial:

sudo gitlab-runner register

você verá vários prompts e, embora a maioria das etapas seja bastante direta, várias não são:

Insira o token gitlab-ci para este runner

Há vários tokens disponíveis:

  • Um para o sistema inteiro (disponível nas configurações de administração)
  • Um para cada projeto (disponível nas configurações do projeto)

Conforme você conecta um runner para executar a CD para um projeto específico, você precisa especificar um token para este projeto.

Insira as tags gitlab-ci para este runner (separadas por vírgulas):

Na configuração de CD, você pode filtrar quais scripts vão ser executados em quais tags. Então, no caso mais simples, especifique uma tag, que seria o nome do ambiente.

Insira o executor: ssh, docker+machine, docker-ssh+machine, kubernetes, docker, parallels, virtualbox, docker-ssh, shell:
docker

Se você estiver usando o servidor habitual sem docker, escolha shell.  O Docker será discutido nas partes posteriores.

Permitir que o runner chame o InterSystems IRIS

Depois de conectar o runner ao GitLab, precisamos permitir que ele interaja com o InterSystems IRIS, para isso:

  1. O usuário gitlab-runner precisa conseguir chamar csession. Para fazer isso, adicione-o ao grupo cacheusr: 
    • usermod -a -G cacheusr gitlab-runner
  2. Crie o usuário gitlab-runner no InterSystems IRIS e dê a ele funções para realizar tarefas de CD (escreva para DB, etc.)
  3. Permitir a autenticação no nível do SO

Para 2 e 3, outras abordagens podem ser usadas, como a transmissão de usuário/código, mas acho que a autenticação de SO é preferível. 

Conclusão

Nesta parte:

  • GitLab instalado
  • Ambientes conectados ao GitLab

O que vem a seguir

Na próxima parte, escrevemos nossa configuração de entrega contínua.

0
0 156
Artigo Danusa Calixto · Nov. 9, 2022 10m read

Nesta série de artigos, quero apresentar e discutir várias abordagens possíveis para o desenvolvimento de software com tecnologias da InterSystems e do GitLab. Vou cobrir tópicos como:

  • Git básico
  • Fluxo Git (processo de desenvolvimento)
  • Instalação do GitLab
  • Fluxo de trabalho do GitLab
  • Entrega contínua
  • Instalação e configuração do GitLab
  • CI/CD do GitLab

No artigo anterior, abordamos os fundamentos do Git, por que um entendimento de alto nível dos conceitos do Git é importante para o desenvolvimento de software moderno e como o Git pode ser usado para desenvolver software. Ainda assim, nosso foco foi na parte da implementação do desenvolvimento de software, mas esta parte apresenta:

  • Fluxo de trabalho do GitLab — um processo completo do ciclo de vida do software, desde a ideia até o feedback do usuário
  • Entrega Contínua — uma abordagem de engenharia de software em que as equipes produzem software em ciclos curtos, garantindo que o software possa ser lançado de forma confiável a qualquer momento. Seu objetivo é construir, testar e lançar software com mais rapidez e frequência.

Fluxo de trabalho do GitLab

O fluxo de trabalho do GitLab é uma sequência lógica de possíveis ações a serem tomadas durante todo o ciclo de vida do processo de desenvolvimento de software.

O fluxo de trabalho do GitLab leva em consideração o fluxo do GitLab, que discutimos em um artigo anterior. Veja como funciona:

  1. Ideia: todas as novas propostas começam com uma ideia.
  2. Problema: a maneira mais eficaz de discutir uma ideia é criar um problema para ela. Sua equipe e seus colaboradores podem ajudar você a aprimorar e melhorar a ideia no rastreador de problemas.
  3. Plano: quando a discussão chega a um acordo, é hora de programar. Porém, primeiro, precisamos priorizar e organizar nosso fluxo de trabalho ao atribuir problemas a marcos e quadro de problemas.
  4. Código: agora estamos prontos para escrever nosso código, já que está tudo organizado.
  5. Commit: depois de satisfeitos com o rascunho, podemos enviar nosso código para um feature-branch com controle de versão. O fluxo do GitLab foi explicado em detalhes no artigo anterior.
  6. Teste: executamos nossos scripts usando o CI GitLab, para construir e testar nosso aplicativo.
  7. Revisão: assim que nosso script funcionar e nossos testes e compilações forem bem-sucedidos, estamos prontos para que nosso código seja revisado e aprovado.
  8. Staging: agora é hora de implantar nosso código em um ambiente de staging para verificar se tudo funciona como esperado ou se ainda precisamos de ajustes.
  9. Produção: quando tudo estiver funcionando como deve, é hora de implantar no nosso ambiente de produção!
  10. Feedback: agora é hora de olhar para trás e verificar qual etapa do nosso trabalho precisa ser melhorada.

Novamente, o processo em si não é novo (ou exclusivo do GitLab) e pode ser alcançado com outras ferramentas da sua escolha.

Vamos discutir várias dessas etapas e o que elas implicam. Também há documentação disponível.

Problema e plano

As etapas iniciais do fluxo de trabalho do GitLab são centradas em um problema: um recurso, bug ou outro tipo de trabalho semanticamente separado.

O problema tem várias finalidades, como:

  • Gerenciamento: um problema tem data de vencimento, pessoa designada, tempo gasto e estimativas, etc. para ajudar a monitorar a resolução do problema.
  • Administrativo: um problema faz parte de um marco, quadro kanban, que nos permite rastrear nosso software à medida que ele avança de versão para versão.
  • Desenvolvimento: um problema tem uma discussão e commits associados a ele.

A etapa de planejamento nos permite agrupar os problemas por prioridade, marco, quadro kanban e ter uma visão geral disso.

O desenvolvimento foi discutido na parte anterior, basta seguir qualquer fluxo git que quiser. Depois que desenvolvemos nosso novo recurso e o mesclamos no master: o que vem depois?

Entrega contínua

A entrega contínua é uma abordagem de engenharia de software em que as equipes produzem software em ciclos curtos, garantindo que o software possa ser lançado de forma confiável a qualquer momento. Seu objetivo é construir, testar e lançar software com mais rapidez e frequência. A abordagem ajuda a reduzir o custo, o tempo e o risco da entrega de alterações, permitindo mais atualizações incrementais para aplicativos em produção. Um processo de implantação simples e repetível é importante para a entrega contínua.

Entrega contínua no GitLab

No GitLab, a configuração da entrega contínua é definida por repositório como um arquivo de configuração YAML.

  • A configuração de entrega contínua é uma série de estágios consecutivos.
  • Cada estágio tem um ou vários scripts que são executados em paralelo.

O script define uma ação e quais condições devem ser atendidas para executá-la:

  • O que fazer (executar o comando do SO, executar um contêiner)?
  • Quando executar o script:
    • Quais são os gatilhos (commit de um branch específico)?
    • Nós o executamos se os estágios anteriores falharam?
  • Executar manualmente ou automaticamente?
  • Em que ambiente executar o script?
  • Quais artefatos salvar após a execução dos scripts (eles são carregados do ambiente para o GitLab para facilitar o acesso)?

Ambiente - é um servidor ou contêiner configurado no qual você pode executar seus scripts.

Runners executam scripts em ambientes específicos. Eles são conectados ao GitLab e executam scripts conforme necessário.

O runner pode ser implantado em um servidor, contêiner ou até mesmo na sua máquina local.

Como acontece a entrega contínua?

  1. O novo commit é enviado para o repositório.
  2. O GitLab verifica a configuração de entrega contínua.
  3. A configuração de entrega contínua contém todos os scripts possíveis para todos os casos, para que sejam filtrados para um conjunto de scripts que devem ser executados para esse commit específico (por exemplo, um commit para o branch master aciona apenas ações relacionadas a um branch master). Esse conjunto é chamado de pipeline.
  4. O pipeline é executado em um ambiente de destino e os resultados da execução são salvos e exibidos no GitLab.

Por exemplo, aqui está um pipeline executado após um commit em um branch master:

Ele consiste em quatro etapas, executadas consecutivamente

  1. O estágio de carregamento carrega o código em um servidor
  2. O estágio de teste executa testes de unidade
  3. O estágio de pacote consiste em dois scripts executados em paralelo:
    • Compilação cliente
    • Código de exportação do servidor (principalmente para fins informativos)
  4. O estágio de implantação move o cliente criado para o diretório do servidor web.

Como podemos ver, todos os scripts foram executados com sucesso. Se um dos scripts falhar, por padrão, os scripts posteriores não são executados (mas podemos alterar esse comportamento):

Se abrirmos o script, podemos ver o log e determinar por que ele falhou:

Running with gitlab-runner 10.4.0 (857480b6)
 on test runner (ab34a8c5)
Using Shell executor...
Running on gitlab-test...
&lt;span class="term-fg-l-green term-bold">Fetching changes...&lt;/span>
Removing diff.xml
Removing full.xml
Removing index.html
Removing tests.html
HEAD is now at a5bf3e8 Merge branch '4-versiya-1-0' into 'master'
From http://gitlab.eduard.win/test/testProject
 * [new branch] 5-versiya-1-1 -> origin/5-versiya-1-1
 a5bf3e8..442a4db master -> origin/master
 d28295a..42a10aa preprod -> origin/preprod
 3ac4b21..7edf7f4 prod -> origin/prod
&lt;span class="term-fg-l-green term-bold">Checking out 442a4db1 as master...&lt;/span>
&lt;span class="term-fg-l-green term-bold">Skipping Git submodules setup&lt;/span>
&lt;span class="term-fg-l-green term-bold">$ csession ensemble "##class(isc.git.GitLab).loadDiff()"&lt;/span>

[2018-03-06 13:58:19.188] Importing dir /home/gitlab-runner/builds/ab34a8c5/0/test/testProject/

[2018-03-06 13:58:19.188] Loading diff between a5bf3e8596d842c5cc3da7819409ed81e62c31e3 and 442a4db170aa58f2129e5889a4bb79261aa0cad0

[2018-03-06 13:58:19.192] Variable modified
var=$lb("MyApp/Info.cls")

Load started on 03/06/2018 13:58:19
Loading file /home/gitlab-runner/builds/ab34a8c5/0/test/testProject/MyApp/Info.cls as udl
Load finished successfully.

[2018-03-06 13:58:19.241] Variable items
var="MyApp.Info.cls"
var("MyApp.Info.cls")=""

Compilation started on 03/06/2018 13:58:19 with qualifiers 'cuk /checkuptodate=expandedonly'
Compiling class MyApp.Info
Compiling routine MyApp.Info.1
ERROR: MyApp.Info.cls(version+2) #1003: Expected space : '}' : Offset:14 [zversion+1^MyApp.Info.1]
 TEXT:  quit, "1.0" }
Detected 1 errors during compilation in 0.010s.

[2018-03-06 13:58:19.252] ERROR #5475: Error compiling routine: MyApp.Info.1. Errors: ERROR: MyApp.Info.cls(version+2) #1003: Expected space : '}' : Offset:14 [zversion+1^MyApp.Info.1]
 > ERROR #5030: An error occurred while compiling class 'MyApp.Info'
&lt;span class="term-fg-l-red term-bold">ERROR: Job failed: exit status 1
&lt;/span>

O erro de compilação causou a falha do nosso script.

Conclusão

  • O GitLab é compatível com todos os principais estágios de desenvolvimento de software.
  • A entrega contínua pode ajudar você a automatizar tarefas de construção, teste e implantação do seu software.

O que vem a seguir?

No próximo artigo, vamos:

  • Instalar o GitLab.
  • Conectá-lo a diversos ambientes com os produtos InterSystems instalados.
  • Escrever uma configuração de entrega contínua.

Vamos discutir como a entrega contínua deve funcionar.

Em primeiro lugar, precisamos de vários ambientes e branches que correspondam a eles. O código entra nesse branch e é entregue ao ambiente de destino:

AmbienteBranchEntregaQuem pode fazer enviosQuem pode mesclar
TestemasterAutomáticoDesenvolvedores  ProprietáriosDesenvolvedores  Proprietários
PreprodpreprodAutomáticoNinguémProprietários
ProdprodSemiautomático (pressionar botão para entregar)NinguémProprietários

E, como exemplo, desenvolveremos um novo recurso usando o fluxo do GitLab e o entregaremos usando a CD do GitLab.

  1. O recurso é desenvolvido em um branch de recursos.
  2. O branch de recurso é revisado e mesclado no master branch.
  3. Depois de um tempo (vários recursos mesclados), o master é mesclado com o preprod
  4. Depois de um tempo (teste do usuário, etc.), o preprod é mesclado com o prod

Veja como ficaria:

  1. Desenvolvimento e teste
    • O desenvolvedor envia o código para o novo recurso em um branch de recursos separado
    • Depois que o recurso se torna estável, o desenvolvedor mescla nosso branch de recursos no master branch
    • O código do branch master é entregue ao ambiente de teste, onde é carregado e testado
  2. Entrega para o ambiente de pré-produção
    • O desenvolvedor cria a solicitação de mesclagem do branch master para o branch de pré-produção
    • Depois de algum tempo, o proprietário do repositório aprova a solicitação de mesclagem
    • O código do branch de pré-produção é entregue ao ambiente de pré-produção
  3. Entrega para o ambiente de produção
    • O desenvolvedor cria a solicitação de mesclagem do branch de pré-produção para o branch de produção
    • Depois de algum tempo, o proprietário do repositório aprova a solicitação de mesclagem
    • O proprietário do repositório aperta o botão "Implantar"
    • O código do branch de produção é entregue ao ambiente de produção

Ou o mesmo, mas em formato gráfico:

 

0
0 302
Artigo Danusa Calixto · Set. 13, 2022 31m read

A interoperabilidade é cada vez mais importante atualmente. O InterSystems IRIS 2022.1 tem uma nova API de mensagens para a comunicação com plataformas de streaming de eventos, como Kafka, AWS SQS/SNS, JMS e RabbitMQ.

Este artigo mostra como você pode se conectar ao Kafka e AWS SQS com facilidade.
Começamos com uma breve discussão dos conceitos e termos básicos das plataformas de streaming de eventos. 

Finalidade das plataformas de streaming de eventos e termos comuns

As plataformas de streaming de eventos, como Kafka ou AWS SQS, são capazes de consumir um stream de eventos sem restrições em uma frequência bastante alta e podem reagir a eventos. Os consumidores leem os dados dos streams para processamento adicional. Eles são geralmente usados em ambientes de IoT.

Os termos comuns nessa área são:

  • Tópico/Fila, o local onde os dados são armazenados
  • Produtor, cria e envia os dados (eventos, mensagens) para um tópico ou uma fila
  • Consumidor, lê os eventos/mensagens de um ou mais tópicos ou filas
  • Publicar/Assinar, os produtores enviam os dados para um tópico/fila (publicar), os consumidores assinam um tópico/fila e recebem notificações automáticas com a chegada de novos dados
  • Polling, os consumidores precisam buscar ativamente novos dados em um tópico/fila

Por que eles são usados?

  • Dissociação de produtores e consumidores
  • Altamente escalonável para dados em tempo real

Preciso mesmo deles? Como desenvolvedor do InterSystems IRIS, provavelmente não, mas você não está sozinho...

API de mensagens externas

As novas classes da API estão localizadas no pacote %External.Messaging. Ele contém as classes genéricas Client-, Settings- e Message.  As classes especializadas do Kafka, AWS SQS/SNS, JMS e RabbitMQ são subclasses dessas classes genéricas. 

O fluxo de comunicação básico é:

  1. Criar um objeto de configurações para a plataforma de destino. Isso também é responsável pela autenticação em relação à plataforma de destino.
  2. Criar um objeto de cliente específico e transmitir o objeto de configurações a ele.
  3. Criar um objeto de mensagem e enviar para o destino.

As seguintes seções demonstram como você pode se comunicar com Kafka e AWS SQS (Simple Queue Service).

Interação com o Kafka

Vamos começar com um exemplo do Kafka. Primeiro, criamos uma classe que usa a nova API %External Messaging para criar um tópico, enviar uma mensagem ao Kafka e receber uma mensagem dele.

Primeiro, ela cria um objeto de configurações do Kafka:

&lt;span class="hljs-keyword">set&lt;/span> tSettings = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.KafkaSettings&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
&lt;span class="hljs-keyword">set&lt;/span> tSettings.servers = &lt;span class="hljs-built_in">$$$KAFKASERVER&lt;/span>
&lt;span class="hljs-keyword">set&lt;/span> tSettings.groupId = &lt;span class="hljs-string">"iris-consumer"&lt;/span>

Após definir o endereço do servidor do Kafka, ela define um ID de grupo do Kafka.

Com essas configurações, um objeto de cliente do Kafka é criado:

&lt;span class="hljs-keyword">set&lt;/span> tClient = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.Client&lt;/span>).CreateKafkaClient(tSettings.ToJSON(),.tSc)

Em seguida, um topico é criado ao invocar o método CreateTopic() do cliente do Kafka:

&lt;span class="hljs-keyword">Set&lt;/span> tSC = tClient.CreateTopic(pTopicName,tNumberOfPartitions,tReplicationFactor)

 Veja abaixo a amostra de código completa:

Include Kafka.Settings

&lt;span class="hljs-keyword">Class&lt;/span> Kafka.api [ Abstract ]
{

&lt;span class="hljs-keyword">ClassMethod&lt;/span> CreateTopic(pTopicName &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span>) &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span>
{
    &lt;span class="hljs-keyword">#dim&lt;/span> tSc &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span> = &lt;span class="hljs-built_in">$$$OK&lt;/span>
    &lt;span class="hljs-keyword">try&lt;/span> {
        &lt;span class="hljs-keyword">set&lt;/span> tSettings = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.KafkaSettings&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.servers = &lt;span class="hljs-built_in">$$$KAFKASERVER&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.groupId = &lt;span class="hljs-string">"iris-consumer"&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tClient = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.Client&lt;/span>).CreateKafkaClient(tSettings.ToJSON(),.tSc)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tSc)
        &lt;span class="hljs-keyword">Set&lt;/span> tNumberOfPartitions = &lt;span class="hljs-number">1&lt;/span>
        &lt;span class="hljs-keyword">Set&lt;/span> tReplicationFactor = &lt;span class="hljs-number">1&lt;/span>
        &lt;span class="hljs-keyword">Set&lt;/span> tSC = tClient.CreateTopic(pTopicName,tNumberOfPartitions,tReplicationFactor)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tSC)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.&lt;span class="hljs-keyword">Close&lt;/span>())
        }
    &lt;span class="hljs-keyword">catch&lt;/span> tEx {
        &lt;span class="hljs-keyword">set&lt;/span> tSc = tEx.AsStatus()
    }

    &lt;span class="hljs-keyword">return&lt;/span> tSc
}



}

Depois de criar um tópico, podemos enviar e receber mensagens do Kafka. O código é semelhante ao exibido acima.

&lt;span class="hljs-keyword">ClassMethod&lt;/span> SendMessage(pMessage &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span>, pTopic &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span>) &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span>
{
    &lt;span class="hljs-keyword">#dim&lt;/span> tSettings &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.KafkaSettings&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tClient &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.KafkaClient&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tMessage &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.KafkaMessage&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tSc &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span> = &lt;span class="hljs-built_in">$$$OK&lt;/span>
    &lt;span class="hljs-keyword">try&lt;/span> {
        &lt;span class="hljs-keyword">set&lt;/span> tSettings = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.KafkaSettings&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.servers = &lt;span class="hljs-built_in">$$$KAFKASERVER&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.groupId = &lt;span class="hljs-string">"iris-consumer"&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tMessage = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.KafkaMessage&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
        &lt;span class="hljs-keyword">set&lt;/span> tMessage.topic = pTopic
        &lt;span class="hljs-keyword">set&lt;/span> tMessage.value = pMessage
        &lt;span class="hljs-keyword">set&lt;/span> tClient = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.Client&lt;/span>).CreateKafkaClient(tSettings.ToJSON(),.tSc)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tSc)
        &lt;span class="hljs-keyword">Set&lt;/span> producerSettings = &lt;span class="hljs-string">"{""key.serializer"":""org.apache.kafka.common.serialization.StringSerializer""}"&lt;/span>
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.UpdateProducerConfig(producerSettings))
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.SendMessage(tMessage))
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.&lt;span class="hljs-keyword">Close&lt;/span>())

    }
    &lt;span class="hljs-keyword">catch&lt;/span> tEx {
        &lt;span class="hljs-keyword">set&lt;/span> tSc = tEx.AsStatus()
    }

    &lt;span class="hljs-keyword">return&lt;/span> tSc
}

&lt;span class="hljs-keyword">ClassMethod&lt;/span> ReceiveMessage(pTopicName &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span>, pGroupId &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span> = &lt;span class="hljs-string">"iris-consumer"&lt;/span>, Output pMessages) &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span>
{
    &lt;span class="hljs-keyword">#dim&lt;/span> tSettings &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.KafkaSettings&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tClient &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.KafkaClient&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tMessage &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.KafkaMessage&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tSc &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span> = &lt;span class="hljs-built_in">$$$OK&lt;/span>
    &lt;span class="hljs-keyword">try&lt;/span> {
        &lt;span class="hljs-keyword">set&lt;/span> tSettings = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.KafkaSettings&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.servers = &lt;span class="hljs-built_in">$$$KAFKASERVER&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.groupId = pGroupId
        
        &lt;span class="hljs-keyword">set&lt;/span> tClient = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.Client&lt;/span>).CreateKafkaClient(tSettings.ToJSON(),.tSc)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tSc)
        &lt;span class="hljs-keyword">Set&lt;/span> producerSettings = &lt;span class="hljs-string">"{""key.serializer"":""org.apache.kafka.common.serialization.StringSerializer""}"&lt;/span>
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.UpdateProducerConfig(producerSettings))
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.ReceiveMessage(pTopicName, .pMessages))
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.&lt;span class="hljs-keyword">Close&lt;/span>())
        }
    &lt;span class="hljs-keyword">catch&lt;/span> tEx {
        &lt;span class="hljs-keyword">set&lt;/span> tSc = tEx.AsStatus()
    }

    &lt;span class="hljs-keyword">return&lt;/span> tSc
}

Vamos testar. Com uma instância do Kafka em execução, criamos um tópico community com o método CreateTopic acima:

Ignore os avisos log4j aqui. O método retorna um código de status OK. Então, o tópico foi criado. Em seguida, vamos enviar uma mensagem para esse tópico. Para verificar que a mensagem foi enviada ao tópico, executo um consumidor do Kafka genérico. Esse consumidor ouve o tópico community:

Então, vamos enviar uma mensagem para esse tópico. Vou enviar uma JSON-String para ele, mas você basicamente pode enviar qualquer formato de mensagem para um tópico.

Vamos conferir se o consumidor recebeu a mensagem:

A mensagem foi recebida com sucesso pelo consumidor.

Para receber mensagens e excluir tópicos, é parecido com a amostra acima. Veja abaixo a implementação da amostra completa. O arquivo include Kafka.settings só contém uma definição macro: #define KAFKASERVER <Kafka server location and port>.

Include Kafka.Settings

&lt;span class="hljs-keyword">Class&lt;/span> Kafka.api [ Abstract ]
{

&lt;span class="hljs-keyword">ClassMethod&lt;/span> CreateTopic(pTopicName &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span>) &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span>
{
    &lt;span class="hljs-keyword">#dim&lt;/span> tSc &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span> = &lt;span class="hljs-built_in">$$$OK&lt;/span>
    &lt;span class="hljs-keyword">try&lt;/span> {
        &lt;span class="hljs-keyword">set&lt;/span> tSettings = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.KafkaSettings&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.servers = &lt;span class="hljs-built_in">$$$KAFKASERVER&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.groupId = &lt;span class="hljs-string">"iris-consumer"&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tClient = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.Client&lt;/span>).CreateKafkaClient(tSettings.ToJSON(),.tSc)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tSc)
        &lt;span class="hljs-keyword">Set&lt;/span> tNumberOfPartitions = &lt;span class="hljs-number">1&lt;/span>
        &lt;span class="hljs-keyword">Set&lt;/span> tReplicationFactor = &lt;span class="hljs-number">1&lt;/span>
        &lt;span class="hljs-keyword">Set&lt;/span> tSC = tClient.CreateTopic(pTopicName,tNumberOfPartitions,tReplicationFactor)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tSC)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.&lt;span class="hljs-keyword">Close&lt;/span>())
        }
    &lt;span class="hljs-keyword">catch&lt;/span> tEx {
        &lt;span class="hljs-keyword">set&lt;/span> tSc = tEx.AsStatus()
    }

    &lt;span class="hljs-keyword">return&lt;/span> tSc
}

&lt;span class="hljs-keyword">ClassMethod&lt;/span> DeleteTopic(pTopicName &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span>) &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span>
{
    &lt;span class="hljs-keyword">#dim&lt;/span> tSc &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span> = &lt;span class="hljs-built_in">$$$OK&lt;/span>
    &lt;span class="hljs-keyword">try&lt;/span> {
        &lt;span class="hljs-keyword">set&lt;/span> tSettings = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.KafkaSettings&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.servers = &lt;span class="hljs-built_in">$$$KAFKASERVER&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.groupId = &lt;span class="hljs-string">"iris-consumer"&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tClient = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.Client&lt;/span>).CreateKafkaClient(tSettings.ToJSON(),.tSc)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tSc)
        &lt;span class="hljs-keyword">Set&lt;/span> tNumberOfPartitions = &lt;span class="hljs-number">1&lt;/span>
        &lt;span class="hljs-keyword">Set&lt;/span> tReplicationFactor = &lt;span class="hljs-number">1&lt;/span>
        &lt;span class="hljs-keyword">Set&lt;/span> tSC = tClient.DeleteTopic(pTopicName)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tSC)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.&lt;span class="hljs-keyword">Close&lt;/span>())
        }
    &lt;span class="hljs-keyword">catch&lt;/span> tEx {
        &lt;span class="hljs-keyword">set&lt;/span> tSc = tEx.AsStatus()
    }

    &lt;span class="hljs-keyword">return&lt;/span> tSc
}

&lt;span class="hljs-keyword">ClassMethod&lt;/span> SendMessage(pMessage &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span>, pTopic &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span>) &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span>
{
    &lt;span class="hljs-keyword">#dim&lt;/span> tSettings &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.KafkaSettings&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tClient &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.KafkaClient&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tMessage &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.KafkaMessage&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tSc &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span> = &lt;span class="hljs-built_in">$$$OK&lt;/span>
    &lt;span class="hljs-keyword">try&lt;/span> {
        &lt;span class="hljs-keyword">set&lt;/span> tSettings = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.KafkaSettings&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.servers = &lt;span class="hljs-built_in">$$$KAFKASERVER&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.groupId = &lt;span class="hljs-string">"iris-consumer"&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tMessage = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.KafkaMessage&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
        &lt;span class="hljs-keyword">set&lt;/span> tMessage.topic = pTopic
        &lt;span class="hljs-keyword">set&lt;/span> tMessage.value = pMessage
        &lt;span class="hljs-keyword">set&lt;/span> tClient = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.Client&lt;/span>).CreateKafkaClient(tSettings.ToJSON(),.tSc)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tSc)
        &lt;span class="hljs-keyword">Set&lt;/span> producerSettings = &lt;span class="hljs-string">"{""key.serializer"":""org.apache.kafka.common.serialization.StringSerializer""}"&lt;/span>
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.UpdateProducerConfig(producerSettings))
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.SendMessage(tMessage))
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.&lt;span class="hljs-keyword">Close&lt;/span>())

    }
    &lt;span class="hljs-keyword">catch&lt;/span> tEx {
        &lt;span class="hljs-keyword">set&lt;/span> tSc = tEx.AsStatus()
    }

    &lt;span class="hljs-keyword">return&lt;/span> tSc
}

&lt;span class="hljs-keyword">ClassMethod&lt;/span> ReceiveMessage(pTopicName &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span>, pGroupId &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span> = &lt;span class="hljs-string">"iris-consumer"&lt;/span>, Output pMessages) &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span>
{
    &lt;span class="hljs-keyword">#dim&lt;/span> tSettings &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.KafkaSettings&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tClient &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.KafkaClient&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tMessage &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.KafkaMessage&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tSc &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span> = &lt;span class="hljs-built_in">$$$OK&lt;/span>
    &lt;span class="hljs-keyword">try&lt;/span> {
        &lt;span class="hljs-keyword">set&lt;/span> tSettings = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.KafkaSettings&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.servers = &lt;span class="hljs-built_in">$$$KAFKASERVER&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.groupId = pGroupId
        
        &lt;span class="hljs-keyword">set&lt;/span> tClient = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.Client&lt;/span>).CreateKafkaClient(tSettings.ToJSON(),.tSc)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tSc)
        &lt;span class="hljs-keyword">Set&lt;/span> producerSettings = &lt;span class="hljs-string">"{""key.serializer"":""org.apache.kafka.common.serialization.StringSerializer""}"&lt;/span>
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.UpdateProducerConfig(producerSettings))
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.ReceiveMessage(pTopicName, .pMessages))
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.&lt;span class="hljs-keyword">Close&lt;/span>())
        }
    &lt;span class="hljs-keyword">catch&lt;/span> tEx {
        &lt;span class="hljs-keyword">set&lt;/span> tSc = tEx.AsStatus()
    }

    &lt;span class="hljs-keyword">return&lt;/span> tSc
}

}

 

Interação com o AWS SQS

Como você se comunicaria com o AWS SQS (Simple Queue Service)? 
O procedimento básico é bastante similar. No entanto, o AWS exige a autenticação e não usa o termo "tópico". Ele fala sobre filas. Você pode enviar uma mensagem para uma fila, e os consumidores podem receber mensagens de uma ou mais filas.

Semelhante à classe da API acima, criei algo para o AWS SQS.

&lt;span class="hljs-keyword">Class&lt;/span> AWS.SQS.api [ Abstract ]
{

&lt;span class="hljs-keyword">ClassMethod&lt;/span> SendMessage(pMessage &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span>, pQueue &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span>) &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span>
{
    &lt;span class="hljs-keyword">#dim&lt;/span> tSettings &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.SQSSettings&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tMessage &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.SQSMessage&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tClient &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.SQSClient&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tSc &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span> = &lt;span class="hljs-built_in">$$$OK&lt;/span>
    &lt;span class="hljs-keyword">try&lt;/span> {
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(&lt;span class="hljs-keyword">##class&lt;/span>(AWS.Utils).GetCredentials(.tCredentials))
        &lt;span class="hljs-keyword">set&lt;/span> tSettings = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.SQSSettings&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.accessKey = tCredentials(&lt;span class="hljs-string">"aws_access_key_id"&lt;/span>)
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.secretKey = tCredentials(&lt;span class="hljs-string">"aws_secret_access_key"&lt;/span>)
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.sessionToken = tCredentials(&lt;span class="hljs-string">"aws_session_token"&lt;/span>)
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.region = &lt;span class="hljs-string">"eu-central-1"&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tMessage = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.SQSMessage&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
        &lt;span class="hljs-keyword">set&lt;/span> tMessage.body = pMessage
        &lt;span class="hljs-keyword">set&lt;/span> tMessage.queue = pQueue

        &lt;span class="hljs-keyword">set&lt;/span> tClient = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.Client&lt;/span>).CreateSQSClient(tSettings.ToJSON(),.tSc)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tSc)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.SendMessage(tMessage))

    }
    &lt;span class="hljs-keyword">catch&lt;/span> tEx {
        &lt;span class="hljs-keyword">set&lt;/span> tSc = tEx.AsStatus()
    }

    &lt;span class="hljs-keyword">return&lt;/span> tSc
}

&lt;span class="hljs-keyword">ClassMethod&lt;/span> ReceiveMessage(pQueueName &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span>, Output pMessages) &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span>
{
    &lt;span class="hljs-keyword">#dim&lt;/span> tSettings &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.SQSSettings&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tClient &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.SQSClient&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tSc &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span> = &lt;span class="hljs-built_in">$$$OK&lt;/span>
    &lt;span class="hljs-keyword">try&lt;/span> {
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(&lt;span class="hljs-keyword">##class&lt;/span>(AWS.Utils).GetCredentials(.tCredentials))
        &lt;span class="hljs-keyword">set&lt;/span> tSettings = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.SQSSettings&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.accessKey = tCredentials(&lt;span class="hljs-string">"aws_access_key_id"&lt;/span>)
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.secretKey = tCredentials(&lt;span class="hljs-string">"aws_secret_access_key"&lt;/span>)
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.sessionToken = tCredentials(&lt;span class="hljs-string">"aws_session_token"&lt;/span>)
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.region = &lt;span class="hljs-string">"eu-central-1"&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tClient = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.Client&lt;/span>).CreateSQSClient(tSettings.ToJSON(),.tSc)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tSc)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.ReceiveMessage(pQueueName, .pMessages))

    }
    &lt;span class="hljs-keyword">catch&lt;/span> tEx {
        &lt;span class="hljs-keyword">set&lt;/span> tSc = tEx.AsStatus()
    }

    &lt;span class="hljs-keyword">return&lt;/span> tSc
}

&lt;span class="hljs-keyword">ClassMethod&lt;/span> DeleteMessage(pQueueName &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span>, pReceiptHandle &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span>) &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span>
{
    &lt;span class="hljs-keyword">#dim&lt;/span> tSettings &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.SQSSettings&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tClient &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.SQSClient&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tSc &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span> = &lt;span class="hljs-built_in">$$$OK&lt;/span>
    &lt;span class="hljs-keyword">try&lt;/span> {
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(&lt;span class="hljs-keyword">##class&lt;/span>(AWS.Utils).GetCredentials(.tCredentials))
        &lt;span class="hljs-keyword">set&lt;/span> tSettings = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.SQSSettings&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.accessKey = tCredentials(&lt;span class="hljs-string">"aws_access_key_id"&lt;/span>)
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.secretKey = tCredentials(&lt;span class="hljs-string">"aws_secret_access_key"&lt;/span>)
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.sessionToken = tCredentials(&lt;span class="hljs-string">"aws_session_token"&lt;/span>)
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.region = &lt;span class="hljs-string">"eu-central-1"&lt;/span>
                &lt;span class="hljs-keyword">set&lt;/span> tClient = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.Client&lt;/span>).CreateSQSClient(tSettings.ToJSON(),.tSc)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tSc)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.DeleteMessage(pQueueName, pReceiptHandle))

    }
    &lt;span class="hljs-keyword">catch&lt;/span> tEx {
        &lt;span class="hljs-keyword">set&lt;/span> tSc = tEx.AsStatus()
    }

    &lt;span class="hljs-keyword">return&lt;/span> tSc
}

&lt;span class="hljs-keyword">ClassMethod&lt;/span> CreateQueue(pQueueName &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span>) &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span>
{
    &lt;span class="hljs-keyword">#dim&lt;/span> tSettings &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.SQSSettings&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tClient &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.SQSClient&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tSQSSettings &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.SQSQueueSettings&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tSc &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span> = &lt;span class="hljs-built_in">$$$OK&lt;/span>
    &lt;span class="hljs-keyword">try&lt;/span> {
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(&lt;span class="hljs-keyword">##class&lt;/span>(AWS.Utils).GetCredentials(.tCredentials))
        &lt;span class="hljs-keyword">set&lt;/span> tSettings = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.SQSSettings&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.accessKey = tCredentials(&lt;span class="hljs-string">"aws_access_key_id"&lt;/span>)
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.secretKey = tCredentials(&lt;span class="hljs-string">"aws_secret_access_key"&lt;/span>)
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.sessionToken = tCredentials(&lt;span class="hljs-string">"aws_session_token"&lt;/span>)
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.region = &lt;span class="hljs-string">"eu-central-1"&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tClient = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.Client&lt;/span>).CreateSQSClient(tSettings.ToJSON(),.tSc)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tSc)

        &lt;span class="hljs-keyword">set&lt;/span> tSQSSettings = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.SQSQueueSettings&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()

        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.CreateQueue(pQueueName,tSQSSettings))


    }
    &lt;span class="hljs-keyword">catch&lt;/span> tEx {
        &lt;span class="hljs-keyword">set&lt;/span> tSc = tEx.AsStatus()
    }

    &lt;span class="hljs-keyword">return&lt;/span> tSc
}

&lt;span class="hljs-keyword">ClassMethod&lt;/span> DeleteQueue(pQueueName &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%String&lt;/span>) &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span>
{
    &lt;span class="hljs-keyword">#dim&lt;/span> tSettings &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.SQSSettings&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tClient &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.SQSClient&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tSQSSettings &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%External.Messaging.SQSQueueSettings&lt;/span>
    &lt;span class="hljs-keyword">#dim&lt;/span> tSc &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span> = &lt;span class="hljs-built_in">$$$OK&lt;/span>
    &lt;span class="hljs-keyword">try&lt;/span> {
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(&lt;span class="hljs-keyword">##class&lt;/span>(AWS.Utils).GetCredentials(.tCredentials))
        &lt;span class="hljs-keyword">set&lt;/span> tSettings = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.SQSSettings&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.accessKey = tCredentials(&lt;span class="hljs-string">"aws_access_key_id"&lt;/span>)
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.secretKey = tCredentials(&lt;span class="hljs-string">"aws_secret_access_key"&lt;/span>)
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.sessionToken = tCredentials(&lt;span class="hljs-string">"aws_session_token"&lt;/span>)
        &lt;span class="hljs-keyword">set&lt;/span> tSettings.region = &lt;span class="hljs-string">"eu-central-1"&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tClient = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%External.Messaging.Client&lt;/span>).CreateSQSClient(tSettings.ToJSON(),.tSc)
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tSc)

        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tClient.DeleteQueue(pQueueName))


    }
    &lt;span class="hljs-keyword">catch&lt;/span> tEx {
        &lt;span class="hljs-keyword">set&lt;/span> tSc = tEx.AsStatus()
    }

    &lt;span class="hljs-keyword">return&lt;/span> tSc
}

}

Ele contém métodos para criar e excluir filas, além de enviar e receber mensagens de uma fila.

Um dos principais pontos aqui é como autenticar. Não queria colocar minhas credenciais no meu código. Por isso, criei um método de ajuda para recuperar minhas credenciais no meu arquivo local e retornar como uma array subscrita para usar nos meus métodos da API:

&lt;span class="hljs-keyword">ClassMethod&lt;/span> GetCredentials(Output pCredentials) &lt;span class="hljs-keyword">As&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span>
{
    &lt;span class="hljs-keyword">#dim&lt;/span> tSc &lt;span class="hljs-keyword">as&lt;/span> &lt;span class="hljs-built_in">%Status&lt;/span> = &lt;span class="hljs-built_in">$$$OK&lt;/span>
    &lt;span class="hljs-keyword">set&lt;/span> tFilename = &lt;span class="hljs-string">"/dur/.aws/credentials"&lt;/span>
    &lt;span class="hljs-keyword">try&lt;/span> {
        &lt;span class="hljs-keyword">set&lt;/span> tCredentialsFile = &lt;span class="hljs-keyword">##class&lt;/span>(&lt;span class="hljs-built_in">%Stream.FileCharacter&lt;/span>).&lt;span class="hljs-built_in">%New&lt;/span>()
        &lt;span class="hljs-built_in">$$$ThrowOnError&lt;/span>(tCredentialsFile.LinkToFile(tFilename))
        &lt;span class="hljs-comment">// first read the header&lt;/span>
        &lt;span class="hljs-keyword">set&lt;/span> tBuffer = tCredentialsFile.ReadLine()
        &lt;span class="hljs-keyword">for&lt;/span> i=&lt;span class="hljs-number">1&lt;/span>:&lt;span class="hljs-number">1&lt;/span>:&lt;span class="hljs-number">3&lt;/span> {
            &lt;span class="hljs-keyword">set&lt;/span> tBuffer = tCredentialsFile.ReadLine()
            &lt;span class="hljs-keyword">set&lt;/span> pCredentials(&lt;span class="hljs-built_in">$piece&lt;/span>(tBuffer,&lt;span class="hljs-string">" ="&lt;/span>,&lt;span class="hljs-number">1&lt;/span>)) = &lt;span class="hljs-built_in">$tr&lt;/span>(&lt;span class="hljs-built_in">$piece&lt;/span>(tBuffer,&lt;span class="hljs-string">"= "&lt;/span>,&lt;span class="hljs-number">2&lt;/span>),&lt;span class="hljs-built_in">$c&lt;/span>(&lt;span class="hljs-number">13&lt;/span>))
        }
    }
    &lt;span class="hljs-keyword">catch&lt;/span> tEx {
        &lt;span class="hljs-keyword">set&lt;/span> tSc = tEx.AsStatus()
    } 

    &lt;span class="hljs-keyword">return&lt;/span> tSc
}

Para concluir este artigo, vamos criar uma fila community na região do AWS "eu-central-1" (Frankfurt, Alemanha).

A fila foi criada com sucesso e está visível no console do AWS para minha conta:

Em seguida, vamos enviar uma mensagem para essa fila:

O método call retorna 1. Portanto, a mensagem foi enviada com êxito.

Por fim, vamos usar o poll na fila do console do AWS:

A mensagem foi enviada para a fila com êxito.

Conclusão

A API de mensagens externas no InterSystems IRIS 2022.1 simplifica bastante a comunicação com as plataformas de streaming de eventos.
Espero que isso tenha sido útil.

0
0 87
Artigo Danusa Calixto · Ago. 11, 2022 12m read

Olá, comunidade,

Este é o terceiro artigo da série sobre a inicialização de instâncias da IRIS com Docker. Desta vez, focaremos no Enterprise Cache Protocol (ECP).

De maneira bastante simplificada, o ECP permite configurar algumas instâncias da IRIS como servidores de aplicação e outras como servidores de dados. As informações técnicas detalhadas podem ser encontradas na documentação oficial.

O objetivo deste artigo é descrever o seguinte:

  • Como programar a inicialização de um servidor de dados e como programar a inicialização de um ou mais servidores de aplicação.
  • Como estabelecer uma conexão criptografada entre os nós com Docker.

Para fazer isso, geralmente, usamos algumas das ferramentas já abordadas nos artigos anteriores sobre Web Gateway e espelhamento (Mirror), que descrevem instrumentos como OpenSSL, envsubst e Config-API.

Requisitos

O ECP não está disponível com a versão da Comunidade da IRIS. Portanto, é necessário o acesso à Central de Suporte (WRC) para fazer o download de uma licença de contêiner e conectar ao registro containers.intersystems.com.

Preparando o sistema

O sistema precisa compartilhar alguns arquivos locais com os contêineres. É necessário criar determinados usuários e grupos para evitar o erro "acesso negado".

sudo useradd --uid 51773 --user-group irisowner
sudo useradd --uid 52773 --user-group irisuser
sudo groupmod --gid 51773 irisowner
sudo groupmod --gid 52773 irisuser

Se você ainda não tem a licença "iris.key", faça o download na WRC e adicione ao diretório do início.

Recupere o repositório de amostra

Todos os arquivos necessários estão disponíveis em um repositório público, exceto a licença "iris.key", então comece por clonar:

git clone https://github.com/lscalese/ecp-with-docker.git
cd ecp-with-docker

Certificados SSL

Para criptografar as comunicações entre os servidores de aplicação e o servidor de dados, precisamos de certificados SSL.
Um script pronto para uso ("gen-certificates.sh") está disponível. No entanto, fique à vontade para modificá-lo, para a consistência das configurações do certificado com sua localização, empresa etc.

Execute:

sh ./gen-certificates.sh

Os certificados gerados estão agora no diretório "./certificates".

ArquivoContêinerDescrição
./certificates/CA_Server.cerServidor de aplicação e servidor de dadosCertificado do servidor da autoridade
./certificates/app_server.cerServidor de aplicaçãoCertificado para a instância do servidor de aplicação da IRIS
./certificates/app_server.keyServidor de aplicaçãoChave privada relacionada
./certificates/data_server.cerServidor de dadosCertificado para a instância do servidor de dados da IRIS
./certificates/data_server.keyServidor de dadosChave privada relacionada

Construa a imagem

Primeiro, faça login no registro docker da InterSystems. A imagem de base será baixada do registro durante a construção:

docker login -u="YourWRCLogin" -p="YourICRToken" containers.intersystems.com

Se você não sabe seu token, faça login em https://containers.intersystems.com/ com a conta da WRC.

Durante essa construção, adicionaremos alguns utilitários de software à imagem de base da IRIS:

  • gettext-base: permitirá substituir as variáveis do ambiente nos arquivos de configuração com o comando "envsubst".
  • iputils-arping: é necessário se quisermos espelhar o servidor de dados.
  • ZPM: gerente de pacotes ObjectScript.

Dockerfile:

ARG IMAGE=containers.intersystems.com/intersystems/iris:2022.2.0.281.0

# Não é necessário fazer o download da imagem do WRC. Ela será extraída do ICR no momento da construção.

FROM $IMAGE

USER root

# Installe iputils-arping para ter um comando de arping.  É necessário para configurar o IP Virtual.
# Baixe a última versão do ZPM (incluso somente na edição da comunidade).
RUN apt-get update && apt-get install iputils-arping gettext-base && \
   rm -rf /var/lib/apt/lists/*

USER ${ISC_PACKAGE_MGRUSER}

WORKDIR /home/irisowner/demo

RUN --mount=type=bind,src=.,dst=. \
   iris start IRIS && \
       iris session IRIS < iris.script && \
   iris stop IRIS quietly

Não há nada especial neste Dockerfile, exceto a última linha. Ela configura a instância do servidor de dados da IRIS para aceitar até 3 servidores de aplicação. Atenção: essa configuração exige a reinicialização da IRIS. Atribuímos o valor deste parâmetro durante a construção para evitar a reinicialização do script depois.

Inicie a construção:

docker-compose build –no-cache

Arquivo de configuração

Para a configuração das instâncias da IRIS (servidores de aplicação e dados), usamos o formato de arquivo SON config-api. Você verá que esses arquivos contêm variáveis de ambiente "${variable_name}". Os valores são definidos nas seções do "ambiente" do arquivo "docker-compose.yml" que veremos ainda neste documento. Essas variáveis serão substituídas logo antes do carregamento dos arquivos usando o utilitário "envsubst".

Servidor de dados

Para o servidor de dados, vamos:

  • Permitir o serviço ECP e definir a lista de clientes autorizados (servidores de aplicação).
  • Criar a configuração "SSL %ECPServer" necessária para a criptografia de comunicações.
  • Criar uma base de dados "myappdata". Ela será usada como uma base de dados remota dos servidores de aplicação.

(data-serer.json)[https://github.com/lscalese/ecp-with-docker/blob/master/config-files/data-server.json]

{
   "Security.Services" : {
       "%Service_ECP" : {
           "Enabled" : true,
           "ClientSystems":"${CLIENT_SYSTEMS}",
           "AutheEnabled":"1024"
       }
   },
   "Security.SSLConfigs": {
       "%ECPServer": {
           "CAFile": "${CA_ROOT}",
           "CertificateFile": "${CA_SERVER}",
           "Name": "%ECPServer",
           "PrivateKeyFile": "${CA_PRIVATE_KEY}",
           "Type": "1",
           "VerifyPeer": 3
       }
   },
   "Security.System": {
       "SSLECPServer":1
   },
   "SYS.Databases":{
       "/usr/irissys/mgr/myappdata/" : {}
   },
   "Databases":{
       "myappdata" : {
           "Directory" : "/usr/irissys/mgr/myappdata/"
       }
   }
}

Esse arquivo de configuração é carregado na inicialização do contêiner do servidor de dados pelo script "init_datasrv.sh". Todos os servidores de aplicação conectados ao servidor de dados precisam ser confiáveis. Esse script validará automaticamente todas as conexões dentro de 100 segundos para limitar as ações manuais no portal de administração. É claro que isso pode ser melhorado para aprimorar a segurança.

Servidor de aplicação

Para os servidores de aplicação, vamos:

  • Ativar o serviço ECP.
  • Criar a configuração do SLL "%ECPClient" necessária para a criptografia da comunicação.
  • Configurar as informações da conexão para o servidor de dados.
  • Criar a configuração da base de dados remota "myappdata".
  • Criar um mapeamento global "demo.*" no espaço de nome "USER" para a base de dados "myappdata". Isso permitirá o teste da operação do ECP mais tarde.

app-server.json:

{
   "Security.Services" : {
       "%Service_ECP" : {
           "Enabled" : true
       }
   },
   "Security.SSLConfigs": {
       "%ECPClient": {
           "CAFile": "${CA_ROOT}",
           "CertificateFile": "${CA_CLIENT}",
           "Name": "%ECPClient",
           "PrivateKeyFile": "${CA_PRIVATE_KEY}",
           "Type": "0"
       }
   },
   "ECPServers" : {
       "${DATASERVER_NAME}" : {
           "Name" : "${DATASERVER_NAME}",
           "Address" : "${DATASERVER_IP}",
           "Port" : "${DATASERVER_PORT}",
           "SSLConfig" : "1"
       }
   },
   "Databases": {
       "myappdata" : {
           "Directory" : "/usr/irissys/mgr/myappdata/",
           "Name" : "${REMOTE_DB_NAME}",
           "Server" : "${DATASERVER_NAME}"
       }
   },
   "MapGlobals":{
       "USER": [{
           "Name" : "demo.*",
           "Database" : "myappdata"
       }]
   }
}

O arquivo de configuração é carregado na inicialização de um contêiner do servidor de aplicação pelo script "init_appsrv.sh".

Inicializando os contêineres

Agora, podemos inicializar os contêineres:

  • 2 servidores de aplicação.
  • 1 servidor de dados.

Para fazer isso execute:

docker-compose up –scale ecp-demo-app-server=2

Veja mais detalhes no arquivo docker-compose:

# As variáveis são definidas no arquivo .env
# para mostrar o arquivo docker-compose revolvido, execute
# docker-compose config

version: '3.7'

services:
  ecp-demo-data-server:
   build: .
   image: ecp-demo
   container_name: ecp-demo-data-server
   hostname: data-server
   networks:
     app_net:
   environment:
     # Lista dos clientes ECP permitidos (servidor de aplicação). 
     - CLIENT_SYSTEMS=ecp-with-docker_ecp-demo-app-server_1;ecp-with-docker_ecp-demo-app-server_2;ecp-with-docker_ecp-demo-app-server_3
     # Path authority server certificate
     - CA_ROOT=/certificates/CA_Server.cer
     # Path to data server certificate
     - CA_SERVER=/certificates/data_server.cer
     # Path to private key of the data server certificate
     - CA_PRIVATE_KEY=/certificates/data_server.key
     # Path to Config-API file to initiliaze this IRIS instance
     - IRIS_CONFIGAPI_FILE=/home/irisowner/demo/data-server.json
   ports:
     - "81:52773"
   volumes:
     # Script após o início - inicialização do servidor de dados.
     - ./init_datasrv.sh:/home/irisowner/demo/init_datasrv.sh
     # Montar certificados (ver gen-certificates.sh para gerar certificados)
     - ./certificates/app_server.cer:/certificates/data_server.cer
     - ./certificates/app_server.key:/certificates/data_server.key
     - ./certificates/CA_Server.cer:/certificates/CA_Server.cer
     # Montar arquivo de configuração
     - ./config-files/data-server.json:/home/irisowner/demo/data-server.json
     # Licença da IRIS
     - ~/iris.key:/usr/irissys/mgr/iris.key
   command: -a /home/irisowner/demo/init_datasrv.sh


 ecp-demo-app-server:
   image: ecp-demo
   networks:
     app_net:
   environment:
     # Nome do host ou ID do servidor de dados.
     - DATASERVER_IP=data-server
     - DATASERVER_NAME=data-server
     - DATASERVER_PORT=1972
     # Caminho do certificado do servidor de autoridade
     - CA_ROOT=/certificates/CA_Server.cer
     - CA_CLIENT=/certificates/app_server.cer
     - CA_PRIVATE_KEY=/certificates/app_server.key
     - IRIS_CONFIGAPI_FILE=/home/irisowner/demo/app-server.json
   ports:
     - 52773
   volumes:
     # Após o início do script - inicialização do servidor de aplicação.
     - ./init_appsrv.sh:/home/irisowner/demo/init_appsrv.sh
     # Montar certificados
     - ./certificates/CA_Server.cer:/certificates/CA_Server.cer
     # Caminho para a chave privada do certificado do servidor de dados
     - ./certificates/app_server.cer:/certificates/app_server.cer
     # Caminho para a chave privada do certificado do servidor de dados
     - ./certificates/app_server.key:/certificates/app_server.key
     # Caminho para o arquivo Config-API inicializar a instância da IRIS
     - ./config-files/app-server.json:/home/irisowner/demo/app-server.json
     # Licença da IRIS
     - ~/iris.key:/usr/irissys/mgr/iris.key
   command: -a /home/irisowner/demo/init_appsrv.sh
 networks:
 app_net:
   ipam:
     driver: default
     config:
       # A variável APP_NET_SUBNET é definida no arquivo .env
       - subnet: "${APP_NET_SUBNET}"

Vamos testar!

Acesso ao portal de administração do servidor de dados

Os contêineres foram inicializados. Vamos conferir o status do servidor de dados.
A porta 52773 é mapeada para a porta local 81, então você pode acessar por este endereço: http://localhost:81/csp/sys/utilhome.csp

Entre com o login e a senha padrão e acesse System -> Configuration -> ECP Params. Clique em "ECP Application Servers". Se tudo estiver funcionando, você verá 2 servidores de aplicação com o status "Normal". A estrutura do nome do cliente é "nome do servidor de dados":"hostname do servidor de aplicação":"nome da instância IRIS". No nosso caso, não configuramos os hostnames do servidor de aplicação, então temos hostnames gerados.

lista de servidores de app

Acessando o portal de administração dos servidores de aplicação

Para se conectar ao portal de administração dos servidores de aplicação, primeiro, você precisa ter o número da porta. Já que usamos a opção "--scale", não conseguimos definir as portas no arquivo docker-compose. Então, precisamos recuperá-las com o comando docker ps:

docker ps -a
CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS                      PORTS                                                                                     NAMES
a1844f38939f   ecp-demo   "/tini -- /iris-main…"   25 minutes ago   Up 25 minutes (unhealthy)   1972/tcp, 2188/tcp, 53773/tcp, 54773/tcp, 0.0.0.0:81->52773/tcp, :::81->52773/tcp         ecp-demo-data-server
4fa9623be1f8   ecp-demo   "/tini -- /iris-main…"   25 minutes ago   Up 25 minutes (unhealthy)   1972/tcp, 2188/tcp, 53773/tcp, 54773/tcp, 0.0.0.0:49170->52773/tcp, :::49170->52773/tcp   ecp-with-docker_ecp-demo-app-server_1
ecff03aa62b6   ecp-demo   "/tini -- /iris-main…"   25 minutes ago   Up 25 minutes (unhealthy)   1972/tcp, 2188/tcp, 53773/tcp, 54773/tcp, 0.0.0.0:49169->52773/tcp, :::49169->52773/tcp   ecp-with-docker_ecp-demo-app-server_2

Neste exemplo, as portas são:

servidor de dados

Teste de leitura/escrita na base de dados remota

Vamos realizar alguns testes de leitura/escrita no terminal.
Abra um terminal IRIS no primeiro servidor de aplicação:

docker exec -it ecp-with-docker_ecp-demo-app-server_1 iris session iris
Set ^demo.ecp=$zdt($h,3,1) _ “ write from the first application server.”

Agora, abra um terminal no segundo servidor de aplicação:

docker exec -it ecp-with-docker_ecp-demo-app-server_2 iris session iris
Set ^demo.ecp(2)=$zdt($h,3,1) _ " write from the second application server."
zwrite ^demo.ecp

Você deverá ver as respostas dos dois servidores:

^demo.ecp(1)="2022-07-05 23:05:10 write from the first application server."
^demo.ecp(2)="2022-07-05 23:07:44 write from the second application server."

Por fim, abra um terminal IRIS no servidor de dados e realize a leitura do global demo.ecp:

docker exec -it ecp-demo-data-server iris session iris
zwrite ^["^^/usr/irissys/mgr/myappdata/"]demo.ecp

^["^^/usr/irissys/mgr/myappdata/"]demo.ecp(1)="2022-07-05 23:05:10 write from the first application server."
^["^^/usr/irissys/mgr/myappdata/"]demo.ecp(2)="2022-07-05 23:07:44 write from the second application server."

Isso é tudo por hoje. Espero que tenha gostado deste artigo. Não hesite em deixar seus comentários.

0
0 99
Artigo Eduard Lebedyuk · Nov. 22, 2021 8m read

Todo mundo tem um ambiente de teste.

Algumas pessoas têm a sorte de ter um ambiente totalmente separado para executar a produção.

-- Desconhecido

.

Nesta série de artigos, gostaria de apresentar e discutir várias abordagens possíveis para o desenvolvimento de software com as tecnologias InterSystems e GitLab. Vou cobrir tópicos como:

  • Git Básico
  • Fluxo Git (processo de desenvolvimento)
  • Instalação do GitLab
  • Fluxo de Trabalho do GitLab
  • GitLab CI/CD
  • CI/CD com contêineres

Esta primeira parte trata do pilar do desenvolvimento de software moderno - sistema de controle de versão Git e vários fluxos Git.

Git Básico

Embora o tópico principal que iremos discutir seja o desenvolvimento de software em geral e como o GitLab pode nos capacitar nesse esforço, o Git, ou melhor, os vários conceitos de alto nível subjacentes no design do Git, são importantes para o melhor entendimento de conceitos posteriores.

Dito isso, o Git é um sistema de controle de versão, baseado nessas ideias (existem muitas outras, essas são as mais importantes):

  • Desenvolvimento não linear significa que enquanto nosso software é lançado consequentemente da versão 1 para a 2 para a 3, sob a mesa a mudança da versão 1 para a 2 é feita em paralelo - vários desenvolvedores desenvolvem uma série de recursos/correções de bugs simultaneamente.
  • Desenvolvimento distribuído significa que o desenvolvedor é independente de um servidor central ou de outros desenvolvedores e pode desenvolver facilmente em seu próprio ambiente.
  • Fusão - as duas ideias anteriores nos levam à situação em que muitas versões diferentes da verdade existem simultaneamente e precisamos uni-las de volta em um estado completo.

Agora, não estou dizendo que Git inventou esses conceitos. Não. Em vez disso, o Git os tornou fáceis e populares e isso, juntamente com várias inovações relacionadas, ou seja,  infraestrutura como código/conteinerização mudou o desenvolvimento de software.

Termos básicos do Git

Repositório é um projeto que armazena dados e metainformações sobre os dados.

  • O repositório "físico" é um diretório em um disco.
  • O repositório armazena arquivos e diretórios.
  • O repositório também armazena um histórico completo de alterações para cada arquivo.

O repositório pode ser armazenado:

  • Localmente, em seu próprio computador
  • Remotamente em um servidor remoto

Mas não há nenhuma diferença particular entre repositórios locais e remotos do ponto de vista do git.

Commit é um estado fixo do repositório. Obviamente, se cada commit armazenasse o estado completo do repositório, nosso repositório cresceria muito rapidamente. É por isso que um commit armazena um diff que é uma diferença entre o commit atual e seu commit pai.

Commits diferentes podem ter um número diferente de pais:

  • 0 - o primeiro commit no repositório não tem pais.
  • 1 - conforme o habitual - nosso commit mudou algo no repositório como era durante o commit pai
  • 2 - quando temos dois estados diferentes do repositório, podemos uni-los em um novo estado. E esse estado e esse commit teriam 2 pais.
  • 2 - pode acontecer quando unimos mais de 2 estados diferentes do repositório em um novo estado. Não seria particularmente relevante para nossa discussão, mas existe.

Agora, para um pai, cada commit diferente é chamado de commit filho. Cada commit pai pode ter qualquer número de commits filhos.

Branch é uma referência (ou ponteiro) para um commit.  Veja como funciona:

Nesta imagem, podemos ver o repositório com dois commits (círculos cinza), o segundo é o head do branch master. Depois de adicionar mais commits, nosso repositório começa a ficar assim:

Esse é o caso mais simples. Um desenvolvedor trabalha em uma mudança de cada vez. No entanto, normalmente, existem muitos desenvolvedores trabalhando simultaneamente em diferentes recursos e precisamos de uma árvore de commit para mostrar o que está acontecendo em nosso repositório.

Árvore de commit

Vamos começar do mesmo ponto de partida. Aqui está o repositório com dois commits:

Mas agora, dois desenvolvedores estão trabalhando ao mesmo tempo e para não interferir um no outro, eles trabalham em branches separados:

Depois de um tempo, eles precisam unir as alterações feitas e para isso eles criam uma solicitação de mesclagem (merge) (também chamada de pull request) - que é exatamente o que parece - é uma solicitação para unir dois estados diferentes do repositório (no nosso caso, queremos mesclar o develop branch no master branch) em um novo estado. Depois de ser devidamente revisado e aprovado, nosso repositório fica assim:

E o desenvolvimento continua:

Resumo - Git Básico

Conceitos principais:

  • Git é um sistema de controle de versão distribuído não linear.
  • Repositório armazena dados e metainformações sobre os dados.
  • Commit é um estado fixo do repositório.
  • Branch é uma referência para um commit. 
  • Solicitação de mesclagem (também chamada de pull request) - é uma solicitação para unir dois estados diferentes do repositório em um novo estado.

Se você quiser ler mais sobre o Git, existem livros disponíveis.

Fluxos Git

Agora que o leitor está familiarizado com os termos e conceitos básicos do Git, vamos falar sobre como a parte do desenvolvimento do ciclo de vida do software pode ser gerenciada usando o Git.  Existem várias práticas (chamadas  de fluxos) que descrevem o processo de desenvolvimento usando Git, mas vamos falar sobre duas delas:

  • Fluxo do GitHub
  • Fluxo do GitLab

Fluxo do GitHub

O fluxo do GitHub é tão fácil quanto parece. Aqui está:

  1. Crie um branch (ramificação) do repositório.
  2. Commit suas alterações para seu novo branch
  3. Envie um pull request do seu branch com as alterações propostas para iniciar uma discussão.
  4. Commit mais alterações em seu branch conforme necessário. Seu pull request será atualizado automaticamente.
  5. Mescle o pull request assim que o branch estiver pronto para ser mesclado.

E existem várias regras que devemos seguir:

  • master branch é sempre implantável (e funcionando!)

  • Não há desenvolvimento indo diretamente para o master branch

  • O desenvolvimento está acontecendo nos branches de recursos

  • master == ambiente** de produção*

  • Você precisa implantar na produção o mais rápido possível

    • Não confunda com "Produções Ensemble", aqui "Produção" significa SISTEMA EM PRODUÇÃO.

** Ambiente é um local configurado onde seu código é executado - pode ser um servidor, uma VM, até mesmo um contêiner.

Veja como funciona:

Você pode ler mais sobre o fluxo do GitHub aqui. Também há um guia ilustrado.

O fluxo do GitHub é bom para pequenos projetos e para testes se você está começando com os fluxos do Git. No entanto, o GitHub o usa, portanto, também pode ser viável em projetos grandes.

Fluxo do GitLab

Se você não estiver pronto para implantar na produção imediatamente, o fluxo do GitLab oferece um fluxo do GitHub + ambientes. É assim que funciona - você desenvolve em branches de recursos, como acima, mescla (merge) no master, como acima, mas aqui está uma diferença: o master é igual apenas no ambiente de teste. Além disso, você tem "Branches de ambiente" que estão vinculados a vários outros ambientes que você possa ter.

Normalmente, existem três ambientes (você pode criar mais se precisar):

  • Ambiente de teste == master branch
  • Ambiente de pré-produção == preprod branch
  • Ambiente de produção == prod branch

O código que chega em um dos branches do ambiente deve ser movido para o ambiente correspondente imediatamente, isso pode ser feito:

  • Automaticamente (cobriremos isso nas partes 2 e 3)
  • Parcialmente automático (igual ao automaticamente, exceto que um botão que autoriza a implantação deve ser pressionado)
  • Manualmente

Todo o processo é assim:

  1. O recurso é desenvolvido no branch de recursos.
  2. O branch de recurso é revisado e mesclado no master branch.
  3. Depois de um tempo (vários recursos mesclados), o master é mesclado com o preprod
  4. Depois de um tempo (teste do usuário, etc.), o preprod é mesclado com o prod  
  5. Enquanto estávamos mesclando e testando, vários novos recursos foram desenvolvidos e mesclados no master, então vá para parte 3.

Veja como funciona:

Você pode ler mais sobre o fluxo do GitLab aqui.

Conclusão

  • Git ****é um sistema de controle de versão distribuído não linear.
  • O fluxo Git pode ser usado como uma diretriz para o ciclo de desenvolvimento de software; existem vários que você pode escolher.

Links

Questões para discussão

  • Você usa um fluxo git? Qual?
  • Quantos ambientes você tem para um projeto padrão?

O que vem a seguir

Na próxima parte, iremos:

  • Instalar o GitLab.
  • Falar sobre alguns ajustes recomendados.
  • Discutir o fluxo de trabalho do GitLab (não deve ser confundido com o fluxo do GitLab).

Fique ligado.

0
0 311
Artigo Alessandro Marin · Nov. 26, 2020 3m read

Estou planejando implementar a Inteligência de Negócio (BI) com base nos dados de minhas instâncias. Qual é a melhor maneira de configurar meus bancos de dados e ambiente para usar o DeepSee?

Este tutorial aborda essa questão mostrando três exemplos de arquitetura para DeepSee. Começaremos com um modelo de arquitetura básico e destacaremos suas limitações. O modelo subsequente é recomendado para aplicações de Inteligência de Negócio (BI) de complexidade intermediária e deve ser suficiente para a maioria dos casos de uso. Terminaremos este tutorial descrevendo como aumentar a flexibilidade da arquitetura para gerenciar implementações avançadas.

Cada exemplo neste tutorial apresenta novos bancos de dados e mapeamentos globais, junto com uma discussão sobre por que e quando eles devem ser configurados. Ao construir a arquitetura, os benefícios fornecidos pelos exemplos mais flexíveis serão destacados.

Antes de começar

Servidores primários e analíticos

Para tornar os dados altamente disponíveis, a InterSystems geralmente recomenda usar as soluções de espelhamento ou sombreamento e então basear a implementação DeepSee no servidor espelho/sombra. A máquina que hospeda a cópia original dos dados é chamada de servidor Primário, enquanto as máquinas que hospedam cópias dos dados e as aplicações de Inteligência de Negócio (BI) costumam ser chamados de servidores Analíticos (ou, às vezes, de Relatórios)

Ter servidores primários e analíticos é muito importante, o principal motivo é evitar problemas de desempenho em qualquer um dos servidores. Verifique a documentação sobre a Arquitetura Recomendada.

Dados e código da aplicação

Armazenar dados de origem e código no mesmo banco de dados geralmente funciona bem apenas para aplicações de pequena escala. Para aplicações mais extensas, é recomendado armazenar os dados de origem e código em dois bancos de dados dedicados, o que permite compartilhar o código com todos os namespaces onde o DeepSee é executado, mantendo os dados separados. O banco de dados de dados de origem deve ser espelhado no servidor de produção. Este banco de dados pode ser somente leitura ou leitura-gravação. É recomendável manter o registro do diário habilitado para este banco de dados.

As classes de origem e as aplicações personalizados devem ser armazenados em um banco de dados dedicado nos servidores de produção e analítico. Observe que esses dois bancos de dados para o código-fonte não precisam estar sincronizados ou mesmo rodar a mesma versão do Caché. Normalmente, o registro no diário não é necessário, desde que o backup do código seja feito regularmente em outro lugar.

Neste tutorial teremos a seguinte configuração. O namespace do APP no servidor analítico tem o APP-DATA e o APP-CODE como bancos de dados padrão. O banco de dados APP-DATA tem acesso aos dados (a classe da tabela de origem e seus fatos) no banco de dados de dados de origem no Primário. O banco de dados APP-CODE armazena o código Caché (arquivos .cls e .INT) e outros códigos personalizados. Essa separação de dados e código é uma arquitetura típica e permite ao usuário, por exemplo, implantar com eficiência o código DeepSee e a aplicação personalizada.

Executar DeepSee em diferentes namespaces

As implementações de Inteligência de Negócio (BI) usando DeepSee geralmente são executadas a partir de namespaces diferentes. Nesta postagem, mostraremos como configurar um único namespace de APP, mas o mesmo procedimento se aplica a todos os namespaces onde a aplicação de inteligência de negócio é executada.

Documentação

Recomenda-se familiarizar-se com a página de documentação Executando a Configuração Inicial. Esta página inclui a configuração de aplicações web, como colocar DeepSee globais em bancos de dados separados e uma lista de mapeamentos alternativos para DeepSee globais.


Na segunda parte desta série mostraremos com a implementação de um modelo básico de arquitetura

1
0 261